Skip to content

Commit

Permalink
TACoApplication: available commitment duration tied to two options
Browse files Browse the repository at this point in the history
  • Loading branch information
vzotova committed Sep 6, 2023
1 parent 5f46c5c commit e8abe65
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 34 deletions.
27 changes: 19 additions & 8 deletions contracts/contracts/TACoApplication.sol
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,12 @@ contract TACoApplication is IApplication, ITACoChildToRoot, OwnableUpgradeable {
uint64 endCommitment;
}

uint64 public constant MINIMUM_COMMITMENT = 365 days;

uint96 public immutable minimumAuthorization;
uint256 public immutable minOperatorSeconds;
uint256 public immutable rewardDuration;
uint256 public immutable deauthorizationDuration;
uint64 public immutable commitmentDurationOption1;
uint64 public immutable commitmentDurationOption2;

IStaking public immutable tStaking;
IERC20 public immutable token;
Expand All @@ -179,19 +179,26 @@ 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
*/
constructor(
IERC20 _token,
IStaking _tStaking,
uint96 _minimumAuthorization,
uint256 _minOperatorSeconds,
uint256 _rewardDuration,
uint256 _deauthorizationDuration
uint256 _deauthorizationDuration,
uint64 _commitmentDurationOption1,
uint64 _commitmentDurationOption2
) {
require(
_rewardDuration != 0 &&
_tStaking.authorizedStake(address(this), address(this)) == 0 &&
_token.totalSupply() > 0,
_token.totalSupply() > 0 &&
_commitmentDurationOption1 > 0 &&
_commitmentDurationOption2 > 0 &&
_commitmentDurationOption1 != _commitmentDurationOption2,
"Wrong input parameters"
);
rewardDuration = _rewardDuration;
Expand All @@ -200,6 +207,8 @@ contract TACoApplication is IApplication, ITACoChildToRoot, OwnableUpgradeable {
token = _token;
tStaking = _tStaking;
minOperatorSeconds = _minOperatorSeconds;
commitmentDurationOption1 = _commitmentDurationOption1;
commitmentDurationOption2 = _commitmentDurationOption2;
_disableInitializers();
}

Expand Down Expand Up @@ -535,17 +544,19 @@ contract TACoApplication is IApplication, ITACoChildToRoot, OwnableUpgradeable {
/**
* @notice Make a commitment to not request authorization decrease for specified duration
* @param _stakingProvider Staking provider address
* @param _duration Duration of commitment
* @param _commitmentDurationOption2 If set to true then will be used second option of commitment duration. Otherwise first
*/
function makeCommitment(
address _stakingProvider,
uint64 _duration
bool _commitmentDurationOption2
) external onlyOwnerOrStakingProvider(_stakingProvider) {
require(_duration >= MINIMUM_COMMITMENT, "Duration must be greater than minimum");
uint64 duration = !_commitmentDurationOption2
? commitmentDurationOption1
: commitmentDurationOption2;
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) + duration;
emit CommitmentMade(_stakingProvider, info.endCommitment);
}

Expand Down
1 change: 1 addition & 0 deletions contracts/contracts/coordination/TACoChildApplication.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ contract TACoChildApplication is ITACoRootToChild, ITACoChildApplication, Initia
"Address for root application must be specified"
);
rootApplication = _rootApplication;
_disableInitializers();
}

