@ocap/tx-protocols 1.17.23 → 1.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/lib/pipes/ensure-cost.js +140 -0
  2. package/lib/pipes/ensure-gas.js +53 -0
  3. package/lib/protocols/account/delegate.js +30 -3
  4. package/lib/protocols/account/migrate.js +15 -1
  5. package/lib/protocols/account/revoke-delegate.js +14 -2
  6. package/lib/protocols/asset/acquire-v2.js +29 -2
  7. package/lib/protocols/asset/acquire-v3.js +34 -2
  8. package/lib/protocols/asset/create.js +9 -10
  9. package/lib/protocols/asset/mint.js +28 -2
  10. package/lib/protocols/asset/pipes/exec-mint-hook.js +1 -1
  11. package/lib/protocols/asset/update.js +11 -2
  12. package/lib/protocols/factory/create.js +8 -9
  13. package/lib/protocols/governance/claim-stake.js +41 -4
  14. package/lib/protocols/governance/revoke-stake.js +14 -3
  15. package/lib/protocols/governance/stake.js +87 -5
  16. package/lib/protocols/rollup/claim-reward.js +46 -16
  17. package/lib/protocols/rollup/create-block.js +35 -3
  18. package/lib/protocols/rollup/create.js +8 -18
  19. package/lib/protocols/rollup/join.js +25 -2
  20. package/lib/protocols/rollup/leave.js +15 -2
  21. package/lib/protocols/rollup/migrate-contract.js +13 -2
  22. package/lib/protocols/rollup/migrate-token.js +13 -2
  23. package/lib/protocols/rollup/pause.js +13 -2
  24. package/lib/protocols/rollup/resume.js +13 -2
  25. package/lib/protocols/rollup/update.js +13 -2
  26. package/lib/protocols/token/create.js +19 -9
  27. package/lib/protocols/token/deposit-v2.js +46 -6
  28. package/lib/protocols/token/withdraw-v2.js +45 -6
  29. package/lib/protocols/trade/exchange-v2.js +38 -3
  30. package/lib/protocols/trade/transfer-v2.js +29 -2
  31. package/lib/protocols/trade/transfer-v3.js +34 -1
  32. package/lib/util.js +58 -8
  33. package/package.json +14 -13
  34. package/lib/protocols/rollup/pipes/ensure-service-fee.js +0 -37
@@ -14,7 +14,8 @@ const { toFactoryAddress } = require('@arcblock/did-util');
14
14
  const debug = require('debug')(`${require('../../../package.json').name}:create-factory`);
15
15
 
16
16
  const { decodeAnySafe } = require('../../util');
17
- const ensureServiceFee = require('../rollup/pipes/ensure-service-fee');
17
+ const EnsureTxGas = require('../../pipes/ensure-gas');
18
+ const EnsureTxCost = require('../../pipes/ensure-cost');
18
19
 
19
20
  const runner = new Runner();
20
21
 
@@ -106,17 +107,18 @@ runner.use((context, next) => {
106
107
  return next(new Error('INVALID_FACTORY_INPUT', 'Not all input.assets exist on chain'));
107
108
  });
108
109
 
109
- runner.use(ensureServiceFee);
110
+ // Ensure tx fee and gas
111
+ runner.use(EnsureTxGas(() => ({ create: 1, update: 1, payment: 0 })));
112
+ runner.use(EnsureTxCost({ attachSenderChanges: true }));
110
113
 
111
114
  // Create factory state
