1
1
import '@frequency-chain/api-augment' ;
2
2
import assert from 'assert' ;
3
- import { AddKeyData , ExtrinsicHelper } from '../scaffolding/extrinsicHelpers' ;
3
+ import { AuthorizedKeyData , ExtrinsicHelper } from '../scaffolding/extrinsicHelpers' ;
4
4
import { ethereumAddressToKeyringPair , getUnifiedAddress , getUnifiedPublicKey } from '../scaffolding/ethereum' ;
5
5
import { getFundingSource } from '../scaffolding/funding' ;
6
6
import { H160 } from '@polkadot/types/interfaces' ;
@@ -12,7 +12,7 @@ import {
12
12
createAndFundKeypair ,
13
13
createKeys ,
14
14
DOLLARS ,
15
- generateAddKeyPayload ,
15
+ generateAuthorizedKeyPayload ,
16
16
getExistentialDeposit ,
17
17
signPayloadSr25519 ,
18
18
Sr25519Signature ,
@@ -115,127 +115,163 @@ describe('MSAs Holding Tokens', function () {
115
115
} ) ;
116
116
117
117
describe ( 'withdrawTokens' , function ( ) {
118
- let keys : KeyringPair ;
118
+ let msaKeys : KeyringPair ;
119
119
let msaId : u64 ;
120
120
let msaAddress : H160 ;
121
+ let otherMsaKeys : KeyringPair ;
121
122
let secondaryKey : KeyringPair ;
122
- const defaultPayload : AddKeyData = { } ;
123
- let payload : AddKeyData ;
123
+ let defaultPayload : AuthorizedKeyData ;
124
+ let payload : AuthorizedKeyData ;
124
125
let ownerSig : Sr25519Signature ;
125
126
let badSig : Sr25519Signature ;
126
- let addKeyData : Codec ;
127
+ let authorizedKeyData : Codec ;
127
128
128
129
before ( async function ( ) {
129
130
// Setup an MSA with tokens
130
- keys = await createAndFundKeypair ( fundingSource , 5n * CENTS ) ;
131
- const { target } = await ExtrinsicHelper . createMsa ( keys ) . signAndSend ( ) ;
131
+ msaKeys = await createAndFundKeypair ( fundingSource , 5n * CENTS ) ;
132
+ let { target } = await ExtrinsicHelper . createMsa ( msaKeys ) . signAndSend ( ) ;
132
133
assert . notEqual ( target ?. data . msaId , undefined , 'MSA Id not in expected event' ) ;
133
134
msaId = target ! . data . msaId ;
134
135
136
+ // Setup another MSA control key
137
+ otherMsaKeys = await createAndFundKeypair ( fundingSource , 5n * CENTS ) ;
138
+ ( { target } = await ExtrinsicHelper . createMsa ( otherMsaKeys ) . signAndSend ( ) ) ;
139
+ assert . notEqual ( target ?. data . msaId , undefined , 'MSA Id not in expected event' ) ;
140
+
135
141
const { accountId } = await ExtrinsicHelper . apiPromise . call . msaRuntimeApi . getEthereumAddressForMsaId ( msaId ) ;
136
142
msaAddress = accountId ;
137
143
138
- secondaryKey = await createAndFundKeypair ( fundingSource , 5n * CENTS ) ;
144
+ // Create unfunded keys; this extrinsic should be free
145
+ secondaryKey = createKeys ( ) ;
139
146
140
147
// Default payload making it easier to test `withdrawTokens`
141
- defaultPayload . msaId = msaId ;
142
- defaultPayload . newPublicKey = getUnifiedPublicKey ( secondaryKey ) ;
148
+ defaultPayload = {
149
+ msaId,
150
+ authorizedPublicKey : getUnifiedPublicKey ( secondaryKey ) ,
151
+ } ;
143
152
} ) ;
144
153
145
154
beforeEach ( async function ( ) {
146
- payload = await generateAddKeyPayload ( defaultPayload ) ;
155
+ payload = await generateAuthorizedKeyPayload ( defaultPayload ) ;
147
156
} ) ;
148
157
149
158
it ( 'should fail if origin is not address contained in the payload (NotKeyOwner)' , async function ( ) {
150
- const badPayload = { ...payload , newPublicKey : getUnifiedAddress ( createKeys ( ) ) } ; // Invalid MSA ID
151
- addKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAddKeyData' , badPayload ) ;
152
- ownerSig = signPayloadSr25519 ( keys , addKeyData ) ;
153
- const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , keys , ownerSig , badPayload ) ;
154
- await assert . rejects ( op . fundAndSend ( fundingSource ) , {
155
- name : 'NotKeyOwner' ,
159
+ const badPayload = { ...payload , authorizedPublicKey : getUnifiedAddress ( createKeys ( ) ) } ; // Invalid MSA ID
160
+ authorizedKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAuthorizedKeyData' , badPayload ) ;
161
+ ownerSig = signPayloadSr25519 ( msaKeys , authorizedKeyData ) ;
162
+ const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , msaKeys , ownerSig , badPayload ) ;
163
+ await assert . rejects ( op . signAndSend ( ) , {
164
+ name : 'RpcError' ,
165
+ code : 1010 ,
166
+ data : 'Custom error: 5' , // NotKeyOwner,
156
167
} ) ;
157
168
} ) ;
158
169
159
170
it ( 'should fail if MSA owner signature is invalid (MsaOwnershipInvalidSignature)' , async function ( ) {
160
- addKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAddKeyData' , payload ) ;
161
- badSig = signPayloadSr25519 ( createKeys ( ) , addKeyData ) ; // Invalid signature
162
- const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , keys , badSig , payload ) ;
163
- await assert . rejects ( op . fundAndSend ( fundingSource ) , {
164
- name : 'MsaOwnershipInvalidSignature' ,
171
+ authorizedKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAuthorizedKeyData' , payload ) ;
172
+ badSig = signPayloadSr25519 ( createKeys ( ) , authorizedKeyData ) ; // Invalid signature
173
+ const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , msaKeys , badSig , payload ) ;
174
+ await assert . rejects ( op . signAndSend ( ) , {
175
+ name : 'RpcError' ,
176
+ code : 1010 ,
177
+ data : 'Custom error: 8' , // MsaOwnershipInvalidSignature
165
178
} ) ;
166
179
} ) ;
167
180
168
181
it ( 'should fail if expiration has passed (ProofHasExpired)' , async function ( ) {
169
- const newPayload = await generateAddKeyPayload ( {
182
+ const newPayload = await generateAuthorizedKeyPayload ( {
170
183
...defaultPayload ,
171
184
expiration : ( await ExtrinsicHelper . getLastBlock ( ) ) . block . header . number . toNumber ( ) ,
172
185
} ) ;
173
- addKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAddKeyData' , newPayload ) ;
174
- ownerSig = signPayloadSr25519 ( keys , addKeyData ) ;
175
- const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , keys , ownerSig , newPayload ) ;
176
- await assert . rejects ( op . fundAndSend ( fundingSource ) , {
177
- name : 'ProofHasExpired' ,
186
+ authorizedKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAuthorizedKeyData' , newPayload ) ;
187
+ ownerSig = signPayloadSr25519 ( msaKeys , authorizedKeyData ) ;
188
+ const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , msaKeys , ownerSig , newPayload ) ;
189
+ await assert . rejects ( op . signAndSend ( ) , {
190
+ name : 'RpcError' ,
191
+ code : 1010 ,
192
+ data : 'Custom error: 14' , // ProofHasExpired,
178
193
} ) ;
179
194
} ) ;
180
195
181
196
it ( 'should fail if expiration is not yet valid (ProofNotYetValid)' , async function ( ) {
182
197
const maxMortality = ExtrinsicHelper . api . consts . msa . mortalityWindowSize . toNumber ( ) ;
183
- const newPayload = await generateAddKeyPayload ( {
198
+ const newPayload = await generateAuthorizedKeyPayload ( {
184
199
...defaultPayload ,
185
200
expiration : ( await ExtrinsicHelper . getLastBlock ( ) ) . block . header . number . toNumber ( ) + maxMortality + 999 ,
186
201
} ) ;
187
- addKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAddKeyData' , newPayload ) ;
188
- ownerSig = signPayloadSr25519 ( keys , addKeyData ) ;
189
- const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , keys , ownerSig , newPayload ) ;
190
- await assert . rejects ( op . fundAndSend ( fundingSource ) , {
191
- name : 'ProofNotYetValid' ,
202
+ authorizedKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAuthorizedKeyData' , newPayload ) ;
203
+ ownerSig = signPayloadSr25519 ( msaKeys , authorizedKeyData ) ;
204
+ const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , msaKeys , ownerSig , newPayload ) ;
205
+ await assert . rejects ( op . signAndSend ( ) , {
206
+ name : 'RpcError' ,
207
+ code : 1010 ,
208
+ data : 'Custom error: 13' , // ProofNotYetValid,
209
+ } ) ;
210
+ } ) ;
211
+
212
+ it ( 'should fail if origin is an MSA control key (IneligibleOrigin)' , async function ( ) {
213
+ authorizedKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAuthorizedKeyData' , payload ) ;
214
+ const newPayload = await generateAuthorizedKeyPayload ( {
215
+ ...defaultPayload ,
216
+ authorizedPublicKey : getUnifiedPublicKey ( otherMsaKeys ) ,
217
+ } ) ;
218
+ authorizedKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAuthorizedKeyData' , newPayload ) ;
219
+ ownerSig = signPayloadSr25519 ( msaKeys , authorizedKeyData ) ;
220
+ const op = ExtrinsicHelper . withdrawTokens ( otherMsaKeys , msaKeys , ownerSig , newPayload ) ;
221
+ await assert . rejects ( op . signAndSend ( ) , {
222
+ name : 'RpcError' ,
223
+ code : 1010 ,
224
+ data : 'Custom error: 12' , // IneligibleOrigin,
192
225
} ) ;
193
226
} ) ;
194
227
195
228
it ( 'should fail if payload signer does not control the MSA in the signed payload (NotMsaOwner)' , async function ( ) {
196
- const newPayload = await generateAddKeyPayload ( {
229
+ const newPayload = await generateAuthorizedKeyPayload ( {
197
230
...defaultPayload ,
198
231
msaId : new u64 ( ExtrinsicHelper . api . registry , 9999 ) ,
199
232
} ) ;
200
- addKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAddKeyData' , newPayload ) ;
201
- ownerSig = signPayloadSr25519 ( keys , addKeyData ) ;
202
- const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , keys , ownerSig , newPayload ) ;
203
- await assert . rejects ( op . fundAndSend ( fundingSource ) , {
204
- name : 'NotMsaOwner' ,
233
+ authorizedKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAuthorizedKeyData' , newPayload ) ;
234
+ ownerSig = signPayloadSr25519 ( msaKeys , authorizedKeyData ) ;
235
+ const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , msaKeys , ownerSig , newPayload ) ;
236
+ await assert . rejects ( op . signAndSend ( ) , {
237
+ name : 'RpcError' ,
238
+ code : 1010 ,
239
+ data : 'Custom error: 17' , // NotMsaOwner,
205
240
} ) ;
206
241
} ) ;
207
242
208
243
it ( 'should fail if payload signer is not an MSA control key (NoKeyExists)' , async function ( ) {
209
244
const badSigner = createKeys ( ) ;
210
- const newPayload = await generateAddKeyPayload ( {
245
+ const newPayload = await generateAuthorizedKeyPayload ( {
211
246
...defaultPayload ,
212
247
msaId : new u64 ( ExtrinsicHelper . api . registry , 9999 ) ,
213
248
} ) ;
214
- addKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAddKeyData ' , newPayload ) ;
215
- ownerSig = signPayloadSr25519 ( badSigner , addKeyData ) ;
249
+ authorizedKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAuthorizedKeyData ' , newPayload ) ;
250
+ ownerSig = signPayloadSr25519 ( badSigner , authorizedKeyData ) ;
216
251
const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , badSigner , ownerSig , newPayload ) ;
217
- await assert . rejects ( op . fundAndSend ( fundingSource ) , {
218
- name : 'NoKeyExists' ,
252
+ await assert . rejects ( op . signAndSend ( ) , {
253
+ name : 'RpcError' ,
254
+ code : 1010 ,
255
+ data : 'Custom error: 16' , // NoKeyExists,
219
256
} ) ;
220
257
} ) ;
221
258
222
259
it ( 'should fail if MSA does not have a balance' , async function ( ) {
223
- addKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAddKeyData' , payload ) ;
224
- ownerSig = signPayloadSr25519 ( keys , addKeyData ) ;
225
- const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , keys , ownerSig , payload ) ;
226
- await assert . rejects ( op . fundAndSend ( fundingSource ) , {
227
- name : 'InsufficientBalanceToWithdraw' ,
260
+ authorizedKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAuthorizedKeyData' , payload ) ;
261
+ ownerSig = signPayloadSr25519 ( msaKeys , authorizedKeyData ) ;
262
+ const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , msaKeys , ownerSig , payload ) ;
263
+ await assert . rejects ( op . signAndSend ( ) , {
264
+ name : 'RpcError' ,
265
+ code : 1010 ,
266
+ data : 'Custom error: 9' , // InsufficientBalanceToWithdraw,
228
267
} ) ;
229
268
} ) ;
230
269
231
270
it ( 'should succeed' , async function ( ) {
232
- // Fund receiver with known amount to pay for transaction
233
- const startingAmount = 1n * DOLLARS ;
234
271
const transferAmount = 1n * DOLLARS ;
235
- const tertiaryKeys = await createAndFundKeypair ( fundingSource , startingAmount ) ;
236
272
const {
237
273
data : { free : startingBalance } ,
238
- } = await ExtrinsicHelper . getAccountInfo ( tertiaryKeys ) ;
274
+ } = await ExtrinsicHelper . getAccountInfo ( secondaryKey ) ;
239
275
240
276
// Send tokens to MSA
241
277
try {
@@ -249,20 +285,18 @@ describe('MSAs Holding Tokens', function () {
249
285
console . error ( 'Error sending tokens to MSA' , err . message ) ;
250
286
}
251
287
252
- const newPayload = await generateAddKeyPayload ( { ...payload , newPublicKey : getUnifiedPublicKey ( tertiaryKeys ) } ) ;
253
- addKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAddKeyData' , newPayload ) ;
254
- ownerSig = signPayloadSr25519 ( keys , addKeyData ) ;
255
- const op = ExtrinsicHelper . withdrawTokens ( tertiaryKeys , keys , ownerSig , newPayload ) ;
256
- const { eventMap } = await op . fundAndSend ( fundingSource ) ;
257
- const feeAmount = ( eventMap [ 'transactionPayment.TransactionFeePaid' ] . data as unknown as any ) . actualFee ;
288
+ authorizedKeyData = ExtrinsicHelper . api . registry . createType ( 'PalletMsaAuthorizedKeyData' , payload ) ;
289
+ ownerSig = signPayloadSr25519 ( msaKeys , authorizedKeyData ) ;
290
+ const op = ExtrinsicHelper . withdrawTokens ( secondaryKey , msaKeys , ownerSig , payload ) ;
291
+ await assert . doesNotReject ( op . signAndSend ( ) , 'token transfer transaction should have succeeded' ) ;
258
292
259
293
// Destination account should have had balance increased
260
294
const {
261
295
data : { free : endingBalance } ,
262
- } = await ExtrinsicHelper . getAccountInfo ( tertiaryKeys ) ;
296
+ } = await ExtrinsicHelper . getAccountInfo ( secondaryKey ) ;
263
297
264
298
assert (
265
- startingBalance . toBigInt ( ) + transferAmount - feeAmount . toBigInt ( ) === endingBalance . toBigInt ( ) ,
299
+ startingBalance . toBigInt ( ) + transferAmount === endingBalance . toBigInt ( ) ,
266
300
'balance of recieve should have increased by the transfer amount minus fee'
267
301
) ;
268
302
} ) ;
0 commit comments