/**
Expand Down
4 changes: 4 additions & 0 deletions tests/application/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
REWARD_DURATION = 60 * 60 * 24 * 7 # one week in seconds
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

DEPENDENCY = project.dependencies["openzeppelin"]["4.9.1"]

Expand Down Expand Up @@ -75,6 +77,8 @@ def taco_application(project, creator, token, threshold_staking):
MIN_OPERATOR_SECONDS,
REWARD_DURATION,
DEAUTHORIZATION_DURATION,
COMMITMENT_DURATION_1,
COMMITMENT_DURATION_2,
)

proxy_admin = DEPENDENCY.ProxyAdmin.deploy(sender=creator)
Expand Down
66 changes: 40 additions & 26 deletions tests/application/test_authorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,17 +412,15 @@ def test_authorization_decrease_request(
chain.pending_timestamp += deauthorization_duration
taco_application.finishAuthorizationDecrease(staking_provider, sender=creator)
threshold_staking.authorizationIncreased(staking_provider, 0, value, sender=creator)
minimum_commitment_duration = taco_application.MINIMUM_COMMITMENT()
taco_application.makeCommitment(
staking_provider, minimum_commitment_duration, sender=staking_provider
)
commitment_duration = taco_application.commitmentDurationOption1()
taco_application.makeCommitment(staking_provider, False, sender=staking_provider)

# Commitment is still active
with ape.reverts("Can't request deauthorization before end of commitment"):
threshold_staking.authorizationDecreaseRequested(
staking_provider, value, value // 2, sender=creator
)
chain.pending_timestamp += minimum_commitment_duration
chain.pending_timestamp += commitment_duration

# Now decrease can be requested
threshold_staking.authorizationDecreaseRequested(
Expand Down Expand Up @@ -692,48 +690,47 @@ def test_commitment(accounts, threshold_staking, taco_application, chain):
Tests for authorization method: makeCommitment
"""

creator, staking_provider = accounts[0:2]
creator, staking_provider, another_staking_provider = accounts[0:3]
deauthorization_duration = DEAUTHORIZATION_DURATION
minimum_authorization = MIN_AUTHORIZATION
value = 2 * minimum_authorization
minimum_commitment_duration = taco_application.MINIMUM_COMMITMENT()
commitment_duration_1 = taco_application.commitmentDurationOption1()
commitment_duration_2 = taco_application.commitmentDurationOption2()

# Commitment can be made only for authorized staking provider
with ape.reverts("Not owner or provider"):
taco_application.makeCommitment(
staking_provider, minimum_commitment_duration, sender=staking_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)

# Prepare staking provider
threshold_staking.authorizationIncreased(staking_provider, 0, value, sender=creator)

# Commitment can't be made for duration less than minimum
with ape.reverts("Duration must be greater than minimum"):
taco_application.makeCommitment(
staking_provider, minimum_commitment_duration - 1, sender=staking_provider
)

# Begin deauthorization
threshold_staking.authorizationDecreaseRequested(
staking_provider, value, minimum_authorization, sender=creator
)

# Commitment can't be made during deauthorization
with ape.reverts("Commitment can't be made during deauthorization"):
taco_application.makeCommitment(
staking_provider, minimum_commitment_duration, sender=staking_provider
)
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)

# Finish deauthorization
chain.pending_timestamp += deauthorization_duration
taco_application.finishAuthorizationDecrease(staking_provider, sender=creator)

# And make a commitment
tx = taco_application.makeCommitment(
staking_provider, minimum_commitment_duration, sender=staking_provider
)
# 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)

# And make a commitment for shorter duration
tx = taco_application.makeCommitment(staking_provider, False, sender=staking_provider)
timestamp = chain.pending_timestamp - 1
end_commitment = timestamp + minimum_commitment_duration
end_commitment = timestamp + commitment_duration_1
assert (
taco_application.stakingProviderInfo(staking_provider)[END_COMMITMENT_SLOT]
== end_commitment
Expand All @@ -746,6 +743,23 @@ 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, minimum_commitment_duration, sender=staking_provider
taco_application.makeCommitment(staking_provider, False, sender=staking_provider)
with ape.reverts("Commitment already made"):
taco_application.makeCommitment(staking_provider, True, 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
)
timestamp = chain.pending_timestamp - 1
end_commitment = timestamp + commitment_duration_2
assert (
taco_application.stakingProviderInfo(another_staking_provider)[END_COMMITMENT_SLOT]
== end_commitment
)
assert tx.events == [
taco_application.CommitmentMade(
stakingProvider=another_staking_provider, endCommitment=end_commitment
)
]

0 comments on commit e8abe65

Please sign in to comment.