Skip to content

Commit 52db769

Browse files
committed
draft: update MultiVotes
1 parent 23d901c commit 52db769

File tree

4 files changed

+77
-24
lines changed

4 files changed

+77
-24
lines changed

contracts/governance/utils/IMultiVotes.sol

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ import {IVotes} from "./IVotes.sol";
88
* @dev Common interface for {ERC20MultiVotes} and other {MultiVotes}-enabled contracts.
99
*/
1010
interface IMultiVotes is IVotes {
11+
12+
/**
13+
* @dev Invalid, start should be equal or smaller than end.
14+
*/
15+
error StartIsBiggerThanEnd(uint256 start, uint256 end);
16+
1117
/**
1218
* @dev Requested more units than actually available.
1319
*/
@@ -29,12 +35,12 @@ interface IMultiVotes is IVotes {
2935
event DelegateModified(address indexed delegator, address indexed delegate, uint256 fromUnits, uint256 toUnits);
3036

3137
/**
32-
* @dev Returns `account` partial delegations.
38+
* @dev Returns `account` partial delegations list starting from `start` to `end`.
3339
*
34-
* NOTE: Without a limit on partial delegations applied, this call may consume too much gas and fail.
35-
* Furthermore, the order of the returned list should be considered pseudo-random.
40+
* NOTE: Order may unexpectedly change if called in different transactions.
41+
* Trust the returned array only if you obtain it within a single transaction.
3642
*/
37-
function multiDelegates(address account) external view returns (address[] memory);
43+
function multiDelegates(address account, uint256 start, uint256 end) external view returns (address[] memory);
3844

3945
/**
4046
* @dev Set delegates list with units assigned for each one

contracts/governance/utils/MultiVotes.sol

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,30 @@ abstract contract MultiVotes is Votes, IMultiVotes {
5656
}
5757

5858
/**
59-
* @dev Returns `account` partial delegations.
59+
* @dev Returns `account` partial delegations list starting from `start` to `end`.
6060
*
61-
* NOTE: Without a limit on partial delegations applied, this call may consume too much gas and fail.
62-
* Furthermore, the order of the returned list should be considered pseudo-random.
61+
* NOTE: Order may unexpectedly change if called in different transactions.
62+
* Trust the returned array only if you obtain it within a single transaction.
6363
*/
64-
function multiDelegates(address account) public view virtual returns (address[] memory) {
65-
return _delegatesList[account];
64+
function multiDelegates(address account, uint256 start, uint256 end) public view virtual returns (address[] memory) {
65+
uint256 maxLength = _delegatesList[account].length;
66+
require(end >= start, StartIsBiggerThanEnd(start, end));
67+
if(start >= maxLength) {
68+
address[] memory empty = new address[](0);
69+
return empty;
70+
}
71+
72+
if (end >= maxLength) {
73+
end = maxLength - 1;
74+
}
75+
uint256 length = (end + 1) - start;
76+
address[] memory list = new address[](length);
77+
78+
for(uint256 i; i < length; i++) {
79+
list[i] = _delegatesList[account][start + i];
80+
}
81+
82+
return list;
6683
}
6784

6885
/**

test/governance/utils/MultiVotes.behavior.js

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ function shouldBehaveLikeMultiVotes(tokens, { mode = 'blocknumber', fungible = t
6868
.to.emit(this.votes, 'DelegateVotesChanged')
6969
.withArgs(this.bob, 0, 15);
7070

71-
let multiDelegates = await this.votes.multiDelegates(this.delegator);
71+
let multiDelegates = await this.votes.multiDelegates(this.delegator, 0, 100);
7272
expect([...multiDelegates]).to.have.members([this.delegatee.address, this.bob.address]);
7373

7474
expect(await this.votes.getDelegatedUnits(this.delegator, this.delegatee)).to.equal(1);
@@ -88,7 +88,7 @@ function shouldBehaveLikeMultiVotes(tokens, { mode = 'blocknumber', fungible = t
8888
.to.emit(this.votes, 'DelegateVotesChanged')
8989
.withArgs(this.alice, 0, 20);
9090

91-
let multiDelegates = await this.votes.multiDelegates(this.delegator);
91+
let multiDelegates = await this.votes.multiDelegates(this.delegator, 0, 100);
9292
expect([...multiDelegates]).to.have.members([this.delegatee.address, this.bob.address, this.alice.address]);
9393

9494
expect(await this.votes.getDelegatedUnits(this.delegator, this.delegatee)).to.equal(1);
@@ -127,7 +127,7 @@ function shouldBehaveLikeMultiVotes(tokens, { mode = 'blocknumber', fungible = t
127127
.to.emit(this.votes, 'DelegateVotesChanged')
128128
.withArgs(this.delegatee, 1, 0);
129129

130-
let multiDelegates = await this.votes.multiDelegates(this.delegator);
130+
let multiDelegates = await this.votes.multiDelegates(this.delegator, 0, 100);
131131
expect([...multiDelegates]).to.have.members([this.bob.address]);
132132

133133
expect(await this.votes.getDelegatedUnits(this.delegator, this.delegatee)).to.equal(0);
@@ -151,7 +151,7 @@ function shouldBehaveLikeMultiVotes(tokens, { mode = 'blocknumber', fungible = t
151151
.to.emit(this.votes, 'DelegateVotesChanged')
152152
.withArgs(this.bob, 15, 10);
153153

154-
let multiDelegates = await this.votes.multiDelegates(this.delegator);
154+
let multiDelegates = await this.votes.multiDelegates(this.delegator, 0, 100);
155155
expect([...multiDelegates]).to.have.members([this.delegatee.address, this.bob.address]);
156156

157157
expect(await this.votes.getDelegatedUnits(this.delegator, this.delegatee)).to.equal(20);
@@ -167,7 +167,7 @@ function shouldBehaveLikeMultiVotes(tokens, { mode = 'blocknumber', fungible = t
167167
const tx = await this.votes.connect(this.delegator).multiDelegate([this.delegatee, this.other], [1, 0]);
168168
await expect(tx).to.not.emit(this.votes, 'DelegateModified').to.not.emit(this.votes, 'DelegateVotesChanged');
169169

170-
let multiDelegates = await this.votes.multiDelegates(this.delegator);
170+
let multiDelegates = await this.votes.multiDelegates(this.delegator, 0, 100);
171171
expect([...multiDelegates]).to.have.members([this.delegatee.address, this.bob.address]);
172172

173173
expect(await this.votes.getDelegatedUnits(this.delegator, this.delegatee)).to.equal(1);
@@ -268,7 +268,7 @@ function shouldBehaveLikeMultiVotes(tokens, { mode = 'blocknumber', fungible = t
268268
.to.emit(this.votes, 'DelegateVotesChanged')
269269
.withArgs(this.delegatee, 0, 15);
270270

271-
let multiDelegates = await this.votes.multiDelegates(this.delegator);
271+
let multiDelegates = await this.votes.multiDelegates(this.delegator, 0, 100);
272272
expect([...multiDelegates]).to.have.members([this.delegatee.address]);
273273
expect(await this.votes.getDelegatedUnits(this.delegator, this.delegatee)).to.equal(15);
274274

@@ -338,7 +338,7 @@ function shouldBehaveLikeMultiVotes(tokens, { mode = 'blocknumber', fungible = t
338338
expect(log2.args.previousVotes).to.equal(0);
339339
expect(log2.args.newVotes).to.equal(15);
340340

341-
let multiDelegates = await this.votes.multiDelegates(this.delegator);
341+
let multiDelegates = await this.votes.multiDelegates(this.delegator, 0, 100);
342342
expect([...multiDelegates]).to.have.members([]);
343343
expect(await this.votes.getDelegatedUnits(this.delegator, this.other)).to.equal(0);
344344
expect(await this.votes.getVotes(this.other.address)).to.equal(15);
@@ -384,7 +384,7 @@ function shouldBehaveLikeMultiVotes(tokens, { mode = 'blocknumber', fungible = t
384384
expect(log2.args.previousVotes).to.equal(0);
385385
expect(log2.args.newVotes).to.equal(8);
386386

387-
let multiDelegates = await this.votes.multiDelegates(this.delegator);
387+
let multiDelegates = await this.votes.multiDelegates(this.delegator, 0, 100);
388388
expect([...multiDelegates]).to.have.members([]);
389389
expect(await this.votes.getDelegatedUnits(this.delegator, this.delegatee)).to.equal(0);
390390
expect(await this.votes.getVotes(this.delegatee.address)).to.equal(8);
@@ -431,6 +431,36 @@ function shouldBehaveLikeMultiVotes(tokens, { mode = 'blocknumber', fungible = t
431431
});
432432
});
433433

434+
describe('multiDelegates', function () {
435+
it('returns empty array if no partial delegation is active', async function () {
436+
expect(await this.votes.multiDelegates(this.delegator, 0, 100)).to.deep.equal([]);
437+
});
438+
439+
it('rejects if start is bigger than end', async function () {
440+
expect(this.votes.multiDelegates(this.delegator, 1, 0))
441+
.to.be.revertedWithCustomError(this.votes, 'StartIsBiggerThanEnd')
442+
.withArgs(1, 0);
443+
});
444+
445+
it('returns empty array if starts is bigger than delegations list', async function () {
446+
await this.votes.connect(this.delegator).multiDelegate([this.delegatee, this.bob], [1, 15]);
447+
expect(await this.votes.multiDelegates(this.delegator, 5, 100)).to.deep.equal([]);
448+
});
449+
450+
it('returns delegates list', async function () {
451+
await this.votes.connect(this.delegator).multiDelegate([this.delegatee, this.bob, this.alice], [1, 15, 84]);
452+
const multiDelegates = await this.votes.multiDelegates(this.delegator, 0, 2);
453+
expect([...multiDelegates]).to.have.members([this.delegatee.address, this.bob.address, this.alice.address]);
454+
})
455+
456+
it('cuts end if its bigger than delegations list', async function () {
457+
await this.votes.connect(this.delegator).multiDelegate([this.delegatee, this.bob, this.alice], [1, 15, 84]);
458+
const multiDelegates = await this.votes.multiDelegates(this.delegator, 0, 100);
459+
expect([...multiDelegates]).to.have.members([this.delegatee.address, this.bob.address, this.alice.address]);
460+
})
461+
462+
})
463+
434464
describe('burning', async function () {
435465
it('burns', async function () {
436466
await this.votes.$_burn(this.delegator, 50);

test/token/ERC20/extensions/ERC20MultiVotes.test.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ describe('ERC20MultiVotes', function () {
250250
.to.emit(this.token, 'DelegateVotesChanged')
251251
.withArgs(this.holder, 0n, supply);
252252

253-
let multiDelegates = await this.token.multiDelegates(this.holder);
253+
let multiDelegates = await this.token.multiDelegates(this.holder, 0, 100);
254254
expect([...multiDelegates]).to.have.members([this.holder.address]);
255255
expect(await this.token.getDelegatedUnits(this.holder, this.holder)).to.equal(supply);
256256
expect(await this.token.getVotes(this.holder)).to.equal(supply);
@@ -323,7 +323,7 @@ describe('ERC20MultiVotes', function () {
323323
.to.emit(this.token, 'DelegateVotesChanged')
324324
.withArgs(this.delegatee, 0, supply);
325325

326-
let multiDelegates = await this.token.multiDelegates(this.holder);
326+
let multiDelegates = await this.token.multiDelegates(this.holder, 0, 100);
327327
expect([...multiDelegates]).to.have.members([this.delegatee.address]);
328328
expect(await this.token.getDelegatedUnits(this.holder, this.delegatee)).to.equal(supply);
329329

@@ -402,7 +402,7 @@ describe('ERC20MultiVotes', function () {
402402
expect(log2.args.previousVotes).to.equal(0);
403403
expect(log2.args.newVotes).to.equal(supply);
404404

405-
let multiDelegates = await this.token.multiDelegates(this.holder);
405+
let multiDelegates = await this.token.multiDelegates(this.holder, 0, 100);
406406
expect([...multiDelegates]).to.have.members([]);
407407
expect(await this.token.getDelegatedUnits(this.holder, this.other)).to.equal(0);
408408
expect(await this.token.getVotes(this.other.address)).to.equal(supply);
@@ -465,7 +465,7 @@ describe('ERC20MultiVotes', function () {
465465
expect(log2.args.previousVotes).to.equal(0);
466466
expect(log2.args.newVotes).to.equal(supply - 1n);
467467

468-
let multiDelegates = await this.token.multiDelegates(this.holder);
468+
let multiDelegates = await this.token.multiDelegates(this.holder, 0, 100);
469469
expect([...multiDelegates]).to.have.members([]);
470470
expect(await this.token.getDelegatedUnits(this.holder, this.delegatee)).to.equal(0);
471471
expect(await this.token.getVotes(this.delegatee.address)).to.equal(supply - 1n);
@@ -563,7 +563,7 @@ describe('ERC20MultiVotes', function () {
563563
.to.emit(this.token, 'DelegateVotesChanged')
564564
.withArgs(this.delegatee, supply / 2n, supply - supply / 4n);
565565

566-
let multiDelegates = await this.token.multiDelegates(this.holder);
566+
let multiDelegates = await this.token.multiDelegates(this.holder, 0, 100);
567567
expect([...multiDelegates]).to.have.members([this.delegatee.address]);
568568
expect(await this.token.getDelegatedUnits(this.holder, this.delegatee)).to.equal(supply - supply / 4n);
569569
expect(await this.token.getVotes(this.delegatee)).to.equal(supply - supply / 4n);
@@ -580,7 +580,7 @@ describe('ERC20MultiVotes', function () {
580580
.to.emit(this.token, 'DelegateVotesChanged')
581581
.withArgs(this.delegatee, supply / 2n, supply / 4n);
582582

583-
let multiDelegates = await this.token.multiDelegates(this.holder);
583+
let multiDelegates = await this.token.multiDelegates(this.holder, 0, 100);
584584
expect([...multiDelegates]).to.have.members([this.delegatee.address]);
585585
expect(await this.token.getDelegatedUnits(this.holder, this.delegatee)).to.equal(supply / 4n);
586586
expect(await this.token.getVotes(this.delegatee)).to.equal(supply / 4n);
@@ -597,7 +597,7 @@ describe('ERC20MultiVotes', function () {
597597
.to.emit(this.token, 'DelegateVotesChanged')
598598
.withArgs(this.delegatee, supply / 2n, 0);
599599

600-
let multiDelegates = await this.token.multiDelegates(this.holder);
600+
let multiDelegates = await this.token.multiDelegates(this.holder, 0, 100);
601601
expect([...multiDelegates]).to.have.members([]);
602602
expect(await this.token.getDelegatedUnits(this.holder, this.delegatee)).to.equal(0);
603603
expect(await this.token.getVotes(this.delegatee)).to.equal(0);

0 commit comments

Comments
 (0)