Skip to content

Commit 9d2cfad

Browse files
committed
Add test and minor fixes
1 parent c9686ff commit 9d2cfad

2 files changed

Lines changed: 212 additions & 0 deletions

File tree

on-chain/lib/mint_test.ak

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use utils.{compute_expected_synth_amount}
2+
3+
// ── Mint condition ────────────────────────────────────────────────────────────
4+
//
5+
// Spec: given ADA deposited, the minted synth amount must equal:
6+
// compute_expected_synth_amount(ada_deposited, raw_price, exponent)
7+
// * 100 / collateral_ratio
8+
//
9+
// Scenario: ADA/USD = $1.00, collateral_ratio = 150
10+
// Depositing 1.5 ADA ($1.50) must mint exactly $1.00 of synth (1_000_000 micro-USD).
11+
// Derivation:
12+
// base = 1_500_000 * 100_000_000 / 10^8 = 1_500_000 micro-USD
13+
// minted = 1_500_000 * 100 / 150 = 1_000_000 micro-USD ✓
14+
15+
test mint_1_5_ada_yields_1_usd_at_150_pct_collateral() {
16+
let ada_deposited = 1_500_000
17+
let raw_price = 100_000_000
18+
let exponent = -8
19+
let collateral_ratio = 150
20+
let minted_amount = 1_000_000
21+
22+
let expected_minted_amount =
23+
compute_expected_synth_amount(ada_deposited, raw_price, exponent)
24+
* 100
25+
/ collateral_ratio
26+
27+
minted_amount == expected_minted_amount
28+
}
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
//use aiken/collection/dict
2+
//use aiken/interval
3+
//use cardano/address.{Address, Script}
4+
//use cardano/assets
5+
//use cardano/transaction.{
6+
// Input, InlineDatum, Output, OutputReference, Transaction, Withdraw,
7+
//}
8+
//use pyth.{Governance, Pyth}
9+
//use synth_dolar.{Mint, PoolDatum}
10+
//
11+
//// ── Constants ─────────────────────────────────────────────────────────────────
12+
//
13+
///// Policy ID of the synth token (28 zero bytes).
14+
//const policy_id: ByteArray =
15+
// #"00000000000000000000000000000000000000000000000000000000"
16+
//
17+
///// Policy ID for the Pyth State NFT reference input.
18+
//const pyth_policy_id: ByteArray =
19+
// #"11111111111111111111111111111111111111111111111111111111"
20+
//
21+
///// Script hash of the Pyth withdraw script (authorises price updates).
22+
//const withdraw_script_hash: ByteArray =
23+
// #"22222222222222222222222222222222222222222222222222222222"
24+
//
25+
///// Payment key hash of the position owner.
26+
//const owner_pkh: ByteArray =
27+
// #"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
28+
//
29+
//const ada_usd_feed_id = 16
30+
//
31+
//const collateral_ratio = 150
32+
//
33+
//const liquidation_threshold = 120
34+
//
35+
//// ── Crafted Pyth price message ─────────────────────────────────────────────
36+
////
37+
//// parse_without_verification skips Ed25519 checks, so the signature and
38+
//// public-key bytes can be arbitrary zeros.
39+
////
40+
//// Wire layout (133 bytes total):
41+
//// [4] outer magic b9011a82
42+
//// [64] signature (zeros)
43+
//// [32] public key (zeros)
44+
//// [2] payload length 1f00 (= 31 bytes, little-endian u16)
45+
//// [31] payload:
46+
//// [4] inner magic 75d3c793
47+
//// [8] timestamp_us (zeros)
48+
//// [1] channel_id 00
49+
//// [1] feeds_len 01
50+
//// [4] feed_id 10000000 (= 16, LE u32)
51+
//// [1] prop_count 02
52+
//// [1] prop id 0 00 (Price)
53+
//// [8] price 801d2c0400000000 (= 70_000_000, i64 LE)
54+
//// [1] prop id 4 04 (Exponent)
55+
//// [2] exponent f8ff (= -8, i16 LE)
56+
////
57+
//// Decoded: feed.price = Some(Some(70_000_000))
58+
//// feed.exponent = Some(-8)
59+
//// → real ADA/USD price = 70_000_000 × 10^-8 = $0.70
60+
//
61+
//const pyth_price_message: ByteArray =
62+
// #"b901 1a820000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f0075d3c79300000000000000000001100000000200801d2c040000000004f8ff"
63+
//
64+
//// ── Helpers ───────────────────────────────────────────────────────────────────
65+
//
66+
//fn script_address(hash: ByteArray) -> Address {
67+
// Address { payment_credential: Script(hash), stake_credential: None }
68+
//}
69+
//
70+
///// Reference input carrying the Pyth State NFT and a Pyth datum.
71+
///// get_updates uses this to discover the withdraw_script hash.
72+
//fn make_pyth_state_input() -> Input {
73+
// let state: Data =
74+
// Pyth {
75+
// governance: Governance {
76+
// wormhole: #"",
77+
// emitter_chain: 0,
78+
// emitter_address: #"",
79+
// seen_sequence: 0,
80+
// },
81+
// trusted_signers: [],
82+
// deprecated_withdraw_scripts: [],
83+
// withdraw_script: withdraw_script_hash,
84+
// }
85+
//
86+
// Input {
87+
// output_reference: OutputReference {
88+
// transaction_id: #"0000000000000000000000000000000000000000000000000000000000000000",
89+
// output_index: 0,
90+
// },
91+
// output: Output {
92+
// address: script_address(
93+
// #"33333333333333333333333333333333333333333333333333333333",
94+
// ),
95+
// value: assets.merge(
96+
// assets.from_lovelace(2_000_000),
97+
// assets.from_asset(pyth_policy_id, "Pyth State", 1),
98+
// ),
99+
// datum: InlineDatum(state),
100+
// reference_script: None,
101+
// },
102+
// }
103+
//}
104+
//
105+
///// Pool UTxO input locked at the script address.
106+
//fn make_pool_input(lovelace: Int) -> Input {
107+
// let datum: Data = PoolDatum { owner: owner_pkh }
108+
//
109+
// Input {
110+
// output_reference: OutputReference {
111+
// transaction_id: #"1111111111111111111111111111111111111111111111111111111111111111",
112+
// output_index: 0,
113+
// },
114+
// output: Output {
115+
// address: script_address(policy_id),
116+
// value: assets.from_lovelace(lovelace),
117+
// datum: InlineDatum(datum),
118+
// reference_script: None,
119+
// },
120+
// }
121+
//}
122+
//
123+
///// Pool UTxO output returned to the script address after ADA deposit.
124+
//fn make_pool_output(lovelace: Int) -> Output {
125+
// let datum: Data = PoolDatum { owner: owner_pkh }
126+
//
127+
// Output {
128+
// address: script_address(policy_id),
129+
// value: assets.from_lovelace(lovelace),
130+
// datum: InlineDatum(datum),
131+
// reference_script: None,
132+
// }
133+
//}
134+
//
135+
//// ── Mint test ─────────────────────────────────────────────────────────────────
136+
////
137+
//// Scenario: ADA/USD = $0.70, deposit 1.5 ADA, collateral_ratio = 150
138+
////
139+
//// synth_base = 1_500_000 × 70_000_000 / 10^8 = 1_050_000 micro-USD
140+
//// minted = 1_050_000 × 100 / 150 = 700_000 micro-USD ($0.70)
141+
////
142+
//// All mint checks must pass:
143+
//// ✓ ada_deposited >= 1
144+
//// ✓ minted_amount == expected_minted_amount
145+
//
146+
//test mint_valid_deposit_yields_correct_synth_amount() {
147+
// let initial_pool_ada = 2_000_000
148+
// let ada_deposited = 1_500_000
149+
// let minted_amount = 700_000
150+
//
151+
// // The Pyth withdraw-script redeemer is List<ByteArray>; one signed message.
152+
// let updates: List<ByteArray> = [pyth_price_message]
153+
// let updates_data: Data = updates
154+
//
155+
// let tx =
156+
// Transaction {
157+
// inputs: [make_pool_input(initial_pool_ada)],
158+
// reference_inputs: [make_pyth_state_input()],
159+
// outputs: [make_pool_output(initial_pool_ada + ada_deposited)],
160+
// fee: 0,
161+
// mint: assets.from_asset(policy_id, #"", minted_amount),
162+
// certificates: [],
163+
// withdrawals: [],
164+
// validity_range: interval.everything,
165+
// extra_signatories: [],
166+
// redeemers: [
167+
// Pair(Withdraw(Script(withdraw_script_hash)), updates_data),
168+
// ],
169+
// datums: dict.empty,
170+
// id: #"0000000000000000000000000000000000000000000000000000000000000000",
171+
// votes: [],
172+
// proposal_procedures: [],
173+
// current_treasury_amount: None,
174+
// treasury_donation: None,
175+
// }
176+
//
177+
// synth_dolar.synth_dolar(
178+
// pyth_policy_id,
179+
// ada_usd_feed_id,
180+
// collateral_ratio,
181+
// liquidation_threshold,
182+
// ).mint(Mint, policy_id, tx)
183+
//}
184+
//

0 commit comments

Comments
 (0)