11/* globals artifacts */
22
3+ const { BN } = require ( "bn.js" ) ;
34const chai = require ( "chai" ) ;
45const bnChai = require ( "bn-chai" ) ;
56const { ethers } = require ( "ethers" ) ;
@@ -16,6 +17,7 @@ const {
1617 forwardTime,
1718 getBlockTime,
1819 expectEvent,
20+ encodeTxData,
1921} = require ( "../../helpers/test-helper" ) ;
2022
2123const { setupRandomColony, getMetaTransactionParameters } = require ( "../../helpers/test-data-generator" ) ;
@@ -28,10 +30,12 @@ chai.use(bnChai(web3.utils.BN));
2830const EtherRouter = artifacts . require ( "EtherRouter" ) ;
2931const IColonyNetwork = artifacts . require ( "IColonyNetwork" ) ;
3032const IReputationMiningCycle = artifacts . require ( "IReputationMiningCycle" ) ;
33+ const IVotingReputation = artifacts . require ( "IVotingReputation" ) ;
3134const Korporatio = artifacts . require ( "Korporatio" ) ;
3235const TokenLocking = artifacts . require ( "TokenLocking" ) ;
3336
3437const KORPORATIO = soliditySha3 ( "Korporatio" ) ;
38+ const VOTING_REPUTATION = soliditySha3 ( "VotingReputation" ) ;
3539
3640contract ( "Korporatio" , ( accounts ) => {
3741 let colony ;
@@ -60,8 +64,6 @@ contract("Korporatio", (accounts) => {
6064 const USER2 = accounts [ 2 ] ;
6165 const MINER = accounts [ 5 ] ;
6266
63- const APPLICATION_FEE = WAD . muln ( 6500 ) ;
64-
6567 before ( async ( ) => {
6668 const etherRouter = await EtherRouter . deployed ( ) ;
6769 colonyNetwork = await IColonyNetwork . at ( etherRouter . address ) ;
@@ -168,32 +170,34 @@ contract("Korporatio", (accounts) => {
168170 await checkErrorRevert ( korporatio . deprecate ( true , { from : USER1 } ) , "ds-auth-unauthorized" ) ;
169171 await checkErrorRevert ( korporatio . uninstall ( { from : USER1 } ) , "ds-auth-unauthorized" ) ;
170172 } ) ;
173+
174+ it ( "cannot create applications unless initialised" , async ( ) => {
175+ await checkErrorRevert (
176+ korporatio . createApplication ( domain1Key , domain1Value , domain1Mask , domain1Siblings , user0Key , user0Value , user0Mask , user0Siblings , {
177+ from : USER0 ,
178+ } ) ,
179+ "korporatio-not-initialised"
180+ ) ;
181+ } ) ;
171182 } ) ;
172183
173184 describe ( "creating applications" , async ( ) => {
174185 beforeEach ( async ( ) => {
175- await korporatio . initialise ( token . address , APPLICATION_FEE , WAD . divn ( 100 ) , SECONDS_PER_DAY , { from : USER0 } ) ;
176-
177186 await colony . approveStake ( korporatio . address , 1 , WAD , { from : USER0 } ) ;
187+
188+ await korporatio . initialise ( WAD . divn ( 100 ) , SECONDS_PER_DAY , { from : USER0 } ) ;
178189 } ) ;
179190
180191 it ( "can query for configuration params" , async ( ) => {
181- const paymentToken = await korporatio . getPaymentToken ( ) ;
182- const applicationFee = await korporatio . getApplicationFee ( ) ;
183192 const stakeFraction = await korporatio . getStakeFraction ( ) ;
184193 const claimDelay = await korporatio . getClaimDelay ( ) ;
185194
186- expect ( paymentToken ) . to . equal ( token . address ) ;
187- expect ( applicationFee ) . to . eq . BN ( APPLICATION_FEE ) ;
188195 expect ( stakeFraction ) . to . eq . BN ( WAD . divn ( 100 ) ) ;
189196 expect ( claimDelay ) . to . eq . BN ( SECONDS_PER_DAY ) ;
190197 } ) ;
191198
192199 it ( "cannot set configuration params if not root architect" , async ( ) => {
193- await checkErrorRevert (
194- korporatio . initialise ( token . address , APPLICATION_FEE , WAD . divn ( 100 ) , SECONDS_PER_DAY , { from : USER1 } ) ,
195- "korporatio-not-root-architect"
196- ) ;
200+ await checkErrorRevert ( korporatio . initialise ( WAD . divn ( 100 ) , SECONDS_PER_DAY , { from : USER1 } ) , "korporatio-not-root-architect" ) ;
197201 } ) ;
198202
199203 it ( "can create an application" , async ( ) => {
@@ -225,7 +229,7 @@ contract("Korporatio", (accounts) => {
225229 } ) ;
226230
227231 it ( "cannot create an application with insufficient rep" , async ( ) => {
228- await korporatio . initialise ( token . address , APPLICATION_FEE , WAD , SECONDS_PER_DAY , { from : USER0 } ) ;
232+ await korporatio . initialise ( WAD , SECONDS_PER_DAY , { from : USER0 } ) ;
229233
230234 await checkErrorRevert (
231235 korporatio . createApplication ( domain1Key , domain1Value , domain1Mask , domain1Siblings , user0Key , user0Value , user0Mask , user0Siblings , {
@@ -256,7 +260,7 @@ contract("Korporatio", (accounts) => {
256260 const applicationId = await korporatio . getNumApplications ( ) ;
257261
258262 // Only applicant can cancel
259- await checkErrorRevert ( korporatio . cancelApplication ( applicationId , { from : USER1 } ) , "korporatio-cannot-cancel " ) ;
263+ await checkErrorRevert ( korporatio . cancelApplication ( applicationId , { from : USER1 } ) , "korporatio-not-applicant " ) ;
260264
261265 const tx = await korporatio . cancelApplication ( applicationId , { from : USER0 } ) ;
262266 const blockTime = await getBlockTime ( tx . receipt . blockNumber ) ;
@@ -278,7 +282,7 @@ contract("Korporatio", (accounts) => {
278282
279283 await forwardTime ( SECONDS_PER_DAY , this ) ;
280284
281- await korporatio . reclaimStake ( applicationId ) ;
285+ await korporatio . reclaimStake ( applicationId , { from : USER0 } ) ;
282286
283287 const obligation = await colony . getObligation ( USER0 , korporatio . address , 1 ) ;
284288 expect ( obligation ) . to . be . zero ;
@@ -331,6 +335,28 @@ contract("Korporatio", (accounts) => {
331335 await checkErrorRevert ( korporatio . slashStake ( applicationId , false , { from : USER2 } ) , "korporatio-caller-not-arbitration" ) ;
332336 } ) ;
333337
338+ it ( "can reclaim a stake via arbitration if the extension is deleted" , async ( ) => {
339+ const korporatioAddress = korporatio . address ;
340+ await korporatio . createApplication ( domain1Key , domain1Value , domain1Mask , domain1Siblings , user0Key , user0Value , user0Mask , user0Siblings , {
341+ from : USER0 ,
342+ } ) ;
343+
344+ const lockPre = await tokenLocking . getUserLock ( token . address , USER0 ) ;
345+ const obligationPre = await colony . getObligation ( USER0 , korporatioAddress , 1 ) ;
346+ expect ( obligationPre ) . to . eq . BN ( WAD . divn ( 100 ) . muln ( 3 ) ) ;
347+
348+ await colony . uninstallExtension ( KORPORATIO , { from : USER0 } ) ;
349+
350+ await colony . transferStake ( 1 , UINT256_MAX , korporatioAddress , USER0 , 1 , obligationPre , USER0 , { from : USER1 } ) ;
351+
352+ const lockPost = await tokenLocking . getUserLock ( token . address , USER0 ) ;
353+ const obligationPost = await colony . getObligation ( USER0 , korporatioAddress , 1 ) ;
354+
355+ // Obligation is zeroed out, but token balance is unchanged
356+ expect ( obligationPost ) . to . be . zero ;
357+ expect ( new BN ( lockPre . balance ) ) . to . eq . BN ( lockPost . balance ) ;
358+ } ) ;
359+
334360 it ( "can update an application" , async ( ) => {
335361 await korporatio . createFreeApplication ( { from : USER0 } ) ;
336362
@@ -348,27 +374,56 @@ contract("Korporatio", (accounts) => {
348374 await checkErrorRevert ( korporatio . updateApplication ( applicationId , ipfsHash , { from : USER0 } ) , "korporatio-stake-cancelled" ) ;
349375 } ) ;
350376
351- it ( "can submit an application and pay the fee" , async ( ) => {
352- await token . mint ( USER0 , APPLICATION_FEE ) ;
353- await token . approve ( korporatio . address , APPLICATION_FEE ) ;
354-
377+ it ( "can submit an application" , async ( ) => {
355378 await korporatio . createFreeApplication ( { from : USER0 } ) ;
356379
357380 const applicationId = await korporatio . getNumApplications ( ) ;
358- const ipfsHash = soliditySha3 ( "IPFS Hash" ) ;
359381
360382 // Cannot submit if not root
361- await checkErrorRevert ( korporatio . submitApplication ( applicationId , ipfsHash , { from : USER1 } ) , "korporatio-caller-not-root" ) ;
383+ await checkErrorRevert ( korporatio . submitApplication ( applicationId , { from : USER1 } ) , "korporatio-caller-not-root" ) ;
384+
385+ const tx = await korporatio . submitApplication ( applicationId , { from : USER0 } ) ;
386+ await expectEvent ( tx , "ApplicationSubmitted" , [ applicationId ] ) ;
387+
388+ // Cannot submit twice
389+ await checkErrorRevert ( korporatio . submitApplication ( applicationId , { from : USER0 } ) , "korporatio-stake-cancelled" ) ;
390+ } ) ;
391+
392+ it ( "can submit an application via a motion" , async ( ) => {
393+ await colony . installExtension ( VOTING_REPUTATION , 9 ) ;
394+ const votingAddress = await colonyNetwork . getExtensionInstallation ( VOTING_REPUTATION , colony . address ) ;
395+ await colony . setArbitrationRole ( 1 , UINT256_MAX , votingAddress , 1 , true ) ;
396+ await colony . setRootRole ( votingAddress , true ) ;
397+ const voting = await IVotingReputation . at ( votingAddress ) ;
398+
399+ await voting . initialise ( WAD . divn ( 1000 ) , 0 , 0 , WAD , SECONDS_PER_DAY , SECONDS_PER_DAY , SECONDS_PER_DAY , SECONDS_PER_DAY ) ;
400+
401+ await korporatio . createFreeApplication ( { from : USER0 } ) ;
402+ const applicationId = await korporatio . getNumApplications ( ) ;
403+
404+ const action = await encodeTxData ( korporatio , "submitApplication" , [ applicationId ] ) ;
405+
406+ // Can't create a motion in a subdomain
407+ await colony . addDomain ( 1 , UINT256_MAX , 1 ) ;
408+ await checkErrorRevert (
409+ voting . createMotion ( 2 , UINT256_MAX , korporatio . address , action , domain1Key , domain1Value , domain1Mask , domain1Siblings ) ,
410+ "voting-rep-invalid-domain-id"
411+ ) ;
412+
413+ // Only in the root domain
414+ await voting . createMotion ( 1 , UINT256_MAX , korporatio . address , action , domain1Key , domain1Value , domain1Mask , domain1Siblings ) ;
415+ const motionId = await voting . getMotionCount ( ) ;
362416
363- const tx = await korporatio . submitApplication ( applicationId , ipfsHash , { from : USER0 } ) ;
364- await expectEvent ( tx , "ApplicationSubmitted" , [ applicationId , ipfsHash ] ) ;
417+ await colony . approveStake ( voting . address , 1 , WAD , { from : USER0 } ) ;
418+ await voting . stakeMotion ( motionId , 1 , UINT256_MAX , 1 , WAD . muln ( 3 ) . divn ( 1000 ) , user0Key , user0Value , user0Mask , user0Siblings , { from : USER0 } ) ;
365419
366- const metaColonyAddress = await colonyNetwork . getMetaColony ( ) ;
367- const metaColonyBalance = await token . balanceOf ( metaColonyAddress ) ;
368- expect ( metaColonyBalance ) . to . eq . BN ( APPLICATION_FEE ) ;
420+ await forwardTime ( SECONDS_PER_DAY , this ) ;
369421
370- // Cannot submit once cancelled
371- await checkErrorRevert ( korporatio . submitApplication ( applicationId , ipfsHash , { from : USER0 } ) , "korporatio-stake-cancelled" ) ;
422+ const tx = await voting . finalizeMotion ( motionId ) ;
423+ const finalizedAt = await getBlockTime ( tx . blockNumber ) ;
424+
425+ const application = await korporatio . getApplication ( applicationId ) ;
426+ expect ( application . cancelledAt ) . to . eq . BN ( finalizedAt ) ;
372427 } ) ;
373428
374429 it ( "can submit a stake via metatransactions" , async ( ) => {
0 commit comments