-
Notifications
You must be signed in to change notification settings - Fork 239
Expand file tree
/
Copy pathdisputable_app.js
More file actions
334 lines (261 loc) · 12 KB
/
Copy pathdisputable_app.js
File metadata and controls
334 lines (261 loc) · 12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
const { toChecksumAddress } = require('web3-utils')
const { assertRevert } = require('../../../helpers/assertThrow')
const { getEventArgument } = require('../../../helpers/events')
const { getNewProxyAddress } = require('../../../helpers/events')
const { decodeEventsOfType } = require('../../../helpers/decodeEvent')
const { assertEvent, assertAmountOfEvents } = require('../../../helpers/assertEvent')(web3)
const ACL = artifacts.require('ACL')
const Kernel = artifacts.require('Kernel')
const DAOFactory = artifacts.require('DAOFactory')
const AgreementMock = artifacts.require('AgreementMock')
const DisputableApp = artifacts.require('DisputableAppMock')
const EVMScriptRegistryFactory = artifacts.require('EVMScriptRegistryFactory')
contract('DisputableApp', ([_, owner, agreement, anotherAgreement, someone]) => {
let disputable, disputableBase, dao, acl
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
const DISPUTABLE_INTERFACE = '0x737c65f9'
const ERC165_INTERFACE = '0x01ffc9a7'
before('deploy DAO', async () => {
const kernelBase = await Kernel.new(true)
const aclBase = await ACL.new()
const registryFactory = await EVMScriptRegistryFactory.new()
const daoFact = await DAOFactory.new(kernelBase.address, aclBase.address, registryFactory.address)
const receipt = await daoFact.newDAO(owner)
dao = await Kernel.at(getEventArgument(receipt, 'DeployDAO', 'dao'))
acl = await ACL.at(await dao.acl())
disputableBase = await DisputableApp.new()
const APP_MANAGER_ROLE = await kernelBase.APP_MANAGER_ROLE()
await acl.createPermission(owner, dao.address, APP_MANAGER_ROLE, owner, { from: owner })
const SET_AGREEMENT_ROLE = await kernelBase.SET_AGREEMENT_ROLE()
await acl.createPermission(owner, dao.address, SET_AGREEMENT_ROLE, owner, { from: owner })
})
beforeEach('install disputable app', async () => {
const initializeData = disputableBase.contract.initialize.getData()
const receipt = await dao.newAppInstance('0x1234', disputableBase.address, initializeData, false, { from: owner })
disputable = await DisputableApp.at(getNewProxyAddress(receipt))
})
describe('supportsInterface', () => {
it('supports ERC165', async () => {
assert.isTrue(await disputable.supportsInterface(ERC165_INTERFACE), 'does not support ERC165')
assert.equal(await disputable.ERC165_INTERFACE(), ERC165_INTERFACE, 'ERC165 interface ID does not match')
assert.equal(await disputable.erc165interfaceID(), await disputable.ERC165_INTERFACE(), 'ERC165 interface ID does not match')
})
it('supports IDisputable', async () => {
assert.isTrue(await disputable.supportsInterface(DISPUTABLE_INTERFACE), 'does not support IDisputable')
assert.equal(await disputable.interfaceID(), DISPUTABLE_INTERFACE)
assert.equal(await disputable.DISPUTABLE_INTERFACE(), await disputable.interfaceID(), 'IDisputable interface ID does not match')
})
it('does not support 0xffffffff', async () => {
assert.isFalse(await disputable.supportsInterface('0xffffffff'), 'should not support 0xffffffff')
})
})
describe('setAgreement', () => {
context('when the sender has permissions', () => {
const from = owner
const itSetsTheAgreementAddress = agreement => {
it('sets the agreement', async () => {
await dao.setAgreement(disputable.address, agreement, { from })
const currentAgreement = await disputable.getAgreement()
assert.equal(currentAgreement, agreement, 'disputable agreement does not match')
})
it('emits an event', async () => {
const { tx } = await dao.setAgreement(disputable.address, agreement, { from })
const receipt = await web3.eth.getTransactionReceipt(tx)
const logs = decodeEventsOfType(receipt, DisputableApp.abi, 'AgreementSet')
assertAmountOfEvents({ logs }, 'AgreementSet')
assertEvent({ logs }, 'AgreementSet', { agreement: toChecksumAddress(agreement) })
})
}
context('when the agreement was not set', () => {
context('when trying to set a new the agreement', () => {
itSetsTheAgreementAddress(agreement)
})
context('when trying to unset the agreement', () => {
it('reverts', async () => {
await assertRevert(dao.setAgreement(disputable.address, ZERO_ADDRESS, { from }), 'DISPUTABLE_AGREEMENT_STATE_INVAL')
})
})
})
context('when the agreement was already set', () => {
beforeEach('set agreement', async () => {
await dao.setAgreement(disputable.address, agreement, { from })
})
context('when trying to re-set the agreement', () => {
it('reverts', async () => {
await assertRevert(dao.setAgreement(disputable.address, agreement, { from }), 'DISPUTABLE_AGREEMENT_STATE_INVAL')
})
})
context('when trying to set a new agreement', () => {
it('reverts', async () => {
await assertRevert(dao.setAgreement(disputable.address, anotherAgreement, { from }), 'DISPUTABLE_AGREEMENT_STATE_INVAL')
})
})
context('when trying to unset the agreement', () => {
it('reverts', async () => {
await assertRevert(dao.setAgreement(disputable.address, ZERO_ADDRESS, { from }), 'DISPUTABLE_AGREEMENT_STATE_INVAL')
})
})
})
})
context('when the sender does not have permissions', () => {
const from = someone
context('when going through the kernel', () => {
it('reverts', async () => {
await assertRevert(dao.setAgreement(disputable.address, agreement, { from }), 'KERNEL_AUTH_FAILED')
})
})
context('when going through the disputable', () => {
it('reverts', async () => {
await assertRevert(disputable.setAgreement(agreement, { from }), 'DISPUTABLE_SENDER_NOT_KERNEL')
})
})
})
})
describe('newAction', () => {
context('when the agreement is not set', () => {
it('reverts', async () => {
await assertRevert(disputable.newAction(0, '0x00', owner), 'DISPUTABLE_AGREEMENT_STATE_INVAL')
})
})
context('when the agreement is set', () => {
let agreement
beforeEach('set agreement', async () => {
agreement = await AgreementMock.new()
await dao.setAgreement(disputable.address, agreement.address, { from: owner })
})
it('does not revert', async () => {
await disputable.newAction(0, '0x00', owner)
})
it('receives ETH when sent', async () => {
const previousBalance = await web3.eth.getBalance(agreement.address)
await disputable.newAction(0, '0x00', owner, { value: 1e18 })
const currentBalance = await web3.eth.getBalance(agreement.address)
assert.equal(currentBalance.sub(previousBalance).toString(), 1e18, 'agreement balance does not match')
})
})
})
describe('closeAction', () => {
context('when the agreement is not set', () => {
it('reverts', async () => {
await assertRevert(disputable.closeAction(0), 'DISPUTABLE_AGREEMENT_STATE_INVAL')
})
})
context('when the agreement is set', () => {
beforeEach('set agreement', async () => {
const agreement = await AgreementMock.new()
await dao.setAgreement(disputable.address, agreement.address, { from: owner })
})
it('does not revert', async () => {
await disputable.closeAction(0)
})
})
})
describe('onDisputableActionChallenged', () => {
const disputableId = 0, challengeId = 0, challenger = owner
context('when the agreement was already set', () => {
const agreement = someone
beforeEach('set agreement', async () => {
await dao.setAgreement(disputable.address, agreement, { from: owner })
})
context('when the sender is the agreement', () => {
const from = agreement
it('does not fails', async () => {
const receipt = await disputable.onDisputableActionChallenged(disputableId, challengeId, challenger, { from })
assertAmountOfEvents(receipt, 'DisputableChallenged')
})
})
context('when the sender is not the agreement', () => {
const from = owner
it('reverts', async () => {
await assertRevert(disputable.onDisputableActionChallenged(disputableId, challengeId, challenger, { from }), 'DISPUTABLE_SENDER_NOT_AGREEMENT')
})
})
})
context('when the agreement was not set', () => {
it('reverts', async () => {
await assertRevert(disputable.onDisputableActionChallenged(disputableId, challengeId, challenger, { from: someone }), 'DISPUTABLE_SENDER_NOT_AGREEMENT')
})
})
})
describe('onDisputableActionAllowed', () => {
const disputableId = 0
context('when the agreement was already set', () => {
const agreement = someone
beforeEach('set agreement', async () => {
await dao.setAgreement(disputable.address, agreement, { from: owner })
})
context('when the sender is the agreement', () => {
const from = agreement
it('does not fails', async () => {
const receipt = await disputable.onDisputableActionAllowed(disputableId, { from })
assertAmountOfEvents(receipt, 'DisputableAllowed')
})
})
context('when the sender is not the agreement', () => {
const from = owner
it('reverts', async () => {
await assertRevert(disputable.onDisputableActionAllowed(disputableId, { from }), 'DISPUTABLE_SENDER_NOT_AGREEMENT')
})
})
})
context('when the agreement was not set', () => {
it('reverts', async () => {
await assertRevert(disputable.onDisputableActionAllowed(disputableId, { from: someone }), 'DISPUTABLE_SENDER_NOT_AGREEMENT')
})
})
})
describe('onDisputableActionRejected', () => {
const disputableId = 0
context('when the agreement was already set', () => {
const agreement = someone
beforeEach('set agreement', async () => {
await dao.setAgreement(disputable.address, agreement, { from: owner })
})
context('when the sender is the agreement', () => {
const from = agreement
it('does not fails', async () => {
const receipt = await disputable.onDisputableActionRejected(disputableId, { from })
assertAmountOfEvents(receipt, 'DisputableRejected')
})
})
context('when the sender is not the agreement', () => {
const from = owner
it('reverts', async () => {
await assertRevert(disputable.onDisputableActionRejected(disputableId, { from }), 'DISPUTABLE_SENDER_NOT_AGREEMENT')
})
})
})
context('when the agreement was not set', () => {
it('reverts', async () => {
await assertRevert(disputable.onDisputableActionRejected(disputableId, { from: someone }), 'DISPUTABLE_SENDER_NOT_AGREEMENT')
})
})
})
describe('onDisputableActionVoided', () => {
const disputableId = 0
context('when the agreement was already set', () => {
const agreement = someone
beforeEach('set agreement', async () => {
await dao.setAgreement(disputable.address, agreement, { from: owner })
})
context('when the sender is the agreement', () => {
const from = agreement
it('does not fails', async () => {
const receipt = await disputable.onDisputableActionVoided(disputableId, { from })
assertAmountOfEvents(receipt, 'DisputableVoided')
})
})
context('when the sender is not the agreement', () => {
const from = owner
it('reverts', async () => {
await assertRevert(disputable.onDisputableActionVoided(disputableId, { from }), 'DISPUTABLE_SENDER_NOT_AGREEMENT')
})
})
})
context('when the agreement was not set', () => {
it('reverts', async () => {
await assertRevert(disputable.onDisputableActionVoided(disputableId, { from: someone }), 'DISPUTABLE_SENDER_NOT_AGREEMENT')
})
})
})
})