Skip to content

Commit e84cfdf

Browse files
Merge pull request #73 from SundaeSwap-finance/rrruko/ssw-206-allow-pool-nft-burn
Resolve SSW-206 (allow pool nft burn)
2 parents b6fbf3d + 51d9d36 commit e84cfdf

File tree

4 files changed

+89
-10
lines changed

4 files changed

+89
-10
lines changed

lib/types/pool.ak

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,6 @@ pub type PoolMintRedeemer {
9494
/// This is safe because we validate that the token is paid to the metadata admin
9595
metadata_output: Int
9696
}
97+
/// to burn the pool NFT (when permitted by the spending validator)
98+
BurnPool { identifier: Ident }
9799
}

plutus.json

Lines changed: 16 additions & 4 deletions
Large diffs are not rendered by default.

validators/pool.ak

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use shared.{AssetClass, Ident, spent_output, pool_nft_name, pool_lp_name, count_
1717
use sundae/multisig
1818
use types/pool.{
1919
CreatePool, MintLP, PoolDatum, PoolMintRedeemer, PoolRedeemer, PoolScoop,
20-
WithdrawFees, UpdatePoolFees,
20+
WithdrawFees, UpdatePoolFees, BurnPool,
2121
}
2222
use types/settings.{SettingsDatum, find_settings_datum}
2323
/// The core / base "pooled AMM" script for the SundaeSwap v3 protocol
@@ -545,6 +545,15 @@ validator(settings_policy_id: PolicyId) {
545545
(ctx.transaction.mint |> value.from_minted_value |> value.quantity_of(own_policy_id, pool_nft_name)) == 0,
546546
}
547547
}
548+
BurnPool(pool_ident) -> {
549+
// Burning an asset is only possible when spending it, so if we enforce
550+
// that the mints consist of exactly 1 burn for the specified pool NFT
551+
// then we can defer to the pool spending validator
552+
expect Mint(own_policy_id) = ctx.purpose
553+
let pool_nft_name = shared.pool_nft_name(pool_ident)
554+
let expected_mint = shared.to_value((own_policy_id, pool_nft_name, -1))
555+
value.from_minted_value(ctx.transaction.mint) == expected_mint
556+
}
548557
}
549558
}
550559
}

validators/tests/pool.ak

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ use tests/examples/ex_shared.{
2222
}
2323
use types/order.{Deposit, Destination, Fixed, Self, OrderDatum, Swap}
2424
use types/pool.{
25-
PoolMintRedeemer, CreatePool, PoolDatum, PoolScoop, WithdrawFees, UpdatePoolFees,
25+
PoolMintRedeemer, CreatePool, PoolDatum, PoolScoop, WithdrawFees,
26+
UpdatePoolFees, BurnPool,
2627
}
2728
use calculation/shared.{PoolState} as calc_shared
2829
use types/settings.{SettingsDatum, settings_nft_name}
@@ -1079,7 +1080,7 @@ test dont_evaporate_pool_test() fail {
10791080
}
10801081

10811082

1082-
test attempt_evaporate_pool_test() fail {
1083+
test attempt_evaporate_pool_test() {
10831084
let withdraw_fees_redeemer = WithdrawFees {
10841085
amount: 18_000_000,
10851086
treasury_output: 0,
@@ -1093,7 +1094,7 @@ test attempt_evaporate_pool_test() fail {
10931094
(ada_policy_id, ada_asset_name),
10941095
(constants.rberry_policy, constants.rberry_asset_name),
10951096
),
1096-
circulating_lp: 1_000_000_000,
1097+
circulating_lp: 0,
10971098
bid_fees_per_10_thousand: pool_fees.1st,
10981099
ask_fees_per_10_thousand: pool_fees.2nd,
10991100
fee_manager: None,
@@ -1109,8 +1110,6 @@ test attempt_evaporate_pool_test() fail {
11091110
InlineDatum(pool_datum))
11101111
|> with_asset_of_tx_input(
11111112
value.from_asset(constants.pool_script_hash, pool_nft_name, 1)
1112-
|> value.add(constants.rberry_policy, constants.rberry_asset_name, 1_000_000_000)
1113-
|> value.add(ada_policy_id, ada_asset_name, 1_000_000_000)
11141113
)
11151114

11161115
let treasury_output = new_tx_output(
@@ -1136,3 +1135,60 @@ test attempt_evaporate_pool_test() fail {
11361135
|> builder.spend(pool_input.output_reference)
11371136
pool_validator.spend(constants.settings_policy_id, pool_datum, withdraw_fees_redeemer, ctx)
11381137
}
1138+
1139+
test burn_pool() {
1140+
let user_addr = wallet_address(constants.payment_key)
1141+
let fees = ((5,5),(5,5))
1142+
let pool_datum =
1143+
PoolDatum {
1144+
identifier: constants.pool_ident,
1145+
assets: ((ada_policy_id, ada_asset_name), (constants.rberry_policy, constants.rberry_asset_name)),
1146+
circulating_lp: 0,
1147+
bid_fees_per_10_thousand: fees.1st,
1148+
ask_fees_per_10_thousand: fees.2nd,
1149+
fee_manager: None,
1150+
market_open: 0,
1151+
fee_finalized: 0,
1152+
protocol_fees: 2_000_000,
1153+
}
1154+
let pool_nft_name = shared.pool_nft_name(constants.pool_ident)
1155+
let pool_address = script_address(constants.pool_script_hash)
1156+
let pool_input =
1157+
Input {
1158+
output_reference: mk_output_reference(0),
1159+
output: Output {
1160+
address: pool_address,
1161+
value: value.from_lovelace(2_000_000)
1162+
|> value.add(constants.pool_script_hash, pool_nft_name, 1),
1163+
datum: InlineDatum(pool_datum),
1164+
reference_script: None,
1165+
},
1166+
}
1167+
let settings_input = {
1168+
let Input { output_reference, output } =
1169+
mk_valid_settings_input([constants.scooper], 1)
1170+
Input { output_reference, output }
1171+
}
1172+
let change_output =
1173+
Output {
1174+
address: user_addr,
1175+
value: value.from_lovelace(2_000_000),
1176+
datum: NoDatum,
1177+
reference_script: None,
1178+
}
1179+
1180+
let (_, pool_nft_token, _) = shared.pool_token_names(constants.pool_ident)
1181+
let ctx = interval.between(1,2)
1182+
|> build_txn_context()
1183+
|> mint_assets(constants.pool_script_hash, value.to_minted_value(
1184+
value.from_lovelace(0)
1185+
|> value.add(constants.pool_script_hash, pool_nft_token, -1)
1186+
))
1187+
|> add_tx_input(pool_input)
1188+
|> add_tx_ref_input(settings_input)
1189+
|> add_tx_output(change_output)
1190+
1191+
let pool_mint_redeemer = BurnPool(constants.pool_ident)
1192+
let result = pool_validator.mint(constants.settings_policy_id, pool_mint_redeemer, ctx)
1193+
result
1194+
}

0 commit comments

Comments
 (0)