Skip to content

Commit d7f61f2

Browse files
authored
Merge pull request #103 from threshold-network/who-is-the-owner
Let the staking provider to refresh KEEP stake owner
2 parents a96d680 + 7c05a34 commit d7f61f2

File tree

6 files changed

+922
-166
lines changed

6 files changed

+922
-166
lines changed

contracts/staking/IStaking.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ interface IStaking {
7070
address authorizer
7171
) external;
7272

73-
/// @notice Refresh Keep stake owner. Can be called only by the old owner.
73+
/// @notice Refresh Keep stake owner. Can be called only by the old owner
74+
/// or their staking provider.
7475
/// @dev The staking provider in T staking contract is the legacy KEEP
7576
/// staking contract operator.
7677
function refreshKeepStakeOwner(address stakingProvider) external;

contracts/staking/KeepStake.sol

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@ interface IManagedGrant {
2828
/// KEEP stakers to use their stakes in T network and weights them based
2929
/// on KEEP<>T token ratio. KEEP stake owner is cached in T staking
3030
/// contract and used to restrict access to all functions only owner or
31-
/// operator should call. To cache KEEP staking contract in T staking
32-
/// contract, it fitst needs to resolve the owner. Resolving liquid
33-
/// KEEP stake owner is easy. Resolving token grant stake owner is
34-
/// complicated and not possible to do on-chain from a contract external
35-
/// to KEEP TokenStaking contract. Keep TokenStaking knows the grant ID
36-
/// but does not expose it externally.
31+
/// operator should call. To cache KEEP stake owner in T staking
32+
/// contract, T staking contract first needs to resolve the owner.
33+
///
34+
/// Resolving liquid KEEP stake owner is easy. Resolving token grant
35+
/// stake owner is complicated and not possible to do on-chain from
36+
/// a contract external to KEEP TokenStaking contract. Keep TokenStaking
37+
/// knows the grant ID but does not expose it externally.
3738
///
3839
/// KeepStake contract addresses this problem by exposing
3940
/// operator-owner mappings snapshotted off-chain based on events and

contracts/staking/TokenStaking.sol

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -397,17 +397,18 @@ contract TokenStaking is Initializable, IStaking, Checkpoints {
397397
);
398398
}
399399

400-
/// @notice Refresh Keep stake owner. Can be called only by the old owner.
400+
/// @notice Refresh Keep stake owner. Can be called only by the old owner
401+
/// or their staking provider.
401402
/// @dev The staking provider in T staking contract is the legacy KEEP
402403
/// staking contract operator.
403-
function refreshKeepStakeOwner(address stakingProvider) external override {
404+
function refreshKeepStakeOwner(address stakingProvider)
405+
external
406+
override
407+
onlyOwnerOrStakingProvider(stakingProvider)
408+
{
404409
StakingProviderInfo storage stakingProviderStruct = stakingProviders[
405410
stakingProvider
406411
];
407-
require(
408-
stakingProviderStruct.owner == msg.sender,
409-
"Caller is not owner"
410-
);
411412
address newOwner = keepStake.resolveOwner(stakingProvider);
412413

413414
emit OwnerRefreshed(

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@
4545
"eslint": "^7.27.0",
4646
"eslint-config-keep": "github:keep-network/eslint-config-keep#0c27ade",
4747
"ethereum-waffle": "^3.4.0",
48-
"ethers": "^5.4.1",
49-
"hardhat": "^2.6.8",
50-
"hardhat-contract-sizer": "^2.1.1",
51-
"hardhat-deploy": "^0.9.4",
52-
"hardhat-gas-reporter": "^1.0.4",
48+
"ethers": "^5.5.3",
49+
"hardhat": "^2.8.3",
50+
"hardhat-contract-sizer": "^2.5.0",
51+
"hardhat-deploy": "^0.9.27",
52+
"hardhat-gas-reporter": "^1.0.6",
5353
"prettier": "^2.3.2",
5454
"prettier-plugin-sh": "^0.7.1",
5555
"prettier-plugin-solidity": "^1.0.0-beta.14 ",

test/staking/TokenStaking.test.js

Lines changed: 102 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -864,11 +864,11 @@ describe("TokenStaking", () => {
864864
tokenStaking
865865
.connect(stakingProvider)
866866
.refreshKeepStakeOwner(stakingProvider.address)
867-
).to.be.revertedWith("Caller is not owner")
867+
).to.be.revertedWith("Not owner or provider")
868868
})
869869
})
870870

