Skip to content

Commit a9330fb

Browse files
authored
Merge pull request cardano-foundation#254 from cardano-foundation/fix/ID-503-Voucher-Refund-Exploit
Fix/id 503 voucher refund exploit
2 parents e5538f8 + bec577d commit a9330fb

File tree

2 files changed

+98
-3
lines changed

2 files changed

+98
-3
lines changed

cardano/onchain/validators/minting_voucher.ak

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use ibc/apps/transfer/transfer_module_redeemer.{Transfer}
1616
use ibc/apps/transfer/types/coin as transfer_coin
1717
use ibc/apps/transfer/types/fungible_token_packet_data.{FungibleTokenPacketData}
1818
use ibc/auth.{AuthToken}
19+
use ibc/core/ics_004/types/acknowledgement_response.{AcknowledgementError}
1920
use ibc/core/ics_005/types/ibc_module_redeemer.{
2021
Callback, IBCModuleRedeemer, OnAcknowledgementPacket, OnRecvPacket,
2122
OnTimeoutPacket, Operator, TransferModuleData, TransferModuleOperator,
@@ -139,7 +140,11 @@ validator mint_voucher(module_token: AuthToken) {
139140
let data =
140141
when ibc_module_callback is {
141142
OnTimeoutPacket { data, .. } -> data
142-
OnAcknowledgementPacket { data, .. } -> data
143+
OnAcknowledgementPacket { acknowledgement, data, .. } ->
144+
when acknowledgement.response is {
145+
AcknowledgementError { .. } -> data
146+
_ -> fail
147+
}
143148
_ -> fail
144149
}
145150
expect TransferModuleData(data) = data

cardano/onchain/validators/minting_voucher.test.ak

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ use ibc/apps/transfer/types/coin as transfer_coin
1515
use ibc/apps/transfer/types/fungible_token_packet_data.{FungibleTokenPacketData}
1616
use ibc/auth.{AuthToken}
1717
use ibc/core/ics_004/types/acknowledgement
18+
use ibc/core/ics_004/types/acknowledgement_response.{AcknowledgementResult}
1819
use ibc/core/ics_005/types/ibc_module_redeemer.{
19-
Callback, OnRecvPacket, OnTimeoutPacket, Operator, TransferModuleData,
20-
TransferModuleOperator,
20+
Callback, OnAcknowledgementPacket, OnRecvPacket, OnTimeoutPacket, Operator,
21+
TransferModuleData, TransferModuleOperator,
2122
}
2223
use ibc/utils/string as string_utils
2324
use minting_voucher
@@ -297,3 +298,92 @@ test test_refund_voucher() {
297298
transaction,
298299
)
299300
}
301+
302+
// ID-503-Not possible to refund voucher if transfer suceeds
303+
test test_refund_voucher_fail() fail {
304+
let mock_data = prepare_mock_data()
305+
306+
//=========================arrange packet data===============================
307+
let packet_source_port = "port-99"
308+
let packet_source_channel = "channel-99"
309+
let packet_dest_channel = "channel-99"
310+
311+
let transfer_amount = 100
312+
313+
let source_prefix =
314+
transfer_coin.get_denom_prefix(packet_source_port, packet_source_channel)
315+
let prefixed_denom = bytearray.concat(source_prefix, "ibc/usdt")
316+
317+
//525f6e2b0f8a15a3c95d82c8113b99dfebfe40f124cb2bc71ee99e22
318+
let sender =
319+
#"3532356636653262306638613135613363393564383263383131336239396466656266653430663132346362326263373165653939653232"
320+
321+
let ftpd =
322+
FungibleTokenPacketData {
323+
denom: prefixed_denom,
324+
amount: string.from_int(transfer_amount) |> string.to_bytearray(),
325+
sender,
326+
receiver: "cosmos address",
327+
memo: "",
328+
}
329+
330+
//==================================arrange output============================
331+
let token_name = crypto.sha3_256(ftpd.denom)
332+
333+
let mint =
334+
from_asset(mock_data.voucher_minting_policy_id, token_name, transfer_amount)
335+
336+
expect Some(sender_public_key_hash) = string_utils.hex_string_to_bytes(sender)
337+
338+
let sender_output =
339+
Output {
340+
address: from_verification_key(sender_public_key_hash),
341+
value: mint,
342+
datum: NoDatum,
343+
reference_script: None,
344+
}
345+
let outputs = [sender_output]
346+
347+
//==================================arrange redeemers============================
348+
let mint_voucher_redeemer =
349+
RefundVoucher { packet_source_port, packet_source_channel }
350+
let purpose = Mint(mock_data.voucher_minting_policy_id)
351+
352+
let packet_data = TransferModuleData(ftpd)
353+
354+
let spend_module_redeemer =
355+
Callback(
356+
OnAcknowledgementPacket {
357+
channel_id: packet_dest_channel,
358+
acknowledgement: acknowledgement.new_result_acknowledgement(#[1]),
359+
data: packet_data,
360+
},
361+
)
362+
let mint_voucher_redeemer_in_data: Redeemer = mint_voucher_redeemer
363+
let spend_module_redeemer_in_data: Redeemer = spend_module_redeemer
364+
365+
let redeemers: Pairs<ScriptPurpose, Redeemer> =
366+
[
367+
Pair(purpose, mint_voucher_redeemer_in_data),
368+
Pair(
369+
Spend(mock_data.module_input.output_reference),
370+
spend_module_redeemer_in_data,
371+
),
372+
]
373+
374+
let transaction =
375+
Transaction {
376+
..transaction.placeholder,
377+
inputs: [mock_data.module_input],
378+
outputs: outputs,
379+
redeemers: redeemers,
380+
mint: mint,
381+
}
382+
383+
minting_voucher.mint_voucher.mint(
384+
mock_data.module_token,
385+
mint_voucher_redeemer,
386+
mock_data.voucher_minting_policy_id,
387+
transaction,
388+
)
389+
}

0 commit comments

Comments
 (0)