112
115
  runner.use(
113
116
  async (context, next) => {
114
- const { tx, itx, statedb, senderState, delegatorState, senderUpdates, vaultState, vaultUpdates, factoryProps } =
115
- context;
117
+ const { tx, itx, statedb, senderState, delegatorState, senderUpdates, factoryProps, updateVaults } = context;
116
118
  const tokens = { [context.config.token.address]: '0' };
117
119
  const owner = delegatorState ? delegatorState.address : senderState.address;
118
120
 
119
- const [newSenderState, factoryState, newVaultState] = await Promise.all([
121
+ const [newSenderState, factoryState] = await Promise.all([
120
122
  // Update owner state
121
123
  statedb.account.update(
122
124
  senderState.address,
@@ -127,14 +129,11 @@ runner.use(
127
129
  // Create factory state
128
130
  statedb.factory.create(itx.address, factory.create({ ...factoryProps, tokens, owner }, context), context),
129
131
 
130
- isEmpty(vaultUpdates)
131
- ? vaultState
132
- : statedb.account.update(vaultState.address, account.update(vaultState, vaultUpdates, context), context),
132
+ updateVaults(),
133
133
  ]);
134
134
 
135
135
  context.senderState = newSenderState;
136
136
  context.factoryState = factoryState;
137
- context.vaultState = newVaultState;
138
137
 
139
138
  debug('createFactory', factoryState);
140
139
 
@@ -6,9 +6,11 @@ const { account, asset, stake, evidence } = require('@ocap/state');
6
6
  const { getRelatedAddresses } = require('@ocap/util/lib/get-related-addr');
7
7
 
8
8
  // eslint-disable-next-line global-require
9
- const debug = require('debug')(`${require('../../../package.json').name}:acquire-asset-v2`);
9
+ const debug = require('debug')(`${require('../../../package.json').name}:claim-stake`);
10
10
 
11
- const { applyTokenUpdates } = require('../../util');
11
+ const { applyTokenUpdates, applyTokenChange } = require('../../util');
12
+ const EnsureTxGas = require('../../pipes/ensure-gas');
13
+ const EnsureTxCost = require('../../pipes/ensure-cost');
12
14
 
13
15
  const runner = new Runner();
14
16
 
@@ -132,10 +134,37 @@ runner.use(pipes.ExtractState({ from: 'assets', to: 'assetStates', status: 'OK',
132
134
  runner.use(pipes.VerifyTransferrable({ assets: 'assetStates' }));
133
135
  runner.use(pipes.VerifyUpdater({ assetKey: 'assetStates', ownerKey: 'stakeState' }));
134
136
 
137
+ // Ensure tx fee and gas
138
+ runner.use(
139
+ EnsureTxGas((context) => {
140
+ const result = { create: 1, update: 2, payment: 0 };
141
+ if (context.receiverStates) {
142
+ result.update += context.receiverStates.length;
143
+ }
144
+ if (context.assetStates) {
145
+ result.update += context.assetStates.length;
146
+ }
147
+
148
+ return result;
149
+ })
150
+ );
151
+ runner.use(EnsureTxCost({ attachSenderChanges: true }));
152
+
135
153
  // 8. update statedb
136
154
  runner.use(
137
155
  async (context, next) => {
138
- const { tx, itx, outputs, statedb, senderState, stakeState, receiverStates, assetStates = [] } = context;
156
+ const {
157
+ tx,
158
+ itx,
159
+ outputs,
160
+ statedb,
161
+ senderState,
162
+ senderChange,
163
+ stakeState,
164
+ receiverStates,
165
+ updateVaults,
166
+ assetStates = [],
167
+ } = context;
139
168
 
140
169
  const receiverUpdates = {};
141
170
  const assetUpdates = {};
@@ -150,6 +179,9 @@ runner.use(
150
179
  // Update receiver balance
151
180
  const ownerState = receiverStates.find((s) => getRelatedAddresses(s).includes(owner));
152
181
  receiverUpdates[ownerState.address] = applyTokenUpdates(tokens, ownerState, 'add');
182
+ if (senderChange && ownerState.address === senderChange.address) {
183
+ receiverUpdates[ownerState.address] = applyTokenChange(receiverUpdates[ownerState.address], senderChange);
184
+ }
153
185
 
154
186
  // Update asset owner
155
187
  assets.forEach((a) => {
@@ -170,7 +202,10 @@ runner.use(
170
202
  senderState.address,
171
203
  account.update(
172
204
  senderState,
173
- Object.assign({ nonce: tx.nonce }, receiverUpdates[senderState.address] || {}),
205
+ Object.assign(
206
+ { nonce: tx.nonce },
207
+ receiverUpdates[senderState.address] || (senderChange ? applyTokenChange(senderState, senderChange) : {})
208
+ ),
174
209
  context
175
210
  ),
176
211
  context
@@ -201,6 +236,8 @@ runner.use(
201
236
  evidence.create({ hash: itx.evidence.hash, data: 'claim-stake' }, context),
202
237
  context
203
238
  ),
239
+
240
+ updateVaults(),
204
241
  ]);
205
242
 
206
243
  context.senderState = newSenderState;
@@ -5,9 +5,11 @@ const { account, stake } = require('@ocap/state');
5
5
  const { getRelatedAddresses } = require('@ocap/util/lib/get-related-addr');
6
6
 
7
7
  // eslint-disable-next-line global-require
8
- const debug = require('debug')(`${require('../../../package.json').name}:acquire-asset-v2`);
8
+ const debug = require('debug')(`${require('../../../package.json').name}:revoke-stake`);
9
9
 
10
10
  const { applyTokenUpdates } = require('../../util');
11
+ const EnsureTxGas = require('../../pipes/ensure-gas');
12
+ const EnsureTxCost = require('../../pipes/ensure-cost');
11
13
 
12
14
  const runner = new Runner();
13
15
 
@@ -93,10 +95,14 @@ runner.use(pipes.ExtractState({ from: 'assets', to: 'assetStates', status: 'OK',
93
95
  runner.use(pipes.VerifyTransferrable({ assets: 'assetStates' }));
94
96
  runner.use(pipes.VerifyUpdater({ assetKey: 'assetStates', ownerKey: 'stakeState' }));
95
97
 
98
+ // Ensure tx fee and gas
99
+ runner.use(EnsureTxGas(() => ({ create: 0, update: 2, payment: 0 })));
100
+ runner.use(EnsureTxCost({ attachSenderChanges: true }));
101
+
96
102
  // 8. update statedb
97
103
  runner.use(
98
104
  async (context, next) => {
99
- const { tx, itx, outputs, statedb, senderState, stakeState } = context;
105
+ const { tx, itx, outputs, statedb, senderState, senderUpdates, stakeState, updateVaults } = context;
100
106
 
101
107
  const stakeUpdates = {
102
108
  tokens: stakeState.tokens || {},
@@ -119,8 +125,13 @@ runner.use(
119
125
  });
120
126
 
121
127
  const [newSenderState, newStakeState] = await Promise.all([
122
- statedb.account.update(senderState.address, account.update(senderState, { nonce: tx.nonce }, context), context),
128
+ statedb.account.update(
129
+ senderState.address,
130
+ account.update(senderState, { nonce: tx.nonce, ...senderUpdates }, context),
131
+ context
132
+ ),
123
133
  statedb.stake.update(stakeState.address, stake.update(stakeState, stakeUpdates, context), context),
134
+ updateVaults(),
124
135
  ]);
125
136
 
126
137
  context.senderState = newSenderState;
@@ -3,14 +3,18 @@ const { promisify } = require('util');
3
3
  const isEmpty = require('empty-value');
4
4
  const { Joi } = require('@arcblock/validator');
5
5
  const { CustomError: Error } = require('@ocap/util/lib/error');
6
+ const { BN, fromTokenToUnit } = require('@ocap/util');
6
7
  const { Runner, pipes } = require('@ocap/tx-pipeline');
7
8
  const { toStakeAddress } = require('@arcblock/did-util');
8
9
  const { account, asset, stake } = require('@ocap/state');
9
10
 
10
11
  // eslint-disable-next-line global-require
11
- const debug = require('debug')(`${require('../../../package.json').name}:acquire-asset-v2`);
12
+ const debug = require('debug')(`${require('../../../package.json').name}:stake`);
12
13
 
13
- const { applyTokenUpdates } = require('../../util');
14
+ const { applyTokenUpdates, applyTokenChange, isGasStakeAddress, isGasStakeInput } = require('../../util');
15
+
16
+ const EnsureTxGas = require('../../pipes/ensure-gas');
17
+ const EnsureTxCost = require('../../pipes/ensure-cost');
14
18
 
15
19
  const verifyAssetOwner = promisify(pipes.VerifyUpdater({ assetKey: 'assets', ownerKey: 'owner' }));
16
20
 
@@ -94,10 +98,79 @@ runner.use(async (context, next) => {
94
98
  return next();
95
99
  });
96
100
 
101
+ // 8. handle tx gas stakes
102
+ runner.use(async (context, next) => {
103
+ const { tx, itx, inputs, config } = context;
104
+ const { token, transaction } = config;
105
+ const { minStake, maxStake } = transaction.txGas;
106
+
107
+ // FIXME: delegation not supported here
108
+ context.isGasStake = isGasStakeAddress(tx.from, itx.address) && isGasStakeInput(inputs, token.address);
109
+
110
+ if (context.isGasStake) {
111
+ const [tokenInput] = inputs[0].tokensList;
112
+ const actualStake = new BN(tokenInput.value);
113
+ const expectedMinStake = fromTokenToUnit(minStake, token.decimal);
114
+ const expectedMaxStake = fromTokenToUnit(maxStake, token.decimal);
115
+ if (actualStake.lt(expectedMinStake)) {
116
+ return next(new Error('INVALID_TX', `Stake for gas should be greater than: ${minStake}`));
117
+ }
118
+ if (actualStake.gt(expectedMaxStake)) {
119
+ return next(new Error('INVALID_TX', `Stake for gas should be less than: ${maxStake}`));
120
+ }
121
+ }
122
+
123
+ if (context.isGasStake) {
124
+ context.revokeWaitingPeriod = transaction.txGas.stakeLockPeriod;
125
+ } else {
126
+ context.revokeWaitingPeriod = itx.revokeWaitingPeriod;
127
+ }
128
+
129
+ return next();
130
+ });
131
+
132
+ // Ensure tx fee and gas
133
+ runner.use(
134
+ EnsureTxGas((context) => {
135
+ // FIXME: payment check
136
+ const result = { create: 0, update: 0, payment: 0 };
137
+ if (context.senderState) {
138
+ result.update += 1;
139
+ } else {
140
+ result.create += 1;
141
+ }
142
+ if (context.stakeState) {
143
+ result.update += 1;
144
+ } else {
145
+ result.create += 1;
146
+ }
147
+ if (context.signerStates) {
148
+ result.update += context.signerStates.length;
149
+ }
150
+ if (context.assetStates) {
151
+ result.update += context.assetStates.length;
152
+ }
153
+
154
+ return result;
155
+ })
156
+ );
157
+ runner.use(EnsureTxCost({ attachSenderChanges: true }));
158
+
97
159
  // update statedb
98
160
  runner.use(
99
161
  async (context, next) => {
100
- const { tx, itx, inputs, statedb, senderState, stakeState, signerStates, assetStates = [] } = context;
162
+ const {
163
+ tx,
164
+ itx,
165
+ inputs,
166
+ statedb,
167
+ senderState,
168
+ senderChange,
169
+ stakeState,
170
+ signerStates,
171
+ updateVaults,
172
+ assetStates = [],
173
+ } = context;
101
174
 
102
175
  const signerUpdates = {};
103
176
  const stakeUpdates = stakeState
@@ -111,6 +184,9 @@ runner.use(
111
184
  signerStates.find((s) => s.address === owner),
112
185
  'sub'
113
186
  );
187
+ if (senderChange && owner === senderChange.address) {
188
+ signerUpdates[owner] = applyTokenChange(signerUpdates[owner], senderChange);
189
+ }
114
190
  Object.assign(stakeUpdates, applyTokenUpdates(tokensList, stakeUpdates, 'add'));
115
191
  stakeUpdates.assets.push(...assetsList);
116
192
  });
@@ -123,7 +199,10 @@ runner.use(
123
199
  senderState,
124
200
  account.updateOrCreate(
125
201
  senderState,
126
- Object.assign({ address: tx.from, nonce: tx.nonce, pk: tx.pk }, signerUpdates[tx.from] || {}),
202
+ Object.assign(
203
+ { address: tx.from, nonce: tx.nonce, pk: tx.pk },
204
+ signerUpdates[tx.from] || (senderChange ? applyTokenChange(senderState, senderChange) : {})
205
+ ),
127
206
  context
128
207
  ),
129
208
  context
@@ -145,7 +224,8 @@ runner.use(
145
224
  {
146
225
  sender: tx.from,
147
226
  revocable: !itx.locked,
148
- ...pick(itx, ['address', 'receiver', 'message', 'data', 'revokeWaitingPeriod']),
227
+ revokeWaitingPeriod: context.revokeWaitingPeriod,
228
+ ...pick(itx, ['address', 'receiver', 'message', 'data']),
149
229
  ...stakeUpdates,
150
230
  },
151
231
  context
@@ -159,6 +239,8 @@ runner.use(
159
239
  statedb.asset.update(x.address, asset.update(x, { owner: itx.address }, context), context)
160
240
  )
161
241
  ),
242
+
243
+ updateVaults(),
162
244
  ]);
163
245
 
164
246
  context.senderState = newSenderState;
@@ -12,6 +12,8 @@ const debug = require('debug')(`${require('../../../package.json').name}:claim-b
12
12
 
13
13
  const { toStakeAddress } = require('@arcblock/did-util');
14
14
  const VerifySigners = require('./pipes/verify-signers');
15
+ const EnsureTxGas = require('../../pipes/ensure-gas');
16
+ const EnsureTxCost = require('../../pipes/ensure-cost');
15
17
  const { applyTokenChange, splitTxFee, getBNSum, getRewardLocker, RATE_BASE } = require('../../util');
16
18
 
17
19
  const runner = new Runner();
@@ -211,10 +213,40 @@ runner.use((context, next) => {
211
213
  return next();
212
214
  });
213
215
 
216
+ // Ensure tx fee and gas
217
+ runner.use(
218
+ EnsureTxGas((context) => {
219
+ const result = { create: 2, update: 1, payment: 0 };
220
+
221
+ result.update += context.accountStates.length;
222
+ if (context.updates[context.lockerState.address]) {
223
+ result.update += 1;
224
+ }
225
+ if (context.updates[context.stakeState.address]) {
226
+ result.update += 1;
227
+ }
228
+
229
+ return result;
230
+ })
231
+ );
232
+ runner.use(EnsureTxCost({ attachSenderChanges: true }));
233
+
214
234
  // 10. update state
215
235
  runner.use(
216
236
  async (context, next) => {
217
- const { tx, itx, updates, statedb, senderState, blockState, lockerState, stakeState, accountStates } = context;
237
+ const {
238
+ tx,
239
+ itx,
240
+ updates,
241
+ statedb,
242
+ senderState,
243
+ blockState,
244
+ lockerState,
245
+ stakeState,
246
+ accountStates,
247
+ senderChange,
248
+ updateVaults,
249
+ } = context;
218
250
 
219
251
  const [newStakeStates, newAccountStates, newBlockState] = await Promise.all([
220
252
  // update stake states
@@ -232,20 +264,15 @@ runner.use(
232
264
 
233
265
  // update accounts(proposer, publisher, validator)
234
266
  Promise.all(
235
- accountStates.map((x) =>
236
- statedb.account.update(
237
- x.address,
238
- account.update(
239
- x,
240
- Object.assign(
241
- x.address === senderState.address ? { nonce: tx.nonce } : {},
242
- applyTokenChange(x, updates.account[x.address])
243
- ),
244
- context
245
- ),
246
- context
247
- )
248
- )
267
+ accountStates.map((x) => {
268
+ let updateSet = applyTokenChange(x, updates.account[x.address]);
269
+ if (x.address === senderState.address) {
270
+ updateSet.nonce = tx.nonce;
271
+ updateSet = Object.assign(updateSet, senderChange ? applyTokenChange(updateSet, senderChange) : {});
272
+ }
273
+
274
+ return statedb.account.update(x.address, account.update(x, updateSet, context), context);
275
+ })
249
276
  ),
250
277
 
251
278
  // Update block state, just update the context
@@ -262,6 +289,8 @@ runner.use(
262
289
  evidence.create({ hash: itx.blockHash, data: 'rollup-claim-block-reward' }, context),
263
290
  context
264
291
  ),
292
+
293
+ updateVaults(),
265
294
  ]);
266
295
 
267
296
  // to avoid this to be incorrectly indexed
@@ -271,7 +300,8 @@ runner.use(
271
300
  context.accountStates = newAccountStates;
272
301
  context.blockState = newBlockState;
273
302
 
274
- context.updatedAccounts = cloneDeep([...Object.values(updates.account), ...Object.values(updates.stake)]);
303
+ context.updatedAccounts.push(...cloneDeep(Object.values(updates.account)));
304
+ context.updatedAccounts.push(...cloneDeep(Object.values(updates.stake)));
275
305
 
276
306
  debug('claim-block-reward', itx);
277
307
 
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable indent */
2
2
  const pick = require('lodash/pick');
3
+ const cloneDeep = require('lodash/cloneDeep');
3
4
  const { CustomError: Error } = require('@ocap/util/lib/error');
4
5
  const MerkleTree = require('@ocap/merkle-tree');
5
6
  const { Joi, schemas, patterns } = require('@arcblock/validator');
@@ -14,6 +15,9 @@ const debug = require('debug')(`${require('../../../package.json').name}:create-
14
15
  const VerifySigners = require('./pipes/verify-signers');
15
16
  const VerifyEvidence = require('./pipes/verify-evidence');
16
17
  const VerifyPaused = require('./pipes/verify-paused');
18
+ const EnsureTxGas = require('../../pipes/ensure-gas');
19
+ const EnsureTxCost = require('../../pipes/ensure-cost');
20
+
17
21
  const { applyTokenChange, ensureBlockReward, getRewardLocker } = require('../../util');
18
22
 
19
23
  const runner = new Runner();
@@ -246,10 +250,35 @@ runner.use((context, next) => {
246
250
  });
247
251
  runner.use(pipes.ExtractState({ from: 'senders', to: 'senderStates', status: 'INVALID_SENDER_STATE', table: 'account' })); // prettier-ignore
248
252
 
253
+ // Ensure tx fee and gas
254
+ runner.use(
255
+ EnsureTxGas((context) => {
256
+ const result = { create: 1, update: 2, payment: 0 };
257
+
258
+ result.update += context.stakeStates.filter((x) => context.stakeUpdates[x.address]).length;
259
+ result.update += context.txStates.length;
260
+ result.update += (context.senderStates || []).length;
261
+
262
+ return result;
263
+ })
264
+ );
265
+ runner.use(EnsureTxCost({ attachSenderChanges: true }));
266
+
249
267
  // 11. update state: mint tokens for deposits, burn tokens for withdraws
250
268
  runner.use(
251
269
  async (context, next) => {
252
- const { tx, itx, statedb, rollupState, senderState, stakeStates, txStates, formattedItx } = context;
270
+ const {
271
+ tx,
272
+ itx,
273
+ statedb,
274
+ rollupState,
275
+ senderState,
276
+ stakeStates,
277
+ txStates,
278
+ formattedItx,
279
+ senderUpdates,
280
+ updateVaults,
281
+ } = context;
253
282
  const senderStates = context.senderStates || [];
254
283
 
255
284
  const [newSenderState, newStakeStates, newSenderStates, newRollupState, rollupBlockState, newTxStates] =
@@ -257,7 +286,7 @@ runner.use(
257
286
  // update sender(proposer) account
258
287
  statedb.account.update(
259
288
  senderState.address,
260
- account.update(senderState, Object.assign({ nonce: tx.nonce }), context),
289
+ account.update(senderState, { nonce: tx.nonce, ...senderUpdates }, context),
261
290
  context
262
291
  ),
263
292
 
@@ -312,6 +341,8 @@ runner.use(
312
341
  Promise.all(
313
342
  txStates.map((x) => statedb.tx.update(x.hash, Tx.update(x, { finalized: true, tx: x.tx }), context))
314
343
  ),
344
+
345
+ updateVaults(),
315
346
  ]);
316
347
 
317
348
  context.senderState = newSenderState;
@@ -321,7 +352,8 @@ runner.use(
321
352
  context.rollupBlockState = rollupBlockState;
322
353
  context.txStates = newTxStates;
323
354
 
324
- context.updatedAccounts = [...Object.values(context.stakeUpdates), ...Object.values(context.accountUpdates)];
355
+ context.updatedAccounts.push(...cloneDeep(Object.values(context.stakeUpdates)));
356
+ context.updatedAccounts.push(...cloneDeep(Object.values(context.accountUpdates)));
325
357
 
326
358
  debug('create-rollup-block', { itx, updatedAccounts: context.updatedAccounts });
327
359
 
@@ -12,7 +12,8 @@ const { toRollupAddress } = require('@arcblock/did-util');
12
12
  const debug = require('debug')(`${require('../../../package.json').name}:create-rollup`);
13
13
 
14
14
  const { decodeAnySafe } = require('../../util');
15
- const ensureServiceFee = require('./pipes/ensure-service-fee');
15
+ const EnsureTxGas = require('../../pipes/ensure-gas');
16
+ const EnsureTxCost = require('../../pipes/ensure-cost');
16
17
 
17
18
  const runner = new Runner();
18
19
 
@@ -108,25 +109,17 @@ runner.use(
108
109
  ])
109
110
  );
110
111
 
111
- runner.use(ensureServiceFee);
112
+ // Ensure tx fee and gas
113
+ runner.use(EnsureTxGas(() => ({ create: 1, update: 1, payment: 0 })));
114
+ runner.use(EnsureTxCost({ attachSenderChanges: true }));
112
115
 
113
116
  // 5. create rollup state
114
117
  runner.use(
115
118
  async (context, next) => {
116
- const {
117
- tx,
118
- formattedItx,
119
- rollupData,
120
- statedb,
121
- senderState,
122
- delegatorState,
123
- senderUpdates,
124
- vaultState,
125
- vaultUpdates,
126
- } = context;
119
+ const { tx, formattedItx, rollupData, statedb, senderState, delegatorState, senderUpdates, updateVaults } = context;
127
120
 
128
121
  const issuer = delegatorState ? delegatorState.address : senderState.address;
129
- const [newSenderState, rollupState, newVaultState] = await Promise.all([
122
+ const [newSenderState, rollupState] = await Promise.all([
130
123
  statedb.account.update(
131
124
  senderState.address,
132
125
  account.update(senderState, { nonce: tx.nonce, ...senderUpdates }, context),
@@ -147,9 +140,7 @@ runner.use(
147
140
  context
148
141
  ),
149
142
 
150
- isEmpty(vaultUpdates)
151
- ? vaultState
152
- : statedb.account.update(vaultState.address, account.update(vaultState, vaultUpdates, context), context),
143
+ updateVaults(),
153
144
  ]);
154
145
 
155
146
  // FIXME: create-rollup 的时候不能校验 stake,还是在这里创建 stake?如果在这里创建 stake,是否需要多签?
@@ -157,7 +148,6 @@ runner.use(
157
148
 
158
149
  context.senderState = newSenderState;
159
150
  context.rollupState = rollupState;
160
- context.vaultState = newVaultState;
161
151
 
162
152
  debug('create-rollup', rollupState);
163
153
 
@@ -15,6 +15,8 @@ const debug = require('debug')(`${require('../../../package.json').name}:join-ro
15
15
  const VerifySigners = require('./pipes/verify-signers');
16
16
  const VerifyEvidence = require('./pipes/verify-evidence');
17
17
  const VerifyPaused = require('./pipes/verify-paused');
18
+ const EnsureTxGas = require('../../pipes/ensure-gas');
19
+ const EnsureTxCost = require('../../pipes/ensure-cost');
18
20
 
19
21
  const runner = new Runner();
20
22
 
@@ -110,14 +112,33 @@ runner.use(
110
112
  );
111
113
  runner.use(pipes.VerifyAccountMigration({ signerKey: 'signerStates', senderKey: 'senderState' }));
112
114
 
115
+ // Ensure tx fee and gas
116
+ runner.use(EnsureTxGas(() => ({ create: 1, update: 3, payment: 0 })));
117
+ runner.use(EnsureTxCost({ attachSenderChanges: true }));
118
+
113
119
  // 8. update state
114
120
  runner.use(
115
121
  async (context, next) => {
116
- const { tx, itx, rollupState, statedb, senderState, stakeState, newValidator, stakeAddress } = context;
122
+ const {
123
+ tx,
124
+ itx,
125
+ rollupState,
126
+ statedb,
127
+ senderState,
128
+ stakeState,
129
+ newValidator,
130
+ stakeAddress,
131
+ senderUpdates,
132
+ updateVaults,
133
+ } = context;
117
134
  const newValidators = rollupState.validators.concat([newValidator]);
118
135
 
119
136
  const [newSenderState, newRollupState, newStakeState, evidenceState] = await Promise.all([
120
- statedb.account.update(senderState.address, account.update(senderState, { nonce: tx.nonce }, context), context),
137
+ statedb.account.update(
138
+ senderState.address,
139
+ account.update(senderState, { nonce: tx.nonce, ...senderUpdates }, context),
140
+ context
141
+ ),
121
142
 
122
143
  // persist new validators list
123
144
  statedb.rollup.update(
@@ -139,6 +160,8 @@ runner.use(
139
160
  evidence.create({ hash: itx.evidence.hash, data: 'rollup-join' }, context),
140
161
  context
141
162
  ),
163
+
164
+ updateVaults(),
142
165
  ]);
143
166
 
144
167
  context.senderState = newSenderState;
@@ -12,6 +12,8 @@ const debug = require('debug')(`${require('../../../package.json').name}:leave-r
12
12
  const VerifySigners = require('./pipes/verify-signers');
13
13
  const VerifyEvidence = require('./pipes/verify-evidence');
14
14
  const VerifyPaused = require('./pipes/verify-paused');
15
+ const EnsureTxGas = require('../../pipes/ensure-gas');
16
+ const EnsureTxCost = require('../../pipes/ensure-cost');
15
17
 
16
18
  const runner = new Runner();
17
19
 
@@ -85,14 +87,23 @@ runner.use(
85
87
  );
86
88
  runner.use(pipes.VerifyAccountMigration({ signerKey: 'signerStates', senderKey: 'senderState' }));
87
89
 
90
+ // Ensure tx fee and gas
91
+ runner.use(EnsureTxGas(() => ({ create: 1, update: 3, payment: 0 })));
92
+ runner.use(EnsureTxCost({ attachSenderChanges: true }));
93
+
88
94
  // 8. update state
89
95
  runner.use(
90
96
  async (context, next) => {
91
- const { tx, itx, rollupState, statedb, senderState, stakeState, stakeAddress } = context;
97
+ const { tx, itx, rollupState, statedb, senderState, stakeState, stakeAddress, senderUpdates, updateVaults } =
98
+ context;
92
99
  const newValidators = rollupState.validators.filter((x) => x.address !== tx.from);
93
100
 
94
101
  const [newSenderState, newRollupState, newStakeState, evidenceState] = await Promise.all([
95
- statedb.account.update(senderState.address, account.update(senderState, { nonce: tx.nonce }, context), context),
102
+ statedb.account.update(
103
+ senderState.address,
104
+ account.update(senderState, { nonce: tx.nonce, ...senderUpdates }, context),
105
+ context
106
+ ),
96
107
 
97
108
  // persist new validators list
98
109
  statedb.rollup.update(
@@ -110,6 +121,8 @@ runner.use(
110
121
  evidence.create({ hash: itx.evidence.hash, data: 'rollup-leave' }, context),
111
122
  context
112
123
  ),
124
+
125
+ updateVaults(),
113
126
  ]);
114
127
 
115
128
  context.senderState = newSenderState;