Skip to content

Commit 67d134e

Browse files
authored
Fix dca swap amount logic (#1109)
* Fix dca swap amount logic * Fix to HNT decimals * fix tests
1 parent 525f953 commit 67d134e

File tree

5 files changed

+37
-14
lines changed

5 files changed

+37
-14
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

programs/dc-auto-top/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "dc-auto-top"
3-
version = "0.0.6"
3+
version = "0.0.7"
44
# Trigger deployment - timestamp: 03-31-2025 #3
55
description = "Created with Anchor"
66
edition = "2021"

programs/dc-auto-top/src/instructions/top_off_hnt_v0.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,11 +240,22 @@ pub fn handler<'info>(
240240
.ok_or(ErrorCode::ArithmeticError)?,
241241
};
242242

243-
msg!("hnt_per_swap: {}", hnt_per_swap);
243+
// Convert HNT per swap to HNT decimals from DCA decimals
244+
let hnt_per_swap_hnt_decimals = match ctx.accounts.dca_mint.decimals.cmp(&8u8) {
245+
std::cmp::Ordering::Greater => hnt_per_swap
246+
.checked_div(10_u64.pow(u32::from(ctx.accounts.dca_mint.decimals - 8)))
247+
.ok_or(ErrorCode::ArithmeticError)?,
248+
std::cmp::Ordering::Less => hnt_per_swap
249+
.checked_mul(10_u64.pow(u32::from(8 - ctx.accounts.dca_mint.decimals)))
250+
.ok_or(ErrorCode::ArithmeticError)?,
251+
std::cmp::Ordering::Equal => hnt_per_swap,
252+
};
253+
254+
msg!("hnt_per_swap: {}", hnt_per_swap_hnt_decimals);
244255

245256
// Now calculate number of orders needed using ceiling division
246-
if hnt_per_swap > 0 {
247-
hnt_needed.div_ceil(hnt_per_swap)
257+
if hnt_per_swap_hnt_decimals > 0 {
258+
hnt_needed.div_ceil(hnt_per_swap_hnt_decimals)
248259
} else {
249260
0
250261
}

tests/dc-auto-topoff.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@ describe("dc-auto-topoff", () => {
510510

511511
// Calculate required input amount per swap to get exactly hntNeeded/numOrders HNT per swap
512512
// Formula: outputAmount = inputAmount * (inputPrice / outputPrice)
513+
// (dollars / dollars) / (dollars / hnt) = hnt / dollars
513514
// So: inputAmount = outputAmount * (outputPrice / inputPrice)
514515
const hntPerSwap = hntNeeded.divn(numOrders); // 10 HNT per swap
515516

@@ -525,17 +526,23 @@ describe("dc-auto-topoff", () => {
525526
.mul(outputPrice)
526527
.div(inputPrice)
527528
.div(new anchor.BN(10).pow(new anchor.BN(Math.abs(expoDiff))))
529+
// Decimal difference between USDC and HNT
530+
.div(new anchor.BN(100))
528531
.add(new anchor.BN(1));
529532
} else if (expoDiff < 0) {
530533
dcaSwapAmount = hntPerSwap
531534
.mul(outputPrice)
532535
.div(inputPrice)
533536
.mul(new anchor.BN(10).pow(new anchor.BN(Math.abs(expoDiff))))
537+
// Decimal difference between USDC and HNT
538+
.div(new anchor.BN(100))
534539
.add(new anchor.BN(1));
535540
} else {
536541
dcaSwapAmount = hntPerSwap
537542
.mul(outputPrice)
538543
.div(inputPrice)
544+
// Decimal difference between USDC and HNT
545+
.div(new anchor.BN(100))
539546
.add(new anchor.BN(1));
540547
}
541548

@@ -669,6 +676,10 @@ describe("dc-auto-topoff", () => {
669676
const actualAmount = new anchor.BN(
670677
hntAccountAfterFirstSwap.amount.toString()
671678
);
679+
console.log(`Actual amount after first swap: ${actualAmount.toString()}`);
680+
console.log(
681+
`Expected amount after first swap: ${expectedAfterFirstSwap.toString()}`
682+
);
672683
const difference = actualAmount.gt(expectedAfterFirstSwap)
673684
? actualAmount.sub(expectedAfterFirstSwap)
674685
: expectedAfterFirstSwap.sub(actualAmount);

tests/utils/dca-test-server.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ function calculateExpectedOutput(
4949
.div(outputPriceWithConf);
5050
}
5151

52-
return expectedOutput;
52+
// Extra two decimals on HNT
53+
return expectedOutput.mul(new BN(100));
5354
}
5455

5556
export interface DcaServerConfig {
@@ -117,11 +118,13 @@ export async function createDcaServer(
117118
);
118119

119120
console.log(
120-
`Input Price: ${inputPriceUpdate.priceMessage.price.toString()} (expo: ${inputPriceUpdate.priceMessage.exponent
121+
`Input Price: ${inputPriceUpdate.priceMessage.price.toString()} (expo: ${
122+
inputPriceUpdate.priceMessage.exponent
121123
})`
122124
);
123125
console.log(
124-
`Output Price: ${outputPriceUpdate.priceMessage.price.toString()} (expo: ${outputPriceUpdate.priceMessage.exponent
126+
`Output Price: ${outputPriceUpdate.priceMessage.price.toString()} (expo: ${
127+
outputPriceUpdate.priceMessage.exponent
125128
})`
126129
);
127130

@@ -231,9 +234,7 @@ export async function runAllTasks(
231234
taskQueue: PublicKey,
232235
crankTurner: Keypair
233236
) {
234-
const taskQueueAcc = await tuktukProgram.account.taskQueueV0.fetch(
235-
taskQueue
236-
);
237+
const taskQueueAcc = await tuktukProgram.account.taskQueueV0.fetch(taskQueue);
237238

238239
// Find all task IDs that need to be executed (have a 1 in the bitmap)
239240
const taskIds: number[] = [];
@@ -251,8 +252,9 @@ export async function runAllTasks(
251252
const task = taskKey(taskQueue, taskId)[0];
252253
const taskAcc = await tuktukProgram.account.taskV0.fetch(task);
253254
if (
254-
((taskAcc.trigger.timestamp?.[0]?.toNumber() || 0) >
255-
new Date().getTime() / 1000) || taskAcc.transaction.remoteV0?.url?.includes(".helium.io")
255+
(taskAcc.trigger.timestamp?.[0]?.toNumber() || 0) >
256+
new Date().getTime() / 1000 ||
257+
taskAcc.transaction.remoteV0?.url?.includes(".helium.io")
256258
) {
257259
continue;
258260
}
@@ -276,4 +278,3 @@ export async function runAllTasks(
276278
}
277279

278280
export { calculateExpectedOutput };
279-

0 commit comments

Comments
 (0)