Skip to content

Commit a09cce7

Browse files
committed
fix: clean EVM relay error messages, detect nonce-already-used
Made-with: Cursor
1 parent b4e5d61 commit a09cce7

1 file changed

Lines changed: 17 additions & 14 deletions

File tree

public/app.js

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2451,31 +2451,34 @@ async function relayToEvm() {
24512451
} catch (error) {
24522452
console.error('Full error:', error);
24532453

2454-
// Detect destination_caller restriction
2454+
// Extract the revert reason from nested ethers.js error
24552455
const errMsg = error.message || '';
2456-
const errData = error.error?.data?.message || error.error?.message || '';
2457-
const isCallerError = errMsg.includes('Invalid caller for message')
2458-
|| errData.includes('Invalid caller for message');
2456+
const revertReason = error.error?.data?.message || error.error?.message || '';
2457+
const combined = errMsg + ' ' + revertReason;
24592458

2460-
if (isCallerError) {
2459+
if (error.code === 'ACTION_REJECTED' || error.code === 4001) {
2460+
log('Transaction was rejected by user.', 'warning');
2461+
updateModalStep(3, 'pending', 'Failed', 'Transaction rejected by user.');
2462+
} else if (combined.includes('Invalid caller for message')) {
24612463
const requiredCaller = extractDestCaller(messageHex);
24622464
log('This CCTP message has a destination_caller restriction.', 'error');
24632465
if (requiredCaller) {
24642466
log(`Required caller: ${requiredCaller}`, 'error');
24652467
log(`Your wallet: ${evmAddress}`, 'info');
2466-
if (requiredCaller.toLowerCase() !== evmAddress.toLowerCase()) {
2467-
log('You must connect the wallet that matches the required caller address to complete this relay.', 'warning');
2468-
log('This is typically set by the bridge/app that initiated the burn (e.g. cctp.money, Noble Express).', 'info');
2469-
}
2468+
log('You must connect the wallet that matches the required caller to complete this relay.', 'warning');
2469+
log('This is typically set by the bridge/app that initiated the burn (e.g. cctp.money, Noble Express).', 'info');
24702470
} else {
2471-
log('Only the designated wallet can complete this relay. Check which address was set as destination_caller.', 'warning');
2471+
log('Only the designated wallet can complete this relay.', 'warning');
24722472
}
24732473
updateModalStep(3, 'pending', 'Failed', 'Destination caller restriction — wrong wallet.');
2474-
} else if (error.code === 'ACTION_REJECTED' || error.code === 4001) {
2475-
log('Transaction was rejected by user.', 'warning');
2476-
updateModalStep(3, 'pending', 'Failed', 'Transaction rejected by user.');
2474+
} else if (combined.includes('Nonce already used') || combined.includes('already used')) {
2475+
log('This message has already been relayed (nonce already used).', 'warning');
2476+
log('The USDC should already be in the destination wallet.', 'info');
2477+
updateModalStep(3, 'pending', 'Already Relayed', 'This transfer was already completed.');
24772478
} else {
2478-
log(`Relay failed: ${errMsg}`, 'error');
2479+
// Show a clean version of the error, not the raw gas estimation noise
2480+
const cleanReason = revertReason || errMsg.match(/reason="([^"]+)"/)?.[1] || errMsg;
2481+
log(`Relay failed: ${cleanReason}`, 'error');
24792482
updateModalStep(3, 'pending', 'Failed', 'Relay transaction failed. Check logs for details.');
24802483
}
24812484
}

0 commit comments

Comments
 (0)