871-
context("when caller is not old owner", () => {
871+
context("when caller is neither old owner nor staking provider", () => {
872872
it("should revert", async () => {
873873
await tToken
874874
.connect(staker)
@@ -883,108 +883,122 @@ describe("TokenStaking", () => {
883883
)
884884
await expect(
885885
tokenStaking
886-
.connect(stakingProvider)
886+
.connect(authorizer)
887887
.refreshKeepStakeOwner(stakingProvider.address)
888-
).to.be.revertedWith("Caller is not owner")
888+
).to.be.revertedWith("Not owner or provider")
889889
})
890890
})
891891

892-
context("when grantee was not changed", () => {
893-
let tx
892+
const contextRefreshKeepStakeOwner = (getCaller) => {
893+
context("when grantee was not changed", () => {
894+
let tx
894895

895-
beforeEach(async () => {
896-
const createdAt = 1
897-
await keepStakingMock.setOperator(
898-
stakingProvider.address,
899-
staker.address,
900-
beneficiary.address,
901-
authorizer.address,
902-
createdAt,
903-
0,
904-
initialStakerBalance
905-
)
906-
await keepStakingMock.setEligibility(
907-
stakingProvider.address,
908-
tokenStaking.address,
909-
true
910-
)
911-
await tokenStaking.stakeKeep(stakingProvider.address)
896+
beforeEach(async () => {
897+
const createdAt = 1
898+
await keepStakingMock.setOperator(
899+
stakingProvider.address,
900+
staker.address,
901+
beneficiary.address,
902+
authorizer.address,
903+
createdAt,
904+
0,
905+
initialStakerBalance
906+
)
907+
await keepStakingMock.setEligibility(
908+
stakingProvider.address,
909+
tokenStaking.address,
910+
true
911+
)
912+
await tokenStaking.stakeKeep(stakingProvider.address)
912913

913-
tx = await tokenStaking
914-
.connect(staker)
915-
.refreshKeepStakeOwner(stakingProvider.address)
916-
})
914+
tx = await tokenStaking
915+
.connect(getCaller())
916+
.refreshKeepStakeOwner(stakingProvider.address)
917+
})
917918

918-
it("should not update owner", async () => {
919-
expect(
920-
await tokenStaking.rolesOf(stakingProvider.address)
921-
).to.deep.equal([
922-
staker.address,
923-
beneficiary.address,
924-
authorizer.address,
925-
])
926-
})
919+
it("should not update owner", async () => {
920+
expect(
921+
await tokenStaking.rolesOf(stakingProvider.address)
922+
).to.deep.equal([
923+
staker.address,
924+
beneficiary.address,
925+
authorizer.address,
926+
])
927+
})
927928

928-
it("should emit OwnerRefreshed", async () => {
929-
await expect(tx)
930-
.to.emit(tokenStaking, "OwnerRefreshed")
931-
.withArgs(stakingProvider.address, staker.address, staker.address)
929+
it("should emit OwnerRefreshed", async () => {
930+
await expect(tx)
931+
.to.emit(tokenStaking, "OwnerRefreshed")
932+
.withArgs(stakingProvider.address, staker.address, staker.address)
933+
})
932934
})
933-
})
934935

935-
context("when grantee was changed", () => {
936-
let tx
936+
context("when grantee was changed", () => {
937+
let tx
937938

938-
beforeEach(async () => {
939-
const createdAt = 1
940-
await keepStakingMock.setOperator(
941-
stakingProvider.address,
942-
otherStaker.address,
943-
beneficiary.address,
944-
authorizer.address,
945-
createdAt,
946-
0,
947-
initialStakerBalance
948-
)
949-
await keepStakingMock.setEligibility(
950-
stakingProvider.address,
951-
tokenStaking.address,
952-
true
953-
)
954-
await tokenStaking.stakeKeep(stakingProvider.address)
939+
beforeEach(async () => {
940+
const createdAt = 1
941+
await keepStakingMock.setOperator(
942+
stakingProvider.address,
943+
otherStaker.address,
944+
beneficiary.address,
945+
authorizer.address,
946+
createdAt,
947+
0,
948+
initialStakerBalance
949+
)
950+
await keepStakingMock.setEligibility(
951+
stakingProvider.address,
952+
tokenStaking.address,
953+
true
954+
)
955+
await tokenStaking.stakeKeep(stakingProvider.address)
955956

956-
await keepStakingMock.setOperator(
957-
stakingProvider.address,
958-
staker.address,
959-
beneficiary.address,
960-
authorizer.address,
961-
createdAt,
962-
0,
963-
initialStakerBalance
964-
)
965-
tx = await tokenStaking
966-
.connect(otherStaker)
967-
.refreshKeepStakeOwner(stakingProvider.address)
957+
await keepStakingMock.setOperator(
958+
stakingProvider.address,
959+
staker.address,
960+
beneficiary.address,
961+
authorizer.address,
962+
createdAt,
963+
0,
964+
initialStakerBalance
965+
)
966+
tx = await tokenStaking
967+
.connect(otherStaker)
968+
.refreshKeepStakeOwner(stakingProvider.address)
969+
})
970+
971+
it("should update owner", async () => {
972+
expect(
973+
await tokenStaking.rolesOf(stakingProvider.address)
974+
).to.deep.equal([
975+
staker.address,
976+
beneficiary.address,
977+
authorizer.address,
978+
])
979+
})
980+
981+
it("should emit OwnerRefreshed", async () => {
982+
await expect(tx)
983+
.to.emit(tokenStaking, "OwnerRefreshed")
984+
.withArgs(
985+
stakingProvider.address,
986+
otherStaker.address,
987+
staker.address
988+
)
989+
})
968990
})
991+
}
969992

970-
it("should update owner", async () => {
971-
expect(
972-
await tokenStaking.rolesOf(stakingProvider.address)
973-
).to.deep.equal([
974-
staker.address,
975-
beneficiary.address,
976-
authorizer.address,
977-
])
993+
context("when caller is the old owner", () => {
994+
contextRefreshKeepStakeOwner(() => {
995+
return staker
978996
})
997+
})
979998

980-
it("should emit OwnerRefreshed", async () => {
981-
await expect(tx)
982-
.to.emit(tokenStaking, "OwnerRefreshed")
983-
.withArgs(
984-
stakingProvider.address,
985-
otherStaker.address,
986-
staker.address
987-
)
999+
context("when caller is the staking provider", () => {
1000+
contextRefreshKeepStakeOwner(() => {
1001+
return stakingProvider
9881002
})
9891003
})
9901004
})

0 commit comments

Comments
 (0)