@kasufinance/kasu-sdk 2.7.0 → 2.7.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.
@@ -51,10 +51,21 @@ import { WaitableTransaction } from './observable';
51
51
  * their mind, and telling them something broke would be a lie. Only a WALLET
52
52
  * call is ever classified that way: the HTTP ports are always `'failed'`,
53
53
  * because a backend that words a refusal "declined" did not involve the
54
- * lender's wallet. A reverted gas estimate on the request step
55
- * (`isUnpredictableGas`) is `'insufficient-balance'` — nothing was refused, the
56
- * transaction simply cannot succeed as composed. Everything else is `'failed'`
57
- * and carries the original error for the consumer's crash reporter.
54
+ * lender's wallet. A revert on the request step is read for WHAT reverted: a
55
+ * protocol error the ABI declares is `'reverted'` with the name, and only a
56
+ * token balance or allowance failure — or a revert nothing can decode — stays
57
+ * `'insufficient-balance'`. Everything else is `'failed'` and carries the
58
+ * original error for the consumer's crash reporter.
59
+ *
60
+ * ## Both signatures are checked before they are used
61
+ *
62
+ * A wallet is not obliged to hand back 65 bytes, and `encodeDepositData` will
63
+ * not catch one that does not: `defaultAbiCoder` encodes any even-length hex
64
+ * as `bytes`, `0x` included, so a malformed acceptance signature becomes a
65
+ * `depositData` blob that is broadcast, mined, and then can never be verified
66
+ * by the agreements service. Both personal signs are therefore length-checked
67
+ * where they are taken, and a bad one fails the step it was taken on rather
68
+ * than the one it would eventually have broken.
58
69
  *
59
70
  * ```ts
60
71
  * const flow = new DepositFlow(ports);
@@ -93,6 +104,22 @@ export type DepositFailure = {
93
104
  step: 'request';
94
105
  reason: 'insufficient-balance';
95
106
  error: unknown;
107
+ } | {
108
+ step: 'request';
109
+ reason: 'reverted';
110
+ /**
111
+ * The custom error the contract reverted with, exactly as the ABI
112
+ * declares it — `'ClearingIsPending'`, `'LendingPoolIsStopped'`,
113
+ * `'UserNotKycd'`, and the rest of
114
+ * `ILendingPoolManagerAbi` / `IKasuAllowListAbi`.
115
+ *
116
+ * Render `reverted` with generic copy and special-case only the
117
+ * names you have words for: a contract upgrade can add an error, and
118
+ * a consumer that assumed the set was closed would have nothing to
119
+ * show for the new one.
120
+ */
121
+ revertError: string;
122
+ error: unknown;
96
123
  } | {
97
124
  step: 'request';
98
125
  reason: 'contract-expired';
@@ -254,6 +281,10 @@ export interface DepositState {
254
281
  export declare const CONTRACT_TTL_MS: number;
255
282
  /** What a run without a spender, from either source, fails with. */
256
283
  export declare const NO_SPENDER_MESSAGE = "DepositFlow: no ERC-20 spender; build the flow with kasu.flows.deposit() or pass `spender` on the input";
284
+ /** What a malformed auth signature fails the generate step with. */
285
+ export declare const INVALID_AUTH_SIGNATURE_MESSAGE = "DepositFlow: the wallet returned a malformed authentication signature; expected 65 bytes of 0x-prefixed hex";
286
+ /** What a malformed acceptance signature fails the confirm step with. */
287
+ export declare const INVALID_ACCEPTANCE_SIGNATURE_MESSAGE = "DepositFlow: the wallet returned a malformed acceptance signature; expected 65 bytes of 0x-prefixed hex";
257
288
  export declare class DepositFlow extends Flow<DepositState, DepositFlowInput> {
258
289
  private readonly _ports;
259
290
  private readonly _ttlMs;
@@ -7,13 +7,31 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ import { utils } from 'ethers';
10
11
  import { asContractType, buildLegacyContractRequestMessage, buildLoanAgreementSignMessage, encodeDepositData, } from '../domain/loan-contract';
12
+ import { decodeRevert } from '../domain/revert-errors';
11
13
  import { classifyWalletFailure, isUnpredictableGas, } from '../domain/wallet-errors';
12
14
  import { Flow } from './flow';
13
15
  /** Generated agreements are valid for five minutes upstream. */
14
16
  export const CONTRACT_TTL_MS = 5 * 60 * 1000;
15
17
  /** What a run without a spender, from either source, fails with. */
16
18
  export const NO_SPENDER_MESSAGE = 'DepositFlow: no ERC-20 spender; build the flow with kasu.flows.deposit() or pass `spender` on the input';
19
+ /** What a malformed auth signature fails the generate step with. */
20
+ export const INVALID_AUTH_SIGNATURE_MESSAGE = 'DepositFlow: the wallet returned a malformed authentication signature; expected 65 bytes of 0x-prefixed hex';
21
+ /** What a malformed acceptance signature fails the confirm step with. */
22
+ export const INVALID_ACCEPTANCE_SIGNATURE_MESSAGE = 'DepositFlow: the wallet returned a malformed acceptance signature; expected 65 bytes of 0x-prefixed hex';
23
+ /**
24
+ * Is this an EIP-191 personal sign, in the only shape the protocol accepts?
25
+ *
26
+ * 65 bytes — `r`, `s`, `v` — 0x-prefixed. Nothing downstream checks it: the
27
+ * ABI coder takes any even-length hex as `bytes`, so `'0x'` and a 64-byte
28
+ * string both encode happily into a `depositData` the agreements service then
29
+ * cannot verify against anything. The check has to happen where the signature
30
+ * is taken, which is here.
31
+ */
32
+ function isPersonalSignature(signature) {
33
+ return utils.isHexString(signature, 65);
34
+ }
17
35
  const INITIAL = {
18
36
  phase: 'idle',
19
37
  step: null,
@@ -38,13 +56,32 @@ function badgeFor(step, approvalRequired) {
38
56
  };
39
57
  }
40
58
  /**
41
- * The request step has a third outcome. `UNPREDICTABLE_GAS_LIMIT` here is
42
- * almost always `transferFrom` reverting on a balance that cannot cover the
43
- * deposit, and it takes precedence: nothing was refused by the lender, so
44
- * inviting a retry would just reproduce it.
59
+ * The request step's extra outcomes, in the order the evidence supports.
60
+ *
61
+ * A revert is read for WHAT reverted before it is read as a shortfall.
62
+ * `requestDepositWithKyc` reverts for a whole family of declared reasons —
63
+ * `LendingPoolIsStopped`, `ClearingIsPending`, `UserNotKycd`, `UserBlocked`,
64
+ * `UserNotInAllowList`, `InvalidTranche`, `BlockExpired` — and every one of
65
+ * them used to arrive as `insufficient-balance`, which told a fully funded
66
+ * lender to top up a wallet that was never short while their pool was simply
67
+ * mid-clearing. So: a decoded protocol error is `reverted` and names itself.
68
+ *
69
+ * Only a token balance or allowance failure — or revert data nothing can
70
+ * decode, on the `UNPREDICTABLE_GAS_LIMIT` ethers raises for a failed gas
71
+ * estimate — is still `insufficient-balance`, which is the case that reason
72
+ * was named for and the one where topping up is genuinely the answer.
45
73
  */
46
74
  function classifyRequest(err) {
47
- if (isUnpredictableGas(err)) {
75
+ const revert = decodeRevert(err);
76
+ if ((revert === null || revert === void 0 ? void 0 : revert.family) === 'protocol') {
77
+ return {
78
+ step: 'request',
79
+ reason: 'reverted',
80
+ revertError: revert.name,
81
+ error: err,
82
+ };
83
+ }
84
+ if (revert !== null || isUnpredictableGas(err)) {
48
85
  return { step: 'request', reason: 'insufficient-balance', error: err };
49
86
  }
50
87
  return classifyWalletFailure('request', err);
@@ -96,6 +133,18 @@ export class DepositFlow extends Flow {
96
133
  this._store.patch(Object.assign({ phase: 'accepting-sign' }, badgeFor('confirm', this._store.state.approvalRequired)), token);
97
134
  try {
98
135
  const signature = yield this._ports.signMessage(contract.contractMessage);
136
+ // Checked HERE, not at the encoder: this is the signature the
137
+ // agreements service verifies the deposit against, and a wallet
138
+ // that returned something other than 65 bytes has not signed
139
+ // anything. Failing the confirm step names the step that produced
140
+ // it; letting it through would put an unverifiable blob on chain.
141
+ if (!isPersonalSignature(signature)) {
142
+ bridge.settle({
143
+ kind: 'failed',
144
+ error: new Error(INVALID_ACCEPTANCE_SIGNATURE_MESSAGE),
145
+ });
146
+ return;
147
+ }
99
148
  bridge.settle({ kind: 'accepted', signature });
100
149
  }
101
150
  catch (err) {
@@ -189,6 +238,18 @@ export class DepositFlow extends Flow {
189
238
  this._fail(token, approvalRequired, classifyWalletFailure('generate', err));
190
239
  return;
191
240
  }
241
+ // The same EIP-191 shape as the acceptance, and the same reason to
242
+ // check it: kasu-backend verifies this one to decide whether to issue
243
+ // an agreement at all, so a malformed signature is a 4xx that says
244
+ // nothing about which step produced it. Named here instead.
245
+ if (!isPersonalSignature(signature)) {
246
+ this._fail(token, approvalRequired, {
247
+ step: 'generate',
248
+ reason: 'failed',
249
+ error: new Error(INVALID_AUTH_SIGNATURE_MESSAGE),
250
+ });
251
+ return;
252
+ }
192
253
  if (!this._store.isCurrent(token))
193
254
  return;
194
255
  // 3. Generate — POST the request.
@@ -245,12 +306,29 @@ export class DepositFlow extends Flow {
245
306
  });
246
307
  return;
247
308
  }
248
- const depositData = encodeDepositData({
249
- signature: outcome.signature,
250
- timestamp: contract.timestamp,
251
- contractVersion: contract.contractVersion,
252
- contractType: asContractType(contract.contractType),
253
- });
309
+ // The acceptance signature is already known to be 65 bytes, but the
310
+ // encoder also reads `timestamp`, `contractVersion` and
311
+ // `contractType` off a response the SDK did not produce. `start()`
312
+ // promises it does not reject, so anything that throws in here becomes
313
+ // a failure the consumer can render rather than an unhandled rejection
314
+ // in an application that was told it never had to catch one.
315
+ let depositData;
316
+ try {
317
+ depositData = encodeDepositData({
318
+ signature: outcome.signature,
319
+ timestamp: contract.timestamp,
320
+ contractVersion: contract.contractVersion,
321
+ contractType: asContractType(contract.contractType),
322
+ });
323
+ }
324
+ catch (err) {
325
+ this._fail(token, approvalRequired, {
326
+ step: 'request',
327
+ reason: 'failed',
328
+ error: err,
329
+ });
330
+ return;
331
+ }
254
332
  // 6. Approve — the EXACT amount, never `MaxUint256`. House rule: an
255
333
  // unlimited allowance outlives the deposit it was granted for, and a
256
334
  // later exploit of the spender would drain a wallet that has long
@@ -1 +1 @@
1
- {"version":3,"file":"deposit-flow.js","sourceRoot":"","sources":["../../src/flows/deposit-flow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deposit-flow.js","sourceRoot":"","sources":["../../src/flows/deposit-flow.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAa,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE1C,OAAO,EACH,cAAc,EACd,iCAAiC,EACjC,6BAA6B,EAC7B,iBAAiB,GAEpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EACH,qBAAqB,EACrB,kBAAkB,GACrB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAuT9B,gEAAgE;AAChE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAE7C,oEAAoE;AACpE,MAAM,CAAC,MAAM,kBAAkB,GAC3B,yGAAyG,CAAC;AAE9G,oEAAoE;AACpE,MAAM,CAAC,MAAM,8BAA8B,GACvC,6GAA6G,CAAC;AAElH,yEAAyE;AACzE,MAAM,CAAC,MAAM,oCAAoC,GAC7C,yGAAyG,CAAC;AAE9G;;;;;;;;GAQG;AACH,SAAS,mBAAmB,CAAC,SAAkB;IAC3C,OAAO,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,OAAO,GAAiB;IAC1B,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,IAAI;IACV,SAAS,EAAE,CAAC;IACZ,SAAS,EAAE,CAAC;IACZ,gBAAgB,EAAE,IAAI;IACtB,QAAQ,EAAE,IAAI;IACd,OAAO,EAAE,IAAI;CAChB,CAAC;AAuBF,8EAA8E;AAC9E,SAAS,WAAW,CAAC,IAAiB,EAAE,gBAAyB;IAC7D,MAAM,KAAK,GAAkB,gBAAgB;QACzC,CAAC,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC;QAC/C,CAAC,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IACzC,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,QAAQ,CACb,IAAiB,EACjB,gBAAyB;IAEzB,OAAO;QACH,IAAI;QACJ,SAAS,EAAE,WAAW,CAAC,IAAI,EAAE,gBAAgB,CAAC;QAC9C,SAAS,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACtC,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,SAAS,eAAe,CAAC,GAAY;IACjC,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,MAAK,UAAU,EAAE,CAAC;QAChC,OAAO;YACH,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,UAAU;YAClB,WAAW,EAAE,MAAM,CAAC,IAAI;YACxB,KAAK,EAAE,GAAG;SACb,CAAC;IACN,CAAC;IACD,IAAI,MAAM,KAAK,IAAI,IAAI,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,sBAAsB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IAC3E,CAAC;IACD,OAAO,qBAAqB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;AACjD,CAAC;AAED,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E,MAAM,OAAO,WAAY,SAAQ,IAAoC;IAyBjE,YACqB,MAAoB,EACrC,IAAyB;;QAEzB,KAAK,CAAC,OAAO,CAAC,CAAC;QAHE,WAAM,GAAN,MAAM,CAAc;QArBzC;;;;;WAKG;QACK,YAAO,GAAwD,IAAI,CAAC;QAE5E;;;;;;;;;WASG;QACK,kBAAa,GAAkB,IAAI,CAAC;QAOxC,IAAI,CAAC,MAAM,GAAG,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,aAAa,mCAAI,eAAe,CAAC;QACrD,IAAI,CAAC,eAAe,GAAG,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,OAAO,CAAC;QACrC,qEAAqE;QACrE,8DAA8D;QAC9D,IAAI,CAAC,IAAI,GAAG,GAAW,EAAE,eAAC,OAAA,MAAA,MAAA,MAAM,CAAC,GAAG,sDAAI,mCAAI,IAAI,CAAC,GAAG,EAAE,CAAA,EAAA,CAAC;IAC3D,CAAC;IAED;;;OAGG;IACG,cAAc;;YAChB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;YAC5C,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,YAAY,EAAE;gBAAE,OAAO;YACxD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;YACrC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,KAAK,iBAET,KAAK,EAAE,gBAAgB,IACpB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,GAE9D,KAAK,CACR,CAAC;YACF,IAAI,CAAC;gBACD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAC3C,QAAQ,CAAC,eAAe,CAC3B,CAAC;gBACF,8DAA8D;gBAC9D,gEAAgE;gBAChE,6DAA6D;gBAC7D,kEAAkE;gBAClE,kEAAkE;gBAClE,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC;oBAClC,MAAM,CAAC,MAAM,CAAC;wBACV,IAAI,EAAE,QAAQ;wBACd,KAAK,EAAE,IAAI,KAAK,CAAC,oCAAoC,CAAC;qBACzD,CAAC,CAAC;oBACH,OAAO;gBACX,CAAC;gBACD,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;YACnD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,6DAA6D;gBAC7D,6CAA6C;gBAC7C,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAClD,CAAC;oBAAS,CAAC;gBACP,iEAAiE;gBACjE,gEAAgE;gBAChE,IAAI,IAAI,CAAC,aAAa,KAAK,KAAK;oBAAE,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAChE,CAAC;QACL,CAAC;KAAA;IAED;;;;;;;OAOG;IACH,eAAe;QACX,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE;YAAE,OAAO;QAC3C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,8EAA8E;IACtE,YAAY;QAChB,OAAO,CACH,IAAI,CAAC,aAAa,KAAK,IAAI;YAC3B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAC5C,CAAC;IACN,CAAC;IAED,kEAAkE;IAC/C,UAAU;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,0EAA0E;IAE1D,IAAI,CAChB,KAAuB,EACvB,KAAa;;;YAEb,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;YAC1B,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;YAE9C,qEAAqE;YACrE,mEAAmE;YACnE,mEAAmE;YACnE,8CAA8C;YAC9C,MAAM,OAAO,GAAG,MAAA,KAAK,CAAC,OAAO,mCAAI,IAAI,CAAC,eAAe,CAAC;YACtD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACX,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE;oBACpB,IAAI,EAAE,UAAU;oBAChB,MAAM,EAAE,QAAQ;oBAChB,KAAK,EAAE,IAAI,KAAK,CAAC,kBAAkB,CAAC;iBACvC,CAAC,CAAC;gBACH,OAAO;YACX,CAAC;YAED,qEAAqE;YACrE,sEAAsE;YACtE,uEAAuE;YACvE,wEAAwE;YACxE,iEAAiE;YACjE,IAAI,gBAAgB,GAAG,IAAI,CAAC;YAC5B,IAAI,CAAC;gBACD,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBAC5D,gBAAgB,GAAG,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAClD,CAAC;YAAC,WAAM,CAAC;gBACL,oEAAoE;gBACpE,gEAAgE;gBAChE,oBAAoB;gBACpB,gBAAgB,GAAG,IAAI,CAAC;YAC5B,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;gBAAE,OAAO;YAE1C,uCAAuC;YACvC,IAAI,CAAC,MAAM,CAAC,KAAK,iBAET,gBAAgB,EAChB,KAAK,EAAE,iBAAiB,IACrB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC,GAE7C,KAAK,CACR,CAAC;YAEF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,aAAa,GAAG,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;YAChE,IAAI,SAAiB,CAAC;YACtB,IAAI,CAAC;gBACD,SAAS,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;YACvD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,IAAI,CAAC,KAAK,CACN,KAAK,EACL,gBAAgB,EAChB,qBAAqB,CAAC,UAAU,EAAE,GAAG,CAAC,CACzC,CAAC;gBACF,OAAO;YACX,CAAC;YACD,mEAAmE;YACnE,sEAAsE;YACtE,mEAAmE;YACnE,4DAA4D;YAC5D,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC;gBAClC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,gBAAgB,EAAE;oBAChC,IAAI,EAAE,UAAU;oBAChB,MAAM,EAAE,QAAQ;oBAChB,KAAK,EAAE,IAAI,KAAK,CAAC,8BAA8B,CAAC;iBACnD,CAAC,CAAC;gBACH,OAAO;YACX,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;gBAAE,OAAO;YAE1C,kCAAkC;YAClC,IAAI,CAAC,MAAM,CAAC,KAAK,iBAET,KAAK,EAAE,kBAAkB,IACtB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC,GAE7C,KAAK,CACR,CAAC;YACF,IAAI,QAAkC,CAAC;YACvC,IAAI,CAAC;gBACD,QAAQ,GAAG,MAAM,KAAK,CAAC,gBAAgB,iBACnC,OAAO,EAAE,KAAK,EACd,SAAS;oBACT,SAAS;oBACT,aAAa,EACb,MAAM,EAAE,KAAK,CAAC,MAAM,EACpB,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAC1C,aAAa,EAAE,KAAK,CAAC,aAAa,IAC/B,eAAe,CAAC,KAAK,CAAC,eAAe,CAAC,EAC3C,CAAC;YACP,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,+DAA+D;gBAC/D,kEAAkE;gBAClE,oEAAoE;gBACpE,sBAAsB;gBACtB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,gBAAgB,EAAE;oBAChC,IAAI,EAAE,UAAU;oBAChB,MAAM,EAAE,QAAQ;oBAChB,KAAK,EAAE,GAAG;iBACb,CAAC,CAAC;gBACH,OAAO;YACX,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;gBAAE,OAAO;YAE1C,mEAAmE;YACnE,MAAM,OAAO,GAAG,MAAM,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,EAAE;gBACzD,IAAI,CAAC,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;gBACnC,IAAI,CAAC,MAAM,CAAC,KAAK,iBAET,KAAK,EAAE,iBAAiB,EACxB,QAAQ,IACL,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC,GAE5C,KAAK,CACR,CAAC;YACN,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,oEAAoE;YACpE,qCAAqC;YACrC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;gBAAE,OAAO;YAC1C,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC9B,IAAI,CAAC,MAAM,CAAC,KAAK,iBACX,KAAK,EAAE,UAAU,IAAK,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC,GAC7D,KAAK,CACR,CAAC;gBACF,OAAO;YACX,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC9B,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC5B,IAAI,CAAC,KAAK,CACN,KAAK,EACL,gBAAgB,EAChB,qBAAqB,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,CAClD,CAAC;gBACN,CAAC;gBACD,OAAO;YACX,CAAC;YAED,uEAAuE;YACvE,kEAAkE;YAClE,uEAAuE;YACvE,uEAAuE;YACvE,uCAAuC;YACvC,IAAI,IAAI,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;gBACjD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,gBAAgB,EAAE;oBAChC,IAAI,EAAE,SAAS;oBACf,MAAM,EAAE,kBAAkB;iBAC7B,CAAC,CAAC;gBACH,OAAO;YACX,CAAC;YAED,oEAAoE;YACpE,wDAAwD;YACxD,mEAAmE;YACnE,uEAAuE;YACvE,uEAAuE;YACvE,6DAA6D;YAC7D,IAAI,WAAmB,CAAC;YACxB,IAAI,CAAC;gBACD,WAAW,GAAG,iBAAiB,CAAC;oBAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;oBAC5B,SAAS,EAAE,QAAQ,CAAC,SAAS;oBAC7B,eAAe,EAAE,QAAQ,CAAC,eAAe;oBACzC,YAAY,EAAE,cAAc,CAAC,QAAQ,CAAC,YAAY,CAAC;iBACtD,CAAC,CAAC;YACP,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,gBAAgB,EAAE;oBAChC,IAAI,EAAE,SAAS;oBACf,MAAM,EAAE,QAAQ;oBAChB,KAAK,EAAE,GAAG;iBACb,CAAC,CAAC;gBACH,OAAO;YACX,CAAC;YAED,oEAAoE;YACpE,wEAAwE;YACxE,qEAAqE;YACrE,4BAA4B;YAC5B,IAAI,gBAAgB,EAAE,CAAC;gBACnB,IAAI,CAAC,MAAM,CAAC,KAAK,iBACX,KAAK,EAAE,SAAS,IAAK,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC,GAC5D,KAAK,CACR,CAAC;gBACF,IAAI,CAAC;oBACD,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;oBACtD,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;gBACpB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACX,IAAI,CAAC,KAAK,CACN,KAAK,EACL,gBAAgB,EAChB,qBAAqB,CAAC,SAAS,EAAE,GAAG,CAAC,CACxC,CAAC;oBACF,OAAO;gBACX,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;oBAAE,OAAO;YAC9C,CAAC;YAED,gEAAgE;YAChE,IAAI,CAAC,MAAM,CAAC,KAAK,iBACX,KAAK,EAAE,cAAc,IAAK,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC,GACjE,KAAK,CACR,CAAC;YAEF,uEAAuE;YACvE,qEAAqE;YACrE,sEAAsE;YACtE,uEAAuE;YACvE,gEAAgE;YAChE,IAAI,GAAiB,CAAC;YACtB,IAAI,CAAC;gBACD,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,cAAc,CACxC,KAAsB,CACzB,CAAC;gBACF,GAAG,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;YACjD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,gBAAgB,EAAE;oBAChC,IAAI,EAAE,SAAS;oBACf,MAAM,EAAE,QAAQ;oBAChB,KAAK,EAAE,GAAG;iBACb,CAAC,CAAC;gBACH,OAAO;YACX,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;gBAAE,OAAO;YAE1C,IAAI,CAAC;gBACD,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;oBAC3B,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,SAAS,EAAE,KAAK,CAAC,SAAS;oBAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,YAAY,EAAE;wBACV,eAAe,EAAE,GAAG,CAAC,eAAe;wBACpC,SAAS,EAAE,GAAG,CAAC,SAAS;qBAC3B;oBACD,WAAW;oBACX,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;iBAC7C,CAAC,CAAC;gBACH,IAAI,CAAC,MAAM,CAAC,KAAK,iBAET,KAAK,EAAE,iBAAiB,IACrB,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC,GAE5C,KAAK,CACR,CAAC;gBACF,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;YACpB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,gBAAgB,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC1D,OAAO;YACX,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;gBAAE,OAAO;YAE1C,IAAI,CAAC,MAAM,CAAC,KAAK,iBACX,KAAK,EAAE,SAAS,IAAK,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC,GAC5D,KAAK,CACR,CAAC;QACN,CAAC;KAAA;IAEO,KAAK,CACT,KAAa,EACb,gBAAyB,EACzB,OAAuB;QAEvB,IAAI,CAAC,MAAM,CAAC,KAAK,iBAET,KAAK,EAAE,OAAO,EACd,OAAO,IACJ,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,gBAAgB,CAAC,GAE/C,KAAK,CACR,CAAC;IACN,CAAC;CACJ;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E;;;;;GAKG;AACH,SAAS,gBAAgB,CACrB,KAAuB,EACvB,KAAa,EACb,SAAiB;IAEjB,IAAI,KAAK,CAAC,eAAe,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,iCAAiC,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC/D,CAAC;IACD,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GACnD,KAAK,CAAC,eAAe,CAAC;IAC1B,OAAO,6BAA6B,CAAC;QACjC,YAAY;QACZ,MAAM;QACN,UAAU;QACV,WAAW;QACX,SAAS;KACZ,CAAC,CAAC;AACP,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CACpB,OAA+B;IAK/B,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IAC3C,OAAO;QACH,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,WAAW,EAAE,OAAO,CAAC,WAAW;KACnC,CAAC;AACN,CAAC"}
@@ -13,7 +13,7 @@
13
13
  export { Flow } from './flow';
14
14
  export { FlowStore } from './observable';
15
15
  export type { WaitableTransaction } from './observable';
16
- export { CONTRACT_TTL_MS, DepositFlow, NO_SPENDER_MESSAGE, } from './deposit-flow';
16
+ export { CONTRACT_TTL_MS, DepositFlow, INVALID_ACCEPTANCE_SIGNATURE_MESSAGE, INVALID_AUTH_SIGNATURE_MESSAGE, NO_SPENDER_MESSAGE, } from './deposit-flow';
17
17
  export type { ContractMessageRequest, DepositFailure, DepositFlowInput, DepositFlowOptions, DepositPhase, DepositPorts, DepositState, DepositStep, GenerateContractRequest, KycSignature, LegacyContractRequest, LoanAgreementRequest, } from './deposit-flow';
18
18
  export { NO_KYC_PARAMS_MESSAGE, WithdrawFlow } from './withdraw-flow';
19
19
  export type { WithdrawFailure, WithdrawFlowInput, WithdrawPhase, WithdrawPorts, WithdrawState, WithdrawStep, } from './withdraw-flow';
@@ -12,6 +12,6 @@
12
12
  */
13
13
  export { Flow } from './flow';
14
14
  export { FlowStore } from './observable';
15
- export { CONTRACT_TTL_MS, DepositFlow, NO_SPENDER_MESSAGE, } from './deposit-flow';
15
+ export { CONTRACT_TTL_MS, DepositFlow, INVALID_ACCEPTANCE_SIGNATURE_MESSAGE, INVALID_AUTH_SIGNATURE_MESSAGE, NO_SPENDER_MESSAGE, } from './deposit-flow';
16
16
  export { NO_KYC_PARAMS_MESSAGE, WithdrawFlow } from './withdraw-flow';
17
17
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/flows/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,OAAO,EACH,eAAe,EACf,WAAW,EACX,kBAAkB,GACrB,MAAM,gBAAgB,CAAC;AAgBxB,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/flows/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,OAAO,EACH,eAAe,EACf,WAAW,EACX,oCAAoC,EACpC,8BAA8B,EAC9B,kBAAkB,GACrB,MAAM,gBAAgB,CAAC;AAgBxB,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kasufinance/kasu-sdk",
3
- "version": "2.7.0",
3
+ "version": "2.7.1",
4
4
  "description": "TypeScript SDK for the Kasu Finance protocol — pool data, portfolio analytics, and KYC-gated deposits and withdrawals on Base and XDC",
5
5
  "keywords": [
6
6
  "kasu",
@@ -101,6 +101,9 @@ export type {
101
101
  RequestStatusCode,
102
102
  } from './requests';
103
103
 
104
+ export { decodeRevert, extractRevertData } from './revert-errors';
105
+ export type { DecodedRevert, RevertFamily } from './revert-errors';
106
+
104
107
  export {
105
108
  CLEARING_WINDOW_SECONDS,
106
109
  computeSettlementWindow,
@@ -0,0 +1,248 @@
1
+ import { ethers } from 'ethers';
2
+
3
+ import { IKasuAllowListAbi__factory } from '../contracts/factories/IKasuAllowListAbi__factory';
4
+ import { ILendingPoolManagerAbi__factory } from '../contracts/factories/ILendingPoolManagerAbi__factory';
5
+
6
+ /**
7
+ * Revert decoding — turn the bytes a failed call came back with into the name
8
+ * the contract actually reverted with.
9
+ *
10
+ * `isUnpredictableGas` says only THAT the call would revert. That was enough
11
+ * while the answer was always the same one: a `transferFrom` failing on a
12
+ * balance that cannot cover the deposit. It is not enough any more, because
13
+ * `requestDepositWithKyc` reverts for a whole family of reasons the ABI
14
+ * declares and the lender can do nothing about — the pool is stopped, the pool
15
+ * is mid-clearing, their KYC lapsed, they are not on the allow list, the
16
+ * allow-list signature's block window closed. Every one of those was reported
17
+ * as "insufficient balance", so a fully funded lender was told to top up a
18
+ * wallet that was never short.
19
+ *
20
+ * The revert data carries the answer. This module extracts it from whatever
21
+ * envelope the provider wrapped it in and matches the 4-byte selector against
22
+ * the custom errors the protocol declares.
23
+ *
24
+ * Pure, like everything else in `domain/`: bytes in, a name out. It never
25
+ * decides what a lender is shown — `DepositFlow` maps the name to a code and
26
+ * the application maps the code to its own words.
27
+ */
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // What a decoded revert is
31
+ // ---------------------------------------------------------------------------
32
+
33
+ /**
34
+ * Which family a recognised revert belongs to, because the two are acted on
35
+ * differently.
36
+ *
37
+ * `erc20` is the case `insufficient-balance` was named for and still means:
38
+ * the token transfer itself failed, so the lender genuinely has to fund or
39
+ * re-approve. `protocol` is everything else the protocol declares — a
40
+ * condition of the pool or the lender's standing, which topping up cannot fix.
41
+ */
42
+ export type RevertFamily = 'protocol' | 'erc20';
43
+
44
+ export interface DecodedRevert {
45
+ /** The custom error's name, exactly as the ABI declares it. */
46
+ name: string;
47
+ family: RevertFamily;
48
+ /** The reason of a `require(..., "…")` revert, when it was one. */
49
+ reason?: string;
50
+ }
51
+
52
+ // ---------------------------------------------------------------------------
53
+ // The selector tables
54
+ // ---------------------------------------------------------------------------
55
+
56
+ /**
57
+ * OpenZeppelin v5's ERC-20 errors. They are not in either Kasu ABI because no
58
+ * Kasu contract declares them — they arrive from the TOKEN, through the
59
+ * manager's `transferFrom`, and they are the modern spelling of the string
60
+ * reverts below.
61
+ */
62
+ const ERC20_ERROR_ABI = [
63
+ 'error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed)',
64
+ 'error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed)',
65
+ ];
66
+
67
+ /**
68
+ * The protocol errors that mean the ERC-20 transfer failed rather than the
69
+ * protocol refusing.
70
+ *
71
+ * `SafeERC20FailedOperation` is OpenZeppelin's wrapper around a token call
72
+ * that returned false or reverted, which on this path IS the `transferFrom`;
73
+ * `AddressInsufficientBalance` is its native-value sibling. Both belong with
74
+ * the balance case, not with the pool conditions — a lender who sees one of
75
+ * them really does need to fund or re-approve.
76
+ */
77
+ const ERC20_FAMILY_NAMES: ReadonlySet<string> = new Set([
78
+ 'AddressInsufficientBalance',
79
+ 'ERC20InsufficientAllowance',
80
+ 'ERC20InsufficientBalance',
81
+ 'SafeERC20FailedOperation',
82
+ ]);
83
+
84
+ /** Solidity's `Error(string)`, the selector every `require` reason arrives under. */
85
+ const STRING_REVERT_SELECTOR = '0x08c379a0';
86
+
87
+ /**
88
+ * The `require` reasons that are a balance or an allowance, across the token
89
+ * implementations in circulation: OpenZeppelin v4's sentences, and the
90
+ * shorthand the minimal implementations use.
91
+ */
92
+ const ERC20_REASON_PATTERNS: readonly RegExp[] = [
93
+ /exceeds\s+balance/,
94
+ /exceeds\s+allowance/,
95
+ /insufficient\s+balance/,
96
+ /insufficient\s+allowance/,
97
+ /transfer_from_failed/,
98
+ /transferfrom\s+failed/,
99
+ /low-level\s+call\s+failed/,
100
+ ];
101
+
102
+ /**
103
+ * selector → error name, built once on first use.
104
+ *
105
+ * Lazily, because a consumer that never sees a revert should not pay for three
106
+ * `Interface` constructions at import. The two Kasu tables are the GENERATED
107
+ * typechain ABIs, so this cannot drift from the contracts: regenerate the ABIs
108
+ * and the new errors are recognised with no edit here.
109
+ */
110
+ let selectorTable: Map<string, string> | null = null;
111
+
112
+ function selectors(): Map<string, string> {
113
+ if (selectorTable) return selectorTable;
114
+ const table = new Map<string, string>();
115
+ const interfaces = [
116
+ // The manager the deposit is called against, and the allow list it
117
+ // delegates the KYC and block-window checks to.
118
+ ILendingPoolManagerAbi__factory.createInterface(),
119
+ IKasuAllowListAbi__factory.createInterface(),
120
+ new ethers.utils.Interface(ERC20_ERROR_ABI),
121
+ ];
122
+ for (const iface of interfaces) {
123
+ for (const fragment of Object.values(iface.errors)) {
124
+ // First writer wins: the same name declared by both ABIs is the
125
+ // same selector, so the duplicate would be a no-op anyway.
126
+ const sighash = iface.getSighash(fragment);
127
+ if (!table.has(sighash)) table.set(sighash, fragment.name);
128
+ }
129
+ }
130
+ selectorTable = table;
131
+ return table;
132
+ }
133
+
134
+ // ---------------------------------------------------------------------------
135
+ // Getting the bytes out of the envelope
136
+ // ---------------------------------------------------------------------------
137
+
138
+ /**
139
+ * How deep to look for the revert data. Providers nest it differently —
140
+ * ethers' own error wraps the provider's, which wraps the RPC body — and a
141
+ * bound is what keeps a self-referencing error object from being walked
142
+ * forever.
143
+ */
144
+ const MAX_DEPTH = 6;
145
+
146
+ /** The keys ethers and the providers under it put a wrapped error on. */
147
+ const NESTED_KEYS = [
148
+ 'data',
149
+ 'error',
150
+ 'originalError',
151
+ 'info',
152
+ 'cause',
153
+ 'body',
154
+ ] as const;
155
+
156
+ /** At least a 4-byte selector, and a whole number of bytes. */
157
+ function isRevertData(value: string): boolean {
158
+ return (
159
+ value.length >= 10 &&
160
+ value.length % 2 === 0 &&
161
+ /^0x[0-9a-fA-F]+$/.test(value)
162
+ );
163
+ }
164
+
165
+ /**
166
+ * Find the revert data on an error, wherever the provider left it.
167
+ *
168
+ * ethers v5 raises `UNPREDICTABLE_GAS_LIMIT` with the provider's own error
169
+ * attached, and each provider nests the bytes one layer differently:
170
+ * `error.data`, `error.error.data`, `error.data.originalError.data`, or only
171
+ * inside the JSON `body` of a `SERVER_ERROR`. Rather than enumerate the
172
+ * products, walk a fixed set of keys to a fixed depth and take the first value
173
+ * that is shaped like revert data.
174
+ */
175
+ export function extractRevertData(err: unknown): string | null {
176
+ return walk(err, 0);
177
+ }
178
+
179
+ function walk(node: unknown, depth: number): string | null {
180
+ if (node == null || depth > MAX_DEPTH) return null;
181
+ if (typeof node === 'string') {
182
+ if (isRevertData(node)) return node;
183
+ // A `SERVER_ERROR`'s body: the RPC's JSON reply, verbatim.
184
+ if (!node.startsWith('{')) return null;
185
+ try {
186
+ return walk(JSON.parse(node), depth + 1);
187
+ } catch {
188
+ return null;
189
+ }
190
+ }
191
+ if (typeof node !== 'object') return null;
192
+ const record = node as Record<string, unknown>;
193
+ for (const key of NESTED_KEYS) {
194
+ const found = walk(record[key], depth + 1);
195
+ if (found) return found;
196
+ }
197
+ return null;
198
+ }
199
+
200
+ // ---------------------------------------------------------------------------
201
+ // Decoding
202
+ // ---------------------------------------------------------------------------
203
+
204
+ /**
205
+ * Decode a failed call's revert into the error the contract named, or `null`
206
+ * when there is nothing recognisable to name.
207
+ *
208
+ * `null` is the honest answer for an unknown selector, an unrelated `require`
209
+ * string, or an error with no revert data at all — the caller keeps whatever
210
+ * it did before rather than inventing a diagnosis from bytes it cannot read.
211
+ */
212
+ export function decodeRevert(err: unknown): DecodedRevert | null {
213
+ const data = extractRevertData(err);
214
+ if (!data) return null;
215
+ const selector = data.slice(0, 10).toLowerCase();
216
+
217
+ if (selector === STRING_REVERT_SELECTOR) {
218
+ const reason = decodeStringRevert(data);
219
+ if (reason === null) return null;
220
+ return isErc20Reason(reason)
221
+ ? { name: 'Error', family: 'erc20', reason }
222
+ : null;
223
+ }
224
+
225
+ const name = selectors().get(selector);
226
+ if (!name) return null;
227
+ return {
228
+ name,
229
+ family: ERC20_FAMILY_NAMES.has(name) ? 'erc20' : 'protocol',
230
+ };
231
+ }
232
+
233
+ function decodeStringRevert(data: string): string | null {
234
+ try {
235
+ const [reason] = ethers.utils.defaultAbiCoder.decode(
236
+ ['string'],
237
+ `0x${data.slice(10)}`,
238
+ ) as [string];
239
+ return reason;
240
+ } catch {
241
+ return null;
242
+ }
243
+ }
244
+
245
+ function isErc20Reason(reason: string): boolean {
246
+ const lower = reason.toLowerCase();
247
+ return ERC20_REASON_PATTERNS.some((pattern) => pattern.test(lower));
248
+ }