Skip to content

Commit

Permalink
chore: capture ForwardFailed state
Browse files Browse the repository at this point in the history
- if Forward (slow transfer) fails, capture the state to distinguish from successful forwards
  • Loading branch information
0xpatrickdev committed Dec 19, 2024
1 parent 43bb509 commit 7fbcaa1
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 11 deletions.
12 changes: 6 additions & 6 deletions packages/fast-usdc/src/exos/settler.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,7 @@ export const prepareSettler = (
*/
forward(txHash, fullValue, EUD) {
const { settlementAccount, intermediateRecipient } = this.state;

const dest = chainHub.makeChainAddress(EUD);

// TODO? statusManager.forwarding(txHash, sender, amount);
const txfrV = E(settlementAccount).transfer(
dest,
AmountMath.make(USDC, fullValue),
Expand All @@ -289,15 +286,18 @@ export const prepareSettler = (
* @param {EvmHash} txHash
*/
onFulfilled(_result, txHash) {
statusManager.forwarded(txHash);
// update status manager, marking tx `FORWARDED` without fee split
statusManager.forwarded(txHash, true);
},
/**
* @param {unknown} reason
* @param {EvmHash} txHash
*/
onRejected(reason, txHash) {
log('⚠️ transfer rejected!', reason, txHash);
// TODO(#10510): statusManager.forwardFailed(txHash, nfa, amount);
log('⚠️ forward transfer rejected!', reason, txHash);
// update status manager, flagging a terminal state that needs to be
// manual intervention or a code update to remediate
statusManager.forwarded(txHash, false);
},
},
},
Expand Down
16 changes: 11 additions & 5 deletions packages/fast-usdc/src/exos/status-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ export const prepareStatusManager = (
disbursed: M.call(EvmHashShape, AmountKeywordRecordShape).returns(
M.undefined(),
),
forwarded: M.call(EvmHashShape).returns(M.undefined()),
forwarded: M.call(EvmHashShape, M.boolean()).returns(M.undefined()),
lookupPending: M.call(M.string(), M.bigint()).returns(
M.arrayOf(PendingTxShape),
),
Expand Down Expand Up @@ -320,12 +320,18 @@ export const prepareStatusManager = (
},

/**
* Mark a transaction as `FORWARDED`
* Mark a transaction as `FORWARDED` or `FORWARD_FAILED`
*
* @param {EvmHash} txHash - undefined in case mint before observed
* @param {EvmHash} txHash
* @param {boolean} success
*/
forwarded(txHash) {
void publishTxnRecord(txHash, harden({ status: TxStatus.Forwarded }));
forwarded(txHash, success) {
void publishTxnRecord(
txHash,
harden({
status: success ? TxStatus.Forwarded : TxStatus.ForwardFailed,
}),
);
},

/**
Expand Down
66 changes: 66 additions & 0 deletions packages/fast-usdc/test/exos/settler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -493,3 +493,69 @@ test('Settlement for Advancing transaction (advance fails)', async t => {
{ status: 'FORWARDED' },
]);
});

test('slow path, and forward fails (terminal state)', async t => {
const {
common,
makeSettler,
statusManager,
defaultSettlerParams,
repayer,
makeSimulate,
accounts,
peekCalls,
storage,
} = t.context;
const { usdc } = common.brands;

const settler = makeSettler({
repayer,
settlementAccount: accounts.settlement.account,
...defaultSettlerParams,
});
const simulate = makeSimulate(settler.notify);
const cctpTxEvidence = simulate.observe();
t.deepEqual(
statusManager.lookupPending(
cctpTxEvidence.tx.forwardingAddress,
cctpTxEvidence.tx.amount,
),
[{ ...cctpTxEvidence, status: PendingTxStatus.Observed }],
'statusManager shows this tx is only observed',
);

t.log('Simulate incoming IBC settlement');
void settler.tap.receiveUpcall(MockVTransferEvents.AGORIC_PLUS_OSMO());
await eventLoopIteration();

t.log('funds are forwarded; no interaction with LP');
t.like(accounts.settlement.callLog, [
[
'transfer',
{
value: 'osmo183dejcnmkka5dzcu9xw6mywq0p2m5peks28men',
},
usdc.units(150),
{
forwardOpts: {
intermediateRecipient: {
value: 'noble1test',
},
},
},
],
]);

t.log('simulating forward failure (e.g. unknown route)');
const mockE = Error('no connection info found');
accounts.settlement.transferVResolver.reject(mockE);
await eventLoopIteration();
t.deepEqual(storage.getDeserialized(`fun.txns.${cctpTxEvidence.txHash}`), [
{ evidence: cctpTxEvidence, status: 'OBSERVED' },
{ status: 'FORWARD_FAILED' },
]);
});

test.todo('create facet methods');

test.todo('ignored packets');

0 comments on commit 7fbcaa1

Please sign in to comment.