Skip to content

Commit 4f31a33

Browse files
committed
fix: ibc shieled deposits with frontend fees
1 parent c08468b commit 4f31a33

File tree

8 files changed

+111
-26
lines changed

8 files changed

+111
-26
lines changed

apps/namadillo/public/config.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
[frontend_fee."*"]
99
transparent_target = "tnam1qrxsru5rdu4he400xny6p779fcw7xuftsgjnmzup"
1010
shielded_target = "znam1494fmm9qd4frr7jrydnxlcyt57nhngzutxnzgh6y70mkvh23d9z0jk2aasxh4p8dn2kczlgpans"
11-
percentage = 0.1
11+
percentage = 0.01
1212

13-
[frontend_fee.tnam1p54697ljxkw3ptffwy8xjhua9uwjc7kk9cc6fxnw]
14-
transparent_target = "tnam1qrku7yxdt6d23nhe826ntukygzkfyczuu5mm0yll"
15-
shielded_target = "znam175uaqlukleyjjyfcccehp2pw3g696a57skewlv0fenldlw702gtjd6qkpjs09zxl6jafsz3e73h"
16-
percentage = 0.5
13+
# [frontend_fee.tnam1p54697ljxkw3ptffwy8xjhua9uwjc7kk9cc6fxnw]
14+
# transparent_target = "tnam1qrku7yxdt6d23nhe826ntukygzkfyczuu5mm0yll"
15+
# shielded_target = "znam175uaqlukleyjjyfcccehp2pw3g696a57skewlv0fenldlw702gtjd6qkpjs09zxl6jafsz3e73h"
16+
# percentage = 0.5

apps/namadillo/src/App/Ibc/IbcTransfer.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,18 @@ export const IbcTransfer = ({
6868
);
6969
const { trackEvent } = useFathomTracker();
7070
const { storeTransaction } = useTransactionActions();
71+
const shielded = isShieldedAddress(destinationAddress ?? "");
7172

7273
const { transferToNamada, gasConfig, frontendFee } = useIbcTransaction({
7374
registry,
7475
sourceAddress,
7576
sourceChannel,
7677
destinationChannel,
77-
shielded: isShieldedAddress(destinationAddress ?? ""),
78+
shielded,
7879
selectedAsset: selectedAssetWithAmount?.asset,
7980
});
8081

8182
// DERIVED VALUES
82-
const shielded = isShieldedAddress(destinationAddress ?? "");
8383
const availableDisplayAmount = mapUndefined((baseDenom) => {
8484
return userAssets ? userAssets[baseDenom]?.amount : undefined;
8585
}, selectedAssetWithAmount?.asset?.address);
@@ -124,11 +124,16 @@ export const IbcTransfer = ({
124124
}: OnSubmitTransferParams): Promise<void> => {
125125
try {
126126
invariant(registry?.chain, "Error: Chain not selected");
127+
invariant(selectedAssetWithAmount?.asset, "Error: Asset not selected");
128+
invariant(displayAmount, "Error: Amount not specified");
129+
invariant(destinationAddress, "Error: Destination address not specified");
130+
127131
setGeneralErrorMessage("");
128132
setCurrentStatus("Submitting...");
133+
129134
const result = await transferToNamada.mutateAsync({
130-
destinationAddress: destinationAddress ?? "",
131-
displayAmount: new BigNumber(displayAmount ?? "0"),
135+
destinationAddress,
136+
displayAmount: BigNumber(displayAmount),
132137
memo,
133138
onUpdateStatus: setCurrentStatus,
134139
});

apps/namadillo/src/App/Transfer/TransferModule.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
namadaShieldedAssetsAtom,
1212
namadaTransparentAssetsAtom,
1313
} from "atoms/balance";
14+
import { getFrontendFeeEntry } from "atoms/fees";
1415
import { namadaRegistryChainAssetsMapAtom } from "atoms/integrations";
1516
import BigNumber from "bignumber.js";
1617
import clsx from "clsx";
@@ -25,7 +26,7 @@ import {
2526
useNavigate,
2627
useSearchParams,
2728
} from "react-router-dom";
28-
import { AssetWithAmountAndChain } from "types";
29+
import { AssetWithAmountAndChain, NamadaAsset } from "types";
2930
import { filterAvailableAssetsWithBalance } from "utils/assets";
3031
import { getDisplayGasFee } from "utils/gas";
3132
import { isIbcAddress, isShieldedAddress } from "./common";
@@ -133,7 +134,14 @@ export const TransferModule = ({
133134
}, [gasConfig]);
134135

135136
const availableAmountMinusFees = useMemo(() => {
136-
if (!availableAmount || !availableAssets || !displayGasFee) return;
137+
if (
138+
!availableAmount ||
139+
!availableAssets ||
140+
!displayGasFee ||
141+
!gasConfig ||
142+
!frontendFee
143+
)
144+
return;
137145
let amountMinusFees = availableAmount;
138146

139147
if (gasConfig?.gasToken === selectedAsset?.asset.address) {
@@ -142,9 +150,10 @@ export const TransferModule = ({
142150
.decimalPlaces(6);
143151
}
144152

145-
// TODO: move this code
146-
const frontendSusFee =
147-
frontendFee?.[selectedAsset.asset.address || "default"];
153+
const frontendSusFee = getFrontendFeeEntry(
154+
frontendFee,
155+
(selectedAsset.asset as NamadaAsset).address
156+
);
148157

149158
if (frontendSusFee && (isShielding || isUnshielding)) {
150159
amountMinusFees = amountMinusFees

apps/namadillo/src/atoms/fees/services.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import {
55
} from "@namada/indexer-client";
66
import { FrontendSusFeeProps } from "@namada/sdk-multicore";
77
import { assertNever } from "@namada/utils";
8-
import { FrontendFee } from "types";
8+
import BigNumber from "bignumber.js";
9+
import { FrontendFee, FrontendFeeEntry } from "types";
910
import { TxKind } from "types/txKind";
1011

1112
export const fetchGasEstimate = async (
@@ -52,13 +53,23 @@ export const fetchTokensGasPrice = async (
5253
return (await api.apiV1GasPriceGet()).data;
5354
};
5455

56+
// TODO: movet o utils
57+
export const getFrontendFeeEntry = (
58+
frontendFee: FrontendFee,
59+
address: string
60+
): FrontendFeeEntry | undefined => {
61+
return frontendFee[address] || frontendFee["*"];
62+
};
63+
5564
export const frontendSusMsgFromConfig = (
5665
frontendFee: FrontendFee,
5766
token: string,
5867
whichTarget: "shielded" | "transparent"
59-
): FrontendSusFeeProps => {
60-
const { percentage, shieldedTarget, transparentTarget } =
61-
frontendFee[token] || frontendFee["*"];
68+
): FrontendSusFeeProps | undefined => {
69+
const entry = getFrontendFeeEntry(frontendFee, token);
70+
if (!entry) return;
71+
72+
const { percentage, shieldedTarget, transparentTarget } = entry;
6273

6374
const target =
6475
whichTarget === "shielded" ? shieldedTarget
@@ -72,3 +83,25 @@ export const frontendSusMsgFromConfig = (
7283

7384
return frontendSusFee;
7485
};
86+
87+
export const calculateAmountWithoutFrontendFee = (
88+
displayAmount: BigNumber,
89+
frontendFee: FrontendFeeEntry
90+
): BigNumber => {
91+
return (
92+
displayAmount
93+
.div(frontendFee.percentage.plus(1))
94+
// We have to round UP here as sdk discards the remainder when calculating the fee,
95+
// basically rounding down. Otherwise we might end up with remaining dust.
96+
.decimalPlaces(6, BigNumber.ROUND_UP)
97+
);
98+
};
99+
100+
export const calculateAmountWithFrontendFee = (
101+
displayAmount: BigNumber,
102+
frontendFee: FrontendFeeEntry
103+
): BigNumber => {
104+
return displayAmount
105+
.multipliedBy(frontendFee.percentage.plus(1))
106+
.decimalPlaces(6, BigNumber.ROUND_DOWN);
107+
};

apps/namadillo/src/hooks/useIbcTransaction.tsx

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import {
77
} from "@tanstack/react-query";
88
import { TokenCurrency } from "App/Common/TokenCurrency";
99
import { chainParametersAtom } from "atoms/chain";
10+
import {
11+
calculateAmountWithFrontendFee,
12+
getFrontendFeeEntry,
13+
} from "atoms/fees";
1014
import {
1115
broadcastIbcTransactionAtom,
1216
createStargateClient,
@@ -21,6 +25,8 @@ import {
2125
} from "atoms/notifications";
2226
import { frontendFeeAtom } from "atoms/settings";
2327
import BigNumber from "bignumber.js";
28+
import { pipe } from "fp-ts/lib/function";
29+
import * as O from "fp-ts/Option";
2430
import invariant from "invariant";
2531
import { useAtomValue, useSetAtom } from "jotai";
2632
import {
@@ -35,6 +41,7 @@ import {
3541
FrontendFee,
3642
GasConfig,
3743
IbcTransferStage,
44+
NamadaAsset,
3845
TransferStep,
3946
TransferTransactionData,
4047
} from "types";
@@ -193,6 +200,11 @@ export const useIbcTransaction = ({
193200
gasConfigQuery.error?.message
194201
);
195202

203+
const frontendFeeEntry = getFrontendFeeEntry(
204+
frontendFee,
205+
(selectedAsset as NamadaAsset).address
206+
);
207+
196208
const baseAmount = toBaseAmount(selectedAsset, displayAmount);
197209

198210
const sourceChainAssets =
@@ -227,11 +239,25 @@ export const useIbcTransaction = ({
227239
const chainId = registry.chain.chain_id;
228240
const denomination = asset.base;
229241

242+
const amount = pipe(
243+
frontendFeeEntry,
244+
O.fromNullable,
245+
O.filter(() => !!shielded),
246+
O.fold(
247+
() => baseAmount,
248+
(fee) =>
249+
toBaseAmount(
250+
selectedAsset,
251+
calculateAmountWithFrontendFee(BigNumber(displayAmount), fee)
252+
)
253+
)
254+
);
255+
230256
const transferMsg = createIbcTransferMessage(
231257
sanitizeChannel(sourceChannel!),
232258
sanitizeAddress(sourceAddress),
233259
sanitizeAddress(maspCompatibleReceiver),
234-
baseAmount,
260+
amount,
235261
denomination,
236262
maspCompatibleMemo
237263
);
@@ -256,7 +282,8 @@ export const useIbcTransaction = ({
256282
chainId,
257283
destinationChainId || "",
258284
getIbcTransferStage(!!shielded),
259-
!!shielded
285+
!!shielded,
286+
baseAmount
260287
);
261288
dispatchPendingTxNotification(tx);
262289
setTxHash(tx.hash);

apps/namadillo/src/lib/transactions.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,18 +139,24 @@ export const createTransferDataFromIbc = (
139139
sourceChainId: string,
140140
destinationChainId: string,
141141
details: IbcTransferStage,
142-
isShieldedTx: boolean
142+
isShieldedTx: boolean,
143+
// It's needed to calculate real amount if frontend fee is used
144+
declaratedBaseAmount: BigNumber
143145
): TransferTransactionData => {
144146
const transferAttributes = getIbcTransferAttributes(tx);
145147
const packetAttributes = getEventAttribute(tx, "send_packet");
146148
const feeAttributes = getEventAttribute(tx, "fee_pay");
147149
const tipAttributes = getEventAttribute(tx, "tip_pay");
148150
const baseDenom = asset.base;
149-
150-
const transferAmount = toDisplayAmount(
151-
asset,
152-
getAmountAttributeValue(transferAttributes, "amount", baseDenom)
151+
const attrAmount = getAmountAttributeValue(
152+
transferAttributes,
153+
"amount",
154+
baseDenom
153155
);
156+
const baseAmount =
157+
attrAmount.eq(declaratedBaseAmount) ? attrAmount : declaratedBaseAmount;
158+
159+
const transferAmount = toDisplayAmount(asset, baseAmount);
154160

155161
const tipPaid = toDisplayAmount(
156162
asset,

apps/namadillo/src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ export type FrontendFee = Record<
5656
percentage: BigNumber;
5757
}
5858
>;
59+
export type FrontendFeeEntry = {
60+
transparentTarget: Address;
61+
shieldedTarget: PaymentAddress;
62+
percentage: BigNumber;
63+
};
5964

6065
export type GasConfigToDisplay = {
6166
totalDisplayAmount: BigNumber;

apps/namadillo/src/workers/MaspTxMessages.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ type GenerateIbcShieldingMemoPayload = {
9494
amount: BigNumber;
9595
destinationChannelId: string;
9696
chainId: string;
97-
frontendSusFee: FrontendSusFeeProps;
97+
frontendSusFee?: FrontendSusFeeProps;
9898
};
9999
export type GenerateIbcShieldingMemo = WebWorkerMessage<
100100
"generate-ibc-shielding-memo",

0 commit comments

Comments
 (0)