Skip to content

Commit bc1a2d3

Browse files
authored
Support multiple voucher signers (#480)
1 parent fe6ea09 commit bc1a2d3

File tree

2 files changed

+25
-21
lines changed

2 files changed

+25
-21
lines changed

contracts/statechannels/AllocationExchange.sol

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,12 @@ contract AllocationExchange is Governed {
3838

3939
IStaking private immutable staking;
4040
IGraphToken private immutable graphToken;
41-
address public authority;
42-
43-
// Tracks redeemed allocationIDs. An allocation can only be redeemed once.
41+
mapping(address => bool) public authority;
4442
mapping(address => bool) public allocationsRedeemed;
4543

4644
// -- Events
4745

48-
event AuthoritySet(address indexed account);
46+
event AuthoritySet(address indexed account, bool authorized);
4947
event AllocationRedeemed(address indexed allocationID, uint256 amount);
5048
event TokensWithdrawn(address indexed to, uint256 amount);
5149

@@ -69,7 +67,7 @@ contract AllocationExchange is Governed {
6967

7068
graphToken = _graphToken;
7169
staking = _staking;
72-
_setAuthority(_authority);
70+
_setAuthority(_authority, true);
7371
}
7472

7573
/**
@@ -97,25 +95,27 @@ contract AllocationExchange is Governed {
9795
* @notice Set the authority allowed to sign vouchers.
9896
* @dev Only the governor can set the authority
9997
* @param _authority Address of the signing authority
98+
* @param _authorized True if the authority is authorized to sign vouchers, false to unset
10099
*/
101-
function setAuthority(address _authority) external onlyGovernor {
102-
_setAuthority(_authority);
100+
function setAuthority(address _authority, bool _authorized) external onlyGovernor {
101+
_setAuthority(_authority, _authorized);
103102
}
104103

105104
/**
106105
* @notice Set the authority allowed to sign vouchers.
107106
* @param _authority Address of the signing authority
107+
* @param _authorized True if the authority is authorized to sign vouchers, false to unset
108108
*/
109-
function _setAuthority(address _authority) private {
109+
function _setAuthority(address _authority, bool _authorized) private {
110110
require(_authority != address(0), "Exchange: empty authority");
111111
// This will help catch some operational errors but not all.
112112
// The validation will fail under the following conditions:
113113
// - a contract in construction
114114
// - an address where a contract will be created
115115
// - an address where a contract lived, but was destroyed
116116
require(!Address.isContract(_authority), "Exchange: authority must be EOA");
117-
authority = _authority;
118-
emit AuthoritySet(authority);
117+
authority[_authority] = _authorized;
118+
emit AuthoritySet(_authority, _authorized);
119119
}
120120

121121
/**
@@ -155,10 +155,8 @@ contract AllocationExchange is Governed {
155155

156156
// Signature check
157157
bytes32 messageHash = keccak256(abi.encodePacked(_voucher.allocationID, _voucher.amount));
158-
require(
159-
authority == ECDSA.recover(messageHash, _voucher.signature),
160-
"Exchange: invalid signer"
161-
);
158+
address voucherSigner = ECDSA.recover(messageHash, _voucher.signature);
159+
require(authority[voucherSigner], "Exchange: invalid signer");
162160

163161
// Mark allocation as collected
164162
allocationsRedeemed[_voucher.allocationID] = true;

test/payments/allocationExchange.test.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ describe('AllocationExchange', () => {
7878

7979
// Ensure the exchange is correctly setup
8080
await staking.connect(governor.signer).setAssetHolder(allocationExchange.address, true)
81-
await allocationExchange.connect(governor.signer).setAuthority(authority.address)
81+
await allocationExchange.connect(governor.signer).setAuthority(authority.address, true)
8282
await allocationExchange.approveAll()
8383
})
8484

@@ -114,21 +114,27 @@ describe('AllocationExchange', () => {
114114

115115
describe('config', function () {
116116
it('should set an authority', async function () {
117+
// Set authority
117118
const newAuthority = randomAddress()
118-
const tx = allocationExchange.connect(governor.signer).setAuthority(newAuthority)
119-
await expect(tx).emit(allocationExchange, 'AuthoritySet').withArgs(newAuthority)
120-
expect(await allocationExchange.authority()).eq(newAuthority)
119+
const tx1 = allocationExchange.connect(governor.signer).setAuthority(newAuthority, true)
120+
await expect(tx1).emit(allocationExchange, 'AuthoritySet').withArgs(newAuthority, true)
121+
expect(await allocationExchange.authority(newAuthority)).eq(true)
122+
123+
// Unset authority
124+
const tx2 = allocationExchange.connect(governor.signer).setAuthority(newAuthority, false)
125+
await expect(tx2).emit(allocationExchange, 'AuthoritySet').withArgs(newAuthority, false)
126+
expect(await allocationExchange.authority(newAuthority)).eq(false)
121127
})
122128

123129
it('reject set an authority if not allowed', async function () {
124130
const newAuthority = randomAddress()
125-
const tx = allocationExchange.connect(indexer.signer).setAuthority(newAuthority)
131+
const tx = allocationExchange.connect(indexer.signer).setAuthority(newAuthority, true)
126132
await expect(tx).revertedWith(' Only Governor can call')
127133
})
128134

129135
it('reject set an empty authority', async function () {
130136
const newAuthority = AddressZero
131-
const tx = allocationExchange.connect(governor.signer).setAuthority(newAuthority)
137+
const tx = allocationExchange.connect(governor.signer).setAuthority(newAuthority, true)
132138
await expect(tx).revertedWith('Exchange: empty authority')
133139
})
134140

@@ -225,7 +231,7 @@ describe('AllocationExchange', () => {
225231
const allocationID = '0xfefefefefefefefefefefefefefefefefefefefe'
226232

227233
// Ensure the exchange is correctly setup
228-
await allocationExchange.connect(governor.signer).setAuthority(authority.address)
234+
await allocationExchange.connect(governor.signer).setAuthority(authority.address, true)
229235
await allocationExchange.approveAll()
230236

231237
// Initiate a withdrawal

0 commit comments

Comments
 (0)