Skip to content

Commit 2ce277c

Browse files
authored
sdk: quote destination amount truncation fix (#560)
* sdk: quote destination amount truncation fix Fixes an issue where calling quote with an amount that has more fractional digits than the destination chain supports throws an error. We need to truncate and scale the destination amount to destination chain decimals. * refactor * rename, added comments * rename function
1 parent bb1dc13 commit 2ce277c

File tree

3 files changed

+41
-14
lines changed

3 files changed

+41
-14
lines changed

sdk/route/src/automatic.ts

+13-7
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,17 @@ export class NttAutomaticRoute<N extends Network>
121121
request.toChain.config.nativeTokenDecimals
122122
);
123123

124-
const amt = amount.parse(params.amount, request.source.decimals);
124+
const parsedAmount = amount.parse(params.amount, request.source.decimals);
125+
// The trimmedAmount may differ from the parsedAmount if the parsedAmount includes dust
126+
const trimmedAmount = NttRoute.trimAmount(
127+
parsedAmount,
128+
request.destination.decimals
129+
);
125130

126131
const validatedParams: Vp = {
127132
amount: params.amount,
128133
normalizedParams: {
129-
amount: amt,
134+
amount: trimmedAmount,
130135
sourceContracts: NttRoute.resolveNttContracts(
131136
this.staticConfig,
132137
request.source.id
@@ -160,6 +165,11 @@ export class NttAutomaticRoute<N extends Network>
160165
params.normalizedParams.options
161166
);
162167

168+
const dstAmount = amount.scale(
169+
params.normalizedParams.amount,
170+
request.destination.decimals
171+
);
172+
163173
const result: QR = {
164174
success: true,
165175
params,
@@ -169,7 +179,7 @@ export class NttAutomaticRoute<N extends Network>
169179
},
170180
destinationToken: {
171181
token: request.destination.id,
172-
amount: amount.parse(params.amount, request.destination.decimals),
182+
amount: dstAmount,
173183
},
174184
relayFee: {
175185
token: Wormhole.tokenId(fromChain.chain, "native"),
@@ -190,10 +200,6 @@ export class NttAutomaticRoute<N extends Network>
190200
const duration = await dstNtt.getRateLimitDuration();
191201
if (duration > 0n) {
192202
const capacity = await dstNtt.getCurrentInboundCapacity(fromChain.chain);
193-
const dstAmount = amount.parse(
194-
params.amount,
195-
request.destination.decimals
196-
);
197203
if (
198204
NttRoute.isCapacityThresholdExceeded(amount.units(dstAmount), capacity)
199205
) {

sdk/route/src/manual.ts

+14-7
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,13 @@ export class NttManualRoute<N extends Network>
102102
): Promise<Vr> {
103103
const options = params.options ?? this.getDefaultOptions();
104104

105-
const amt = amount.parse(params.amount, request.source.decimals);
105+
const parsedAmount = amount.parse(params.amount, request.source.decimals);
106+
// The trimmedAmount may differ from the parsedAmount if the parsedAmount includes dust
107+
const trimmedAmount = NttRoute.trimAmount(
108+
parsedAmount,
109+
request.destination.decimals
110+
);
111+
106112
const gasDropoff = amount.units(
107113
amount.parse(
108114
options.gasDropoff ?? "0.0",
@@ -113,7 +119,7 @@ export class NttManualRoute<N extends Network>
113119
const validatedParams: Vp = {
114120
amount: params.amount,
115121
normalizedParams: {
116-
amount: amt,
122+
amount: trimmedAmount,
117123
sourceContracts: NttRoute.resolveNttContracts(
118124
this.staticConfig,
119125
request.source.id
@@ -137,6 +143,11 @@ export class NttManualRoute<N extends Network>
137143
request: routes.RouteTransferRequest<N>,
138144
params: Vp
139145
): Promise<QR> {
146+
const dstAmount = amount.scale(
147+
params.normalizedParams.amount,
148+
request.destination.decimals
149+
);
150+
140151
const result: QR = {
141152
success: true,
142153
params,
@@ -146,7 +157,7 @@ export class NttManualRoute<N extends Network>
146157
},
147158
destinationToken: {
148159
token: request.destination.id,
149-
amount: amount.parse(params.amount, request.destination.decimals),
160+
amount: dstAmount,
150161
},
151162
eta: finality.estimateFinalityTime(request.fromChain.chain),
152163
};
@@ -157,10 +168,6 @@ export class NttManualRoute<N extends Network>
157168
const duration = await dstNtt.getRateLimitDuration();
158169
if (duration > 0n) {
159170
const capacity = await dstNtt.getCurrentInboundCapacity(fromChain.chain);
160-
const dstAmount = amount.parse(
161-
params.amount,
162-
request.destination.decimals
163-
);
164171
if (
165172
NttRoute.isCapacityThresholdExceeded(amount.units(dstAmount), capacity)
166173
) {

sdk/route/src/types.ts

+14
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export namespace NttRoute {
1818
// Currently only wormhole attestations supported
1919
export type TransceiverType = "wormhole";
2020

21+
export const TRIMMED_DECIMALS = 8;
22+
2123
export type TransceiverConfig = {
2224
type: TransceiverType;
2325
address: string;
@@ -212,4 +214,16 @@ export namespace NttRoute {
212214
const threshold = (capacity * 95n) / 100n;
213215
return amount > threshold;
214216
}
217+
218+
export function trimAmount(
219+
amt: amount.Amount,
220+
dstTokenDecimals: number
221+
): amount.Amount {
222+
// remove dust to avoid `TransferAmountHasDust` revert reason
223+
const truncatedAmount = amount.truncate(
224+
amt,
225+
Math.min(amt.decimals, dstTokenDecimals, NttRoute.TRIMMED_DECIMALS)
226+
);
227+
return truncatedAmount;
228+
}
215229
}

0 commit comments

Comments
 (0)