Skip to content

Commit 0929cdc

Browse files
committed
fix: Money Account deposit Pay flow
Three coupled fixes that together unblock Money Account deposits via MetaMask Pay. - getTokenAddress: prefer transactionMeta.requiredAssets[0].address over txParams.to. For an EIP-7702 batch txParams.to === txParams.from (the EOA self-call), which has no token metadata and resolves to the chain's native price via useTokenFiatRates. requiredAssets is the canonical 'what token does this transaction need' signal. - useMoneyAccount.initiateDeposit: declare requiredAssets on the addTransactionBatch call so Pay's parseRequiredTokens finds the deposit token. The batch (approve + teller.deposit) has no nested transfer() for the implicit fallback to detect. - useUpdateTransactionPayAmount: on the moneyAccountDeposit Done press, patch requiredAssets[0].amount before re-encoding nested calldata. Reads decimals from useTransactionPayRequiredTokens()[0] and encodes amountHuman * 10^decimals via updateTransaction(...) on the snapshot. Subsequent updateAtomicBatchData calls observe the new requiredAssets and only mutate disjoint fields, so neither write clobbers the other. A shared deposit-asset constant (getMoneyAccountDepositAssetAddress) is also exported from moneyAccountTransactions so the calldata encoding and Pay's requiredAssets agree on the asset address.
1 parent 026c91e commit 0929cdc

4 files changed

Lines changed: 84 additions & 9 deletions

File tree

app/components/UI/Money/hooks/useMoneyAccount.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ export function useMoneyAccountDeposit() {
8787
disableHook: true,
8888
disableSequential: true,
8989
transactions: [approveTx, depositTx],
90+
requiredAssets: [
91+
{
92+
address: getMoneyAccountDepositAssetAddress(chainIdHex),
93+
amount: '0x0' as Hex,
94+
standard: 'erc20',
95+
},
96+
],
9097
});
9198
} catch (error) {
9299
Logger.error(error as Error, `${LOG_TAG} Deposit transaction failed`);

app/components/UI/Money/utils/moneyAccountTransactions.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,25 @@ import { selectMoneyAccountVaultConfig } from '../../../../selectors/featureFlag
1515
import ReduxService from '../../../../core/redux';
1616
import type { RootState } from '../../../../reducers';
1717

18+
/**
19+
* Returns the deposit asset address (the token the user pays in) for a given chain.
20+
* TODO: Replace with mUSD address once deployed; until then, USDC mainnet is used.
21+
*
22+
* Single source of truth for the deposit asset so both calldata encoding
23+
* (`buildMoneyAccountDepositBatch`) and Pay's `requiredAssets` agree.
24+
*/
25+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
26+
export function getMoneyAccountDepositAssetAddress(_chainId: Hex): Hex {
27+
// TODO: uncomment when mUSD is deployed
28+
// const musdAddress = MUSD_TOKEN_ADDRESS_BY_CHAIN[_chainId];
29+
// if (!musdAddress) {
30+
// throw new Error(`mUSD not deployed on chain ${_chainId}`);
31+
// }
32+
// return musdAddress;
33+
// TODO: remove when mUSD is deployed - temporarily hardcoded USDC
34+
return '0xaf88d065e77c8cC2239327C5EDb3A432268e5831';
35+
}
36+
1837
const LENS_ABI = [
1938
'function previewDeposit(address depositAsset, uint256 depositAmount, address boringVault, address accountant) view returns (uint256 shares)',
2039
];
@@ -131,13 +150,7 @@ export async function buildMoneyAccountDepositBatch({
131150
lensAddress: string;
132151
provider: ethers.providers.Provider;
133152
}): Promise<MoneyAccountDepositBatchResult> {
134-
// TODO: uncomment when mUSD is deployed
135-
// const musdAddress = MUSD_TOKEN_ADDRESS_BY_CHAIN[chainId];
136-
// if (!musdAddress) {
137-
// throw new Error(`mUSD not deployed on chain ${chainId}`);
138-
// }
139-
// TODO: remove when mUSD is deployed - temporarily hardcoded USDC
140-
const musdAddress = '0xaf88d065e77c8cC2239327C5EDb3A432268e5831';
153+
const musdAddress = getMoneyAccountDepositAssetAddress(chainId);
141154

142155
// Skip the RPC call for zero-amount placeholder batches (e.g. initial deposit submission).
143156
const minimumMint =

app/components/Views/confirmations/hooks/pay/useUpdateTransactionPayAmount.ts

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
import { useCallback } from 'react';
2+
import { BigNumber } from 'bignumber.js';
3+
import { toHex } from '@metamask/controller-utils';
24
import {
35
TransactionMeta,
46
TransactionType,
57
} from '@metamask/transaction-controller';
8+
import { Hex } from '@metamask/utils';
69
import { useTransactionMetadataRequest } from '../transactions/useTransactionMetadataRequest';
710
import { useUpdateTokenAmount } from '../transactions/useUpdateTokenAmount';
8-
import { updateAtomicBatchData } from '../../../../../util/transaction-controller';
11+
import {
12+
updateAtomicBatchData,
13+
updateTransaction,
14+
} from '../../../../../util/transaction-controller';
915
import {
1016
updateMoneyAccountDepositTokenAmount,
1117
updateMoneyAccountWithdrawTokenAmount,
1218
} from '../../../../UI/Money/utils/moneyAccountTransactions';
1319
import { UpdateTransactionPayAmountCall } from '../../types/transactions';
1420
import { hasTransactionType } from '../../utils/transaction';
1521
import Logger from '../../../../../util/Logger';
22+
import { useTransactionPayRequiredTokens } from './useTransactionPayData';
1623

1724
type MoneyAccountAmountUpdater = (
1825
transactionMeta: TransactionMeta,
@@ -22,6 +29,7 @@ type MoneyAccountAmountUpdater = (
2229
export function useUpdateTransactionPayAmount() {
2330
const transactionMeta = useTransactionMetadataRequest();
2431
const { updateTokenAmount } = useUpdateTokenAmount();
32+
const requiredTokens = useTransactionPayRequiredTokens();
2533

2634
const applyMoneyAccountAmountUpdates = useCallback(
2735
async (
@@ -72,6 +80,11 @@ export function useUpdateTransactionPayAmount() {
7280
TransactionType.moneyAccountDeposit,
7381
])
7482
) {
83+
syncMoneyAccountDepositRequiredAssets(
84+
transactionMeta,
85+
amountHuman,
86+
requiredTokens?.[0]?.decimals,
87+
);
7588
await applyMoneyAccountAmountUpdates(
7689
amountHuman,
7790
updateMoneyAccountDepositTokenAmount,
@@ -95,8 +108,45 @@ export function useUpdateTransactionPayAmount() {
95108

96109
updateTokenAmount(amountHuman);
97110
},
98-
[transactionMeta, applyMoneyAccountAmountUpdates, updateTokenAmount],
111+
[
112+
transactionMeta,
113+
applyMoneyAccountAmountUpdates,
114+
updateTokenAmount,
115+
requiredTokens,
116+
],
99117
);
100118

101119
return { updateTransactionPayAmount };
102120
}
121+
122+
function syncMoneyAccountDepositRequiredAssets(
123+
transactionMeta: TransactionMeta,
124+
amountHuman: string,
125+
decimals: number | undefined,
126+
): void {
127+
const existing = transactionMeta.requiredAssets;
128+
if (!existing?.length || decimals === undefined) return;
129+
130+
try {
131+
const amount = toHex(
132+
new BigNumber(amountHuman)
133+
.shiftedBy(decimals)
134+
.decimalPlaces(0, BigNumber.ROUND_UP)
135+
.toFixed(0),
136+
) as Hex;
137+
if (existing[0].amount === amount) return;
138+
139+
updateTransaction(
140+
{
141+
...transactionMeta,
142+
requiredAssets: [{ ...existing[0], amount }, ...existing.slice(1)],
143+
},
144+
'Money Account deposit: sync requiredAssets amount',
145+
);
146+
} catch (error) {
147+
Logger.error(
148+
error as Error,
149+
'Failed to sync Money Account deposit requiredAssets amount',
150+
);
151+
}
152+
}

app/components/Views/confirmations/utils/transaction-pay.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ export function getTokenAddress(
8585
return nestedCall.to;
8686
}
8787

88+
const requiredAssetAddress = transactionMeta?.requiredAssets?.[0]?.address;
89+
if (requiredAssetAddress) {
90+
return requiredAssetAddress;
91+
}
92+
8893
return transactionMeta?.txParams?.to as Hex;
8994
}
9095

0 commit comments

Comments
 (0)