Skip to content

Commit 9a4e820

Browse files
committed
staking: more concept changes
1 parent 9c2854a commit 9a4e820

File tree

3 files changed

+56
-68
lines changed

3 files changed

+56
-68
lines changed

contracts/staking/IStaking.sol

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ interface IStaking {
1616
enum AllocationState { Null, Active, Settled, Finalized, Claimed }
1717

1818
/**
19-
* @dev GRT stake allocation to a channel
19+
* @dev Allocate GRT tokens for the purpose of serving queries of a subgraph deployment
2020
* An allocation is created in the allocate() function and consumed in claim()
2121
*/
2222
struct Allocation {
@@ -25,9 +25,9 @@ interface IStaking {
2525
uint256 tokens; // Tokens allocated to a SubgraphDeployment
2626
uint256 createdAtEpoch; // Epoch when it was created
2727
uint256 settledAtEpoch; // Epoch when it was settled
28-
uint256 collectedFees; // Collected fees from channels
28+
uint256 collectedFees; // Collected fees for the allocation
2929
uint256 effectiveAllocation; // Effective allocation when settled
30-
address channelProxy; // Caller address of the collect() function
30+
address authSender; // Authorized caller address of the collect() function
3131
}
3232

3333
// -- Delegation Data --
@@ -115,7 +115,7 @@ interface IStaking {
115115
bytes32 _subgraphDeploymentID,
116116
uint256 _tokens,
117117
bytes calldata _channelPubKey,
118-
address _channelProxy,
118+
address _authSender,
119119
uint256 _price
120120
) external;
121121

@@ -124,15 +124,15 @@ interface IStaking {
124124
bytes32 _subgraphDeploymentID,
125125
uint256 _tokens,
126126
bytes calldata _channelPubKey,
127-
address _channelProxy,
127+
address _authSender,
128128
uint256 _price
129129
) external;
130130

131-
function settle(address _channelID) external;
131+
function settle(address _allocationID) external;
132132

133-
function collect(uint256 _tokens, address _channelID) external;
133+
function collect(uint256 _tokens, address _allocationID) external;
134134

135-
function claim(address _channelID, bool _restake) external;
135+
function claim(address _allocationID, bool _restake) external;
136136

137137
// -- Getters and calculations --
138138

@@ -142,11 +142,11 @@ interface IStaking {
142142

143143
function getIndexerCapacity(address _indexer) external view returns (uint256);
144144

145-
function getAllocation(address _channelID) external view returns (Allocation memory);
145+
function getAllocation(address _allocationID) external view returns (Allocation memory);
146146

147-
function getAllocationState(address _channelID) external view returns (AllocationState);
147+
function getAllocationState(address _allocationID) external view returns (AllocationState);
148148

149-
function isChannel(address _channelID) external view returns (bool);
149+
function isChannel(address _allocationID) external view returns (bool);
150150

151151
function getDelegation(address _indexer, address _delegator)
152152
external

contracts/staking/Staking.sol

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,13 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking, Governed {
109109
address allocationID,
110110
bytes channelPubKey,
111111
uint256 price,
112-
address proxy
112+
address authSender
113113
);
114114

115115
/**
116-
* @dev Emitted when `indexer` withdrew `tokens` amount in `epoch` from `allocationID` channel.
117-
* The funds are related to `subgraphDeploymentID`.
118-
* `from` attribute records the the multisig contract from where it was settled.
116+
* @dev Emitted when `indexer` collected `tokens` amount in `epoch` for `allocationID`.
117+
* These funds are related to `subgraphDeploymentID`.
118+
* The `from` value is the sender of the collected funds.
119119
*/
120120
event AllocationCollected(
121121
address indexed indexer,
@@ -129,8 +129,8 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking, Governed {
129129
);
130130

131131
/**
132-
* @dev Emitted when `indexer` settled an allocation in `epoch` for `allocationID` channel.
133-
* The `tokens` getting unallocated from `subgraphDeploymentID`.
132+
* @dev Emitted when `indexer` settled an allocation in `epoch` for `allocationID`.
133+
* An amount of `tokens` get unallocated from `subgraphDeploymentID`.
134134
* The `effectiveAllocation` are the tokens allocated from creation to settlement.
135135
*/
136136
event AllocationSettled(
@@ -707,49 +707,42 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking, Governed {
707707
* @dev Allocate available tokens to a subgraph deployment.
708708
* @param _subgraphDeploymentID ID of the SubgraphDeployment where tokens will be allocated
709709
* @param _tokens Amount of tokens to allocate
710-
* @param _channelPubKey The public key used by the indexer to setup the off-chain channel
711-
* @param _channelProxy Address of the multisig proxy used to hold channel funds
710+
* @param _channelPubKey The public key used to route payments
711+
* @param _authSender Authorized sender address of collected funds
712712
* @param _price Price the `indexer` will charge for serving queries of the `subgraphDeploymentID`
713713
*/
714714
function allocate(
715715
bytes32 _subgraphDeploymentID,
716716
uint256 _tokens,
717717
bytes calldata _channelPubKey,
718-
address _channelProxy,
718+
address _authSender,
719719
uint256 _price
720720
) external override {
721721
require(_onlyAuth(msg.sender), "Allocation: caller must be authorized");
722722

723-
_allocate(
724-
msg.sender,
725-
_subgraphDeploymentID,
726-
_tokens,
727-
_channelPubKey,
728-
_channelProxy,
729-
_price
730-
);
723+
_allocate(msg.sender, _subgraphDeploymentID, _tokens, _channelPubKey, _authSender, _price);
731724
}
732725

733726
/**
734727
* @dev Allocate available tokens to a subgraph deployment.
735728
* @param _indexer Indexer address to allocate funds from.
736729
* @param _subgraphDeploymentID ID of the SubgraphDeployment where tokens will be allocated
737730
* @param _tokens Amount of tokens to allocate
738-
* @param _channelPubKey The public key used by the indexer to setup the off-chain channel
739-
* @param _channelProxy Address of the multisig proxy used to hold channel funds
731+
* @param _channelPubKey The public key used to route payments
732+
* @param _authSender Authorized sender address of collected funds
740733
* @param _price Price the `indexer` will charge for serving queries of the `subgraphDeploymentID`
741734
*/
742735
function allocateFrom(
743736
address _indexer,
744737
bytes32 _subgraphDeploymentID,
745738
uint256 _tokens,
746739
bytes calldata _channelPubKey,
747-
address _channelProxy,
740+
address _authSender,
748741
uint256 _price
749742
) external override {
750743
require(_onlyAuth(_indexer), "Allocation: caller must be authorized");
751744

752-
_allocate(_indexer, _subgraphDeploymentID, _tokens, _channelPubKey, _channelProxy, _price);
745+
_allocate(_indexer, _subgraphDeploymentID, _tokens, _channelPubKey, _authSender, _price);
753746
}
754747

755748
/**
@@ -817,16 +810,13 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking, Governed {
817810
// Allocation identifier validation
818811
require(_allocationID != address(0), "Collect: invalid allocation");
819812

820-
// The contract caller must be a channel proxy registered during allocation
821-
require(
822-
alloc.channelProxy == msg.sender,
823-
"Collect: caller is not related to the allocation"
824-
);
813+
// The contract caller must be an authorized sender registered on allocate()
814+
require(alloc.authSender == msg.sender, "Collect: caller is not authorized");
825815

826-
// Transfer tokens to collect from multisig to this contract
816+
// Transfer tokens to collect from the authorized sender
827817
require(
828818
token.transferFrom(msg.sender, address(this), _tokens),
829-
"Collect: cannot transfer tokens to settle"
819+
"Collect: cannot transfer tokens to collect"
830820
);
831821

832822
_collect(_allocationID, msg.sender, _tokens);
@@ -875,7 +865,7 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking, Governed {
875865
alloc.settledAtEpoch = 0;
876866
alloc.collectedFees = 0;
877867
alloc.effectiveAllocation = 0;
878-
alloc.channelProxy = address(0); // This avoid collect() to be called
868+
alloc.authSender = address(0); // This avoid collect() to be called
879869

880870
// When there are tokens to claim from the rebate pool, transfer or restake
881871
if (tokensToClaim > 0) {
@@ -931,15 +921,15 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking, Governed {
931921
* @param _subgraphDeploymentID ID of the SubgraphDeployment where tokens will be allocated
932922
* @param _tokens Amount of tokens to allocate
933923
* @param _channelPubKey The public key used by the indexer to setup the off-chain channel
934-
* @param _channelProxy Address of the multisig proxy used to hold channel funds
924+
* @param _authSender Authorized sender address of collected funds
935925
* @param _price Price the `indexer` will charge for serving queries of the `subgraphDeploymentID`
936926
*/
937927
function _allocate(
938928
address _indexer,
939929
bytes32 _subgraphDeploymentID,
940930
uint256 _tokens,
941931
bytes memory _channelPubKey,
942-
address _channelProxy,
932+
address _authSender,
943933
uint256 _price
944934
) private {
945935
Stakes.Indexer storage indexerStake = stakes[_indexer];
@@ -960,9 +950,8 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking, Governed {
960950
);
961951

962952
// A channel public key is derived by the indexer when creating the offchain payment channel.
963-
// Get the Ethereum address from the public key and use as channel identifier.
964-
// The channel identifier is the address of the indexer signing party of a multisig that
965-
// will hold the funds received when the channel is settled.
953+
// Get the Ethereum address from the public key and use as allocation identifier.
954+
// The allocationID will work to identify collected funds related to this allocation.
966955
address allocationID = address(uint256(keccak256(_sliceByte(bytes(_channelPubKey)))));
967956

968957
// Cannot reuse an allocationID that has already been used in an allocation
@@ -973,17 +962,16 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking, Governed {
973962

974963
// Creates an allocation
975964
// Allocation identifiers are not reused
976-
// The channel proxy address is the contract that will send tokens to be collected to
977-
// this contract
965+
// The authorized sender address can send collected funds to the allocation
978966
allocations[allocationID] = Allocation(
979967
_indexer,
980968
_subgraphDeploymentID,
981969
_tokens, // Tokens allocated
982970
epochManager.currentEpoch(), // createdAtEpoch
983971
0, // settledAtEpoch
984-
0, // Initialize with zero collected fees
972+
0, // Initialize collected fees
985973
0, // Initialize effective allocation
986-
_channelProxy // Source address of allocation collected funds
974+
_authSender // Source address for allocation collected funds
987975
);
988976

989977
// Mark allocated tokens as used
@@ -997,7 +985,7 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking, Governed {
997985
allocationID,
998986
_channelPubKey,
999987
_price,
1000-
_channelProxy
988+
_authSender
1001989
);
1002990
}
1003991

test/staking/allocation.test.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ describe('Staking:Allocation', () => {
4444
let governor: Account
4545
let indexer: Account
4646
let slasher: Account
47-
let channelProxy: Account
47+
let authSender: Account
4848

4949
let fixture: NetworkFixture
5050

@@ -68,11 +68,11 @@ describe('Staking:Allocation', () => {
6868
const allocate = (tokens: BigNumber) => {
6969
return staking
7070
.connect(indexer.signer)
71-
.allocate(subgraphDeploymentID, tokens, channelPubKey, channelProxy.address, price)
71+
.allocate(subgraphDeploymentID, tokens, channelPubKey, authSender.address, price)
7272
}
7373

7474
before(async function () {
75-
;[me, other, governor, indexer, slasher, channelProxy] = await getAccounts()
75+
;[me, other, governor, indexer, slasher, authSender] = await getAccounts()
7676

7777
fixture = new NetworkFixture()
7878
;({ curation, epochManager, grt, staking } = await fixture.load(
@@ -150,7 +150,7 @@ describe('Staking:Allocation', () => {
150150
channelID,
151151
channelPubKey,
152152
price,
153-
channelProxy.address,
153+
authSender.address,
154154
)
155155

156156
// After state
@@ -167,7 +167,7 @@ describe('Staking:Allocation', () => {
167167
expect(afterAlloc.collectedFees).eq(toGRT('0'))
168168
expect(afterAlloc.settledAtEpoch).eq(toBN('0'))
169169
expect(afterAlloc.effectiveAllocation).eq(toGRT('0'))
170-
expect(afterAlloc.channelProxy).eq(channelProxy.address)
170+
expect(afterAlloc.authSender).eq(authSender.address)
171171
}
172172

173173
it('reject allocate zero tokens', async function () {
@@ -184,7 +184,7 @@ describe('Staking:Allocation', () => {
184184
subgraphDeploymentID,
185185
tokensToAllocate,
186186
invalidChannelPubKey,
187-
channelProxy.address,
187+
authSender.address,
188188
price,
189189
)
190190
await expect(tx).revertedWith('Allocation: invalid channel public key')
@@ -220,7 +220,7 @@ describe('Staking:Allocation', () => {
220220
subgraphDeploymentID,
221221
tokensToAllocate,
222222
channelPubKey,
223-
channelProxy.address,
223+
authSender.address,
224224
price,
225225
)
226226
await expect(tx1).revertedWith('Allocation: caller must be authorized')
@@ -234,7 +234,7 @@ describe('Staking:Allocation', () => {
234234
subgraphDeploymentID,
235235
tokensToAllocate,
236236
channelPubKey,
237-
channelProxy.address,
237+
authSender.address,
238238
price,
239239
)
240240
})
@@ -273,7 +273,7 @@ describe('Staking:Allocation', () => {
273273
rebateFees = rebateFees.sub(curationFees)
274274

275275
// Collect tokens from channel
276-
const tx = staking.connect(channelProxy.signer).collect(tokensToCollect, channelID)
276+
const tx = staking.connect(authSender.signer).collect(tokensToCollect, channelID)
277277
await expect(tx)
278278
.emit(staking, 'AllocationCollected')
279279
.withArgs(
@@ -282,7 +282,7 @@ describe('Staking:Allocation', () => {
282282
await epochManager.currentEpoch(),
283283
tokensToCollect,
284284
channelID,
285-
channelProxy.address,
285+
authSender.address,
286286
curationFees,
287287
rebateFees,
288288
)
@@ -310,8 +310,8 @@ describe('Staking:Allocation', () => {
310310

311311
// Fund channel wallet
312312
const tokensToFund = toGRT('100000')
313-
await grt.connect(governor.signer).mint(channelProxy.address, tokensToFund)
314-
await grt.connect(channelProxy.signer).approve(staking.address, tokensToFund)
313+
await grt.connect(governor.signer).mint(authSender.address, tokensToFund)
314+
await grt.connect(authSender.signer).approve(staking.address, tokensToFund)
315315
})
316316

317317
it('reject collect if invalid channel', async function () {
@@ -384,15 +384,15 @@ describe('Staking:Allocation', () => {
384384
await staking.connect(indexer.signer).settle(channelID)
385385

386386
// Collect fees into the channel
387-
const tx1 = staking.connect(channelProxy.signer).collect(tokensToCollect, channelID)
387+
const tx1 = staking.connect(authSender.signer).collect(tokensToCollect, channelID)
388388
await tx1
389389

390390
// Advance blocks to get channel in epoch where it can no longer collect funds (finalized)
391391
await advanceToNextEpoch(epochManager)
392392

393393
// Revert if channel is finalized
394394
expect(await staking.getAllocationState(channelID)).eq(AllocationState.Finalized)
395-
const tx2 = staking.connect(channelProxy.signer).collect(tokensToCollect, channelID)
395+
const tx2 = staking.connect(authSender.signer).collect(tokensToCollect, channelID)
396396
await expect(tx2).revertedWith('Collect: channel must be active or settled')
397397
})
398398
})
@@ -560,7 +560,7 @@ describe('Staking:Allocation', () => {
560560
expect(afterAlloc.settledAtEpoch).eq(toGRT('0'))
561561
expect(afterAlloc.collectedFees).eq(toGRT('0'))
562562
expect(afterAlloc.effectiveAllocation).eq(toGRT('0'))
563-
expect(afterAlloc.channelProxy).eq(AddressZero)
563+
expect(afterAlloc.authSender).eq(AddressZero)
564564
// Rebate updated
565565
expect(afterRebatePool.settlementsCount).eq(beforeRebatePool.settlementsCount.sub(toBN('1')))
566566
if (afterRebatePool.settlementsCount.eq(toBN('0'))) {
@@ -583,8 +583,8 @@ describe('Staking:Allocation', () => {
583583
await staking.connect(governor.signer).setChannelDisputeEpochs(toBN('1'))
584584

585585
// Fund wallets
586-
await grt.connect(governor.signer).mint(channelProxy.address, tokensToCollect)
587-
await grt.connect(channelProxy.signer).approve(staking.address, tokensToCollect)
586+
await grt.connect(governor.signer).mint(authSender.address, tokensToCollect)
587+
await grt.connect(authSender.signer).approve(staking.address, tokensToCollect)
588588
})
589589

590590
it('reject claim for non-existing channel allocation', async function () {
@@ -603,7 +603,7 @@ describe('Staking:Allocation', () => {
603603
context('> when settled', function () {
604604
beforeEach(async function () {
605605
// Collect some funds
606-
await staking.connect(channelProxy.signer).collect(tokensToCollect, channelID)
606+
await staking.connect(authSender.signer).collect(tokensToCollect, channelID)
607607

608608
// Advance blocks to get the channel in epoch where it can be settled
609609
await advanceToNextEpoch(epochManager)

0 commit comments

Comments
 (0)