Skip to content

Commit

Permalink
Merge pull request #87 from threshold-network/reduce-all
Browse files Browse the repository at this point in the history
Involuntarily decrease all authorizations in case of slashing
  • Loading branch information
cygnusv authored Apr 22, 2022
2 parents 702aa5f + 225c4e2 commit 07e49aa
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 116 deletions.
34 changes: 10 additions & 24 deletions contracts/staking/TokenStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ contract TokenStaking is Initializable, IStaking, Checkpoints {
struct SlashingEvent {
address stakingProvider;
uint96 amount;
address application;
}

uint256 internal constant SLASHING_REWARD_PERCENT = 5;
Expand Down Expand Up @@ -1000,8 +999,7 @@ contract TokenStaking is Initializable, IStaking, Checkpoints {
authorizationDecrease(
stakingProvider,
stakingProviderStruct,
slashedAmount,
address(0)
slashedAmount
);
}

Expand Down Expand Up @@ -1044,8 +1042,7 @@ contract TokenStaking is Initializable, IStaking, Checkpoints {
authorizationDecrease(
stakingProvider,
stakingProviderStruct,
slashedAmount,
address(0)
slashedAmount
);
decreaseStakeCheckpoint(
stakingProvider,
Expand Down Expand Up @@ -1472,11 +1469,7 @@ contract TokenStaking is Initializable, IStaking, Checkpoints {
continue;
}
slashingQueue.push(
SlashingEvent(
stakingProvider,
amountToSlash.toUint96(),
msg.sender
)
SlashingEvent(stakingProvider, amountToSlash.toUint96())
);
}

Expand Down Expand Up @@ -1548,8 +1541,7 @@ contract TokenStaking is Initializable, IStaking, Checkpoints {
authorizationDecrease(
slashing.stakingProvider,
stakingProviderStruct,
slashedAmount,
slashing.application
slashedAmount
);
uint96 newStake = stakingProviderStruct.tStake +
stakingProviderStruct.keepInTStake +
Expand All @@ -1561,8 +1553,7 @@ contract TokenStaking is Initializable, IStaking, Checkpoints {
function authorizationDecrease(
address stakingProvider,
StakingProviderInfo storage stakingProviderStruct,
uint96 slashedAmount,
address application
uint96 slashedAmount
) internal {
uint96 totalStake = stakingProviderStruct.tStake +
stakingProviderStruct.nuInTStake +
Expand All @@ -1578,16 +1569,11 @@ contract TokenStaking is Initializable, IStaking, Checkpoints {
AppAuthorization storage authorization = stakingProviderStruct
.authorizations[authorizedApplication];
uint96 fromAmount = authorization.authorized;
if (
application == address(0) ||
authorizedApplication == application
) {
authorization.authorized -= MathUpgradeable
.min(fromAmount, slashedAmount)
.toUint96();
} else if (fromAmount <= totalStake) {
continue;
}

authorization.authorized -= MathUpgradeable
.min(fromAmount, slashedAmount)
.toUint96();

if (authorization.authorized > totalStake) {
authorization.authorized = totalStake;
}
Expand Down
173 changes: 81 additions & 92 deletions test/staking/TokenStaking.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6454,12 +6454,10 @@ describe("TokenStaking", () => {
expect(await tokenStaking.slashingQueue(0)).to.deep.equal([
stakingProvider.address,
amount,
application1Mock.address,
])
expect(await tokenStaking.slashingQueue(1)).to.deep.equal([
otherStaker.address,
amountToSlash,
application1Mock.address,
])
expect(await tokenStaking.getSlashingQueueLength()).to.equal(2)
})
Expand Down Expand Up @@ -6520,12 +6518,10 @@ describe("TokenStaking", () => {
expect(await tokenStaking.slashingQueue(0)).to.deep.equal([
stakingProvider.address,
amountToSlash,
application1Mock.address,
])
expect(await tokenStaking.slashingQueue(1)).to.deep.equal([
otherStaker.address,
amountToSlash,
application1Mock.address,
])
expect(await tokenStaking.getSlashingQueueLength()).to.equal(2)
})
Expand Down Expand Up @@ -6603,12 +6599,10 @@ describe("TokenStaking", () => {
expect(await tokenStaking.slashingQueue(0)).to.deep.equal([
otherStaker.address,
amountToSlash,
application1Mock.address,
])
expect(await tokenStaking.slashingQueue(1)).to.deep.equal([
stakingProvider.address,
amountToSlash,
application1Mock.address,
])
expect(await tokenStaking.getSlashingQueueLength()).to.equal(2)
})
Expand Down Expand Up @@ -6644,7 +6638,6 @@ describe("TokenStaking", () => {
expect(await tokenStaking.slashingQueue(0)).to.deep.equal([
stakingProvider.address,
amountToSlash,
application1Mock.address,
])
expect(await tokenStaking.getSlashingQueueLength()).to.equal(1)
})
Expand Down Expand Up @@ -6687,7 +6680,6 @@ describe("TokenStaking", () => {
expect(await tokenStaking.slashingQueue(0)).to.deep.equal([
otherStaker.address,
amountToSlash,
application1Mock.address,
])
})

Expand Down Expand Up @@ -7001,7 +6993,7 @@ describe("TokenStaking", () => {
).to.equal(0)
})

it("should decrease authorized amount only for one application", async () => {
it("should decrease authorized amounts only for one provider", async () => {
expect(
await tokenStaking.authorizedStake(
stakingProvider.address,
Expand All @@ -7013,7 +7005,7 @@ describe("TokenStaking", () => {
stakingProvider.address,
application2Mock.address
)
).to.equal(provider1Authorized2)
).to.equal(provider1Authorized2.sub(amountToSlash))
expect(
await tokenStaking.authorizedStake(
otherStaker.address,
Expand Down Expand Up @@ -7045,13 +7037,13 @@ describe("TokenStaking", () => {
).to.be.revertedWith("Too many applications")
})

it("should inform only one application", async () => {
it("should inform all applications", async () => {
expect(
await application1Mock.stakingProviders(stakingProvider.address)
).to.deep.equal([provider1Authorized1.sub(amountToSlash), Zero])
expect(
await application2Mock.stakingProviders(stakingProvider.address)
).to.deep.equal([provider1Authorized2, Zero])
).to.deep.equal([provider1Authorized2.sub(amountToSlash), Zero])
expect(
await application1Mock.stakingProviders(otherStaker.address)
).to.deep.equal([provider2Authorized1, Zero])
Expand Down Expand Up @@ -7268,99 +7260,96 @@ describe("TokenStaking", () => {
})
})

context(
"when decrease authorized amount to zero for one application",
() => {
const tAmount = initialStakerBalance
context("when decrease authorized amount to zero", () => {
const tAmount = initialStakerBalance

const amountToSlash = tAmount.div(3)
const authorized = amountToSlash
const amountToSlash = tAmount.div(3)
const authorized = amountToSlash

beforeEach(async () => {
await tokenStaking.connect(deployer).setAuthorizationCeiling(2)
await tokenStaking
.connect(deployer)
.approveApplication(application1Mock.address)
await tokenStaking
.connect(deployer)
.approveApplication(application2Mock.address)
beforeEach(async () => {
await tokenStaking.connect(deployer).setAuthorizationCeiling(2)
await tokenStaking
.connect(deployer)
.approveApplication(application1Mock.address)
await tokenStaking
.connect(deployer)
.approveApplication(application2Mock.address)

await tToken.connect(staker).approve(tokenStaking.address, tAmount)
await tokenStaking
.connect(staker)
.stake(
stakingProvider.address,
staker.address,
staker.address,
tAmount
)
await tokenStaking
.connect(staker)
.increaseAuthorization(
stakingProvider.address,
application2Mock.address,
authorized
)
await tokenStaking
.connect(staker)
.increaseAuthorization(
stakingProvider.address,
application1Mock.address,
authorized
)
await tToken.connect(staker).approve(tokenStaking.address, tAmount)
await tokenStaking
.connect(staker)
.stake(
stakingProvider.address,
staker.address,
staker.address,
tAmount
)
await tokenStaking
.connect(staker)
.increaseAuthorization(
stakingProvider.address,
application2Mock.address,
authorized
)
await tokenStaking
.connect(staker)
.increaseAuthorization(
stakingProvider.address,
application1Mock.address,
authorized
)

await application1Mock.slash(amountToSlash, [stakingProvider.address])
await application1Mock.slash(amountToSlash, [stakingProvider.address])

await tokenStaking.processSlashing(1)
})
await tokenStaking.processSlashing(1)
})

it("should decrease authorized amount", async () => {
expect(
await tokenStaking.authorizedStake(
stakingProvider.address,
application1Mock.address
)
).to.equal(0)
expect(
await tokenStaking.authorizedStake(
stakingProvider.address,
application2Mock.address
)
).to.equal(authorized)
})
it("should decrease authorized amount", async () => {
expect(
await tokenStaking.authorizedStake(
stakingProvider.address,
application1Mock.address
)
).to.equal(0)
expect(
await tokenStaking.authorizedStake(
stakingProvider.address,
application2Mock.address
)
).to.equal(0)
})

it("should allow to authorize one more application", async () => {
await tokenStaking
.connect(staker)
.increaseAuthorization(
stakingProvider.address,
application1Mock.address,
authorized
)
it("should allow to authorize one more application", async () => {
await tokenStaking
.connect(staker)
.increaseAuthorization(
stakingProvider.address,
application1Mock.address,
authorized
)

await tokenStaking
await tokenStaking
.connect(staker)
.increaseAuthorization(
stakingProvider.address,
application2Mock.address,
authorized
)

await tokenStaking
.connect(deployer)
.approveApplication(auxiliaryAccount.address)
await expect(
tokenStaking
.connect(staker)
.increaseAuthorization(
stakingProvider.address,
application2Mock.address,
auxiliaryAccount.address,
authorized
)

await tokenStaking
.connect(deployer)
.approveApplication(auxiliaryAccount.address)
await expect(
tokenStaking
.connect(staker)
.increaseAuthorization(
stakingProvider.address,
auxiliaryAccount.address,
authorized
)
).to.be.revertedWith("Too many applications")
})
}
)
).to.be.revertedWith("Too many applications")
})
})
})

describe("cleanAuthorizedApplications", () => {
Expand Down

0 comments on commit 07e49aa

Please sign in to comment.