@@ -1297,6 +1297,11 @@ impl TransactionBuilder {
12971297 let input_total = self . get_total_input ( ) ?;
12981298 let output_total = self . get_total_output ( ) ?;
12991299
1300+ let shortage = get_input_shortage ( & input_total, & output_total, & fee) ?;
1301+ if let Some ( shortage) = shortage {
1302+ return Err ( JsError :: from_str ( & format ! ( "Insufficient input in transaction. {}" , shortage) ) ) ;
1303+ }
1304+
13001305 use std:: cmp:: Ordering ;
13011306 match & input_total. partial_cmp ( & output_total. checked_add ( & Value :: new ( & fee) ) ?) {
13021307 Some ( Ordering :: Equal ) => {
@@ -2921,6 +2926,196 @@ mod tests {
29212926 ) ;
29222927 }
29232928
2929+ #[ test]
2930+ fn change_with_input_and_mint_not_enough_ada ( ) {
2931+ let mut tx_builder = create_tx_builder_with_fee ( & create_linear_fee ( 1 , 1 ) ) ;
2932+ let spend = root_key_15 ( )
2933+ . derive ( harden ( 1852 ) )
2934+ . derive ( harden ( 1815 ) )
2935+ . derive ( harden ( 0 ) )
2936+ . derive ( 0 )
2937+ . derive ( 0 )
2938+ . to_public ( ) ;
2939+ let change_key = root_key_15 ( )
2940+ . derive ( harden ( 1852 ) )
2941+ . derive ( harden ( 1815 ) )
2942+ . derive ( harden ( 0 ) )
2943+ . derive ( 1 )
2944+ . derive ( 0 )
2945+ . to_public ( ) ;
2946+ let stake = root_key_15 ( )
2947+ . derive ( harden ( 1852 ) )
2948+ . derive ( harden ( 1815 ) )
2949+ . derive ( harden ( 0 ) )
2950+ . derive ( 2 )
2951+ . derive ( 0 )
2952+ . to_public ( ) ;
2953+
2954+ let spend_cred = StakeCredential :: from_keyhash ( & spend. to_raw_key ( ) . hash ( ) ) ;
2955+ let stake_cred = StakeCredential :: from_keyhash ( & stake. to_raw_key ( ) . hash ( ) ) ;
2956+
2957+ let ( min_script, policy_id) = mint_script_and_policy ( 0 ) ;
2958+ let asset_name = AssetName :: new ( vec ! [ 0u8 , 1 , 2 , 3 ] ) . unwrap ( ) ;
2959+
2960+ let amount_minted = to_bignum ( 1000 ) ;
2961+ let amount_sent = to_bignum ( 500 ) ;
2962+ let amount_input_amount = to_bignum ( 600 ) ;
2963+
2964+ let mut asset_input = Assets :: new ( ) ;
2965+ asset_input. insert ( & asset_name, & amount_input_amount) ;
2966+ let mut mass_input = MultiAsset :: new ( ) ;
2967+ mass_input. insert ( & policy_id, & asset_input) ;
2968+
2969+ // Input with 600 coins
2970+ tx_builder. add_input (
2971+ & EnterpriseAddress :: new ( NetworkInfo :: testnet ( ) . network_id ( ) , & spend_cred) . to_address ( ) ,
2972+ & TransactionInput :: new ( & genesis_id ( ) , 0 ) ,
2973+ & Value :: new ( & to_bignum ( 600 ) ) ,
2974+ ) ;
2975+
2976+ tx_builder. add_input (
2977+ & EnterpriseAddress :: new ( NetworkInfo :: testnet ( ) . network_id ( ) , & spend_cred) . to_address ( ) ,
2978+ & TransactionInput :: new ( & genesis_id ( ) , 1 ) ,
2979+ & Value :: new_with_assets ( & to_bignum ( 1 ) , & mass_input) ,
2980+ ) ;
2981+
2982+ let addr_net_0 = BaseAddress :: new (
2983+ NetworkInfo :: testnet ( ) . network_id ( ) ,
2984+ & spend_cred,
2985+ & stake_cred,
2986+ ) . to_address ( ) ;
2987+
2988+ // Adding mint of the asset - which should work as an input
2989+ tx_builder. add_mint_asset ( & min_script, & asset_name, Int :: new ( & amount_minted) ) ;
2990+
2991+ let mut asset = Assets :: new ( ) ;
2992+ asset. insert ( & asset_name, & amount_sent) ;
2993+ let mut mass = MultiAsset :: new ( ) ;
2994+ mass. insert ( & policy_id, & asset) ;
2995+
2996+ // One coin and the minted asset goes into the output
2997+ let mut output_amount = Value :: new ( & to_bignum ( 400 ) ) ;
2998+ output_amount. set_multiasset ( & mass) ;
2999+
3000+ tx_builder
3001+ . add_output (
3002+ & TransactionOutputBuilder :: new ( )
3003+ . with_address ( & addr_net_0)
3004+ . next ( )
3005+ . unwrap ( )
3006+ . with_value ( & output_amount)
3007+ . build ( )
3008+ . unwrap ( ) ,
3009+ )
3010+ . unwrap ( ) ;
3011+
3012+ let change_cred = StakeCredential :: from_keyhash ( & change_key. to_raw_key ( ) . hash ( ) ) ;
3013+ let change_addr = BaseAddress :: new (
3014+ NetworkInfo :: testnet ( ) . network_id ( ) ,
3015+ & change_cred,
3016+ & stake_cred,
3017+ )
3018+ . to_address ( ) ;
3019+
3020+ let added_change = tx_builder. add_change_if_needed ( & change_addr) ;
3021+ assert ! ( added_change. is_err( ) ) ;
3022+ }
3023+
3024+ #[ test]
3025+ fn change_with_input_and_mint_not_enough_assets ( ) {
3026+ let mut tx_builder = create_tx_builder_with_fee ( & create_linear_fee ( 1 , 1 ) ) ;
3027+ let spend = root_key_15 ( )
3028+ . derive ( harden ( 1852 ) )
3029+ . derive ( harden ( 1815 ) )
3030+ . derive ( harden ( 0 ) )
3031+ . derive ( 0 )
3032+ . derive ( 0 )
3033+ . to_public ( ) ;
3034+ let change_key = root_key_15 ( )
3035+ . derive ( harden ( 1852 ) )
3036+ . derive ( harden ( 1815 ) )
3037+ . derive ( harden ( 0 ) )
3038+ . derive ( 1 )
3039+ . derive ( 0 )
3040+ . to_public ( ) ;
3041+ let stake = root_key_15 ( )
3042+ . derive ( harden ( 1852 ) )
3043+ . derive ( harden ( 1815 ) )
3044+ . derive ( harden ( 0 ) )
3045+ . derive ( 2 )
3046+ . derive ( 0 )
3047+ . to_public ( ) ;
3048+
3049+ let spend_cred = StakeCredential :: from_keyhash ( & spend. to_raw_key ( ) . hash ( ) ) ;
3050+ let stake_cred = StakeCredential :: from_keyhash ( & stake. to_raw_key ( ) . hash ( ) ) ;
3051+
3052+ let ( min_script, policy_id) = mint_script_and_policy ( 0 ) ;
3053+ let asset_name = AssetName :: new ( vec ! [ 0u8 , 1 , 2 , 3 ] ) . unwrap ( ) ;
3054+
3055+ let amount_minted = to_bignum ( 1000 ) ;
3056+ let amount_sent = to_bignum ( 100000 ) ;
3057+ let amount_input_amount = to_bignum ( 600 ) ;
3058+
3059+ let mut asset_input = Assets :: new ( ) ;
3060+ asset_input. insert ( & asset_name, & amount_input_amount) ;
3061+ let mut mass_input = MultiAsset :: new ( ) ;
3062+ mass_input. insert ( & policy_id, & asset_input) ;
3063+
3064+ // Input with 600 coins
3065+ tx_builder. add_input (
3066+ & EnterpriseAddress :: new ( NetworkInfo :: testnet ( ) . network_id ( ) , & spend_cred) . to_address ( ) ,
3067+ & TransactionInput :: new ( & genesis_id ( ) , 0 ) ,
3068+ & Value :: new ( & to_bignum ( 100000 ) ) ,
3069+ ) ;
3070+
3071+ tx_builder. add_input (
3072+ & EnterpriseAddress :: new ( NetworkInfo :: testnet ( ) . network_id ( ) , & spend_cred) . to_address ( ) ,
3073+ & TransactionInput :: new ( & genesis_id ( ) , 1 ) ,
3074+ & Value :: new_with_assets ( & to_bignum ( 1 ) , & mass_input) ,
3075+ ) ;
3076+
3077+ let addr_net_0 = BaseAddress :: new (
3078+ NetworkInfo :: testnet ( ) . network_id ( ) ,
3079+ & spend_cred,
3080+ & stake_cred,
3081+ ) . to_address ( ) ;
3082+
3083+ // Adding mint of the asset - which should work as an input
3084+ tx_builder. add_mint_asset ( & min_script, & asset_name, Int :: new ( & amount_minted) ) ;
3085+
3086+ let mut asset = Assets :: new ( ) ;
3087+ asset. insert ( & asset_name, & amount_sent) ;
3088+ let mut mass = MultiAsset :: new ( ) ;
3089+ mass. insert ( & policy_id, & asset) ;
3090+
3091+ // One coin and the minted asset goes into the output
3092+ let mut output_amount = Value :: new ( & to_bignum ( 400 ) ) ;
3093+ output_amount. set_multiasset ( & mass) ;
3094+
3095+ tx_builder
3096+ . add_output (
3097+ & TransactionOutputBuilder :: new ( )
3098+ . with_address ( & addr_net_0)
3099+ . next ( )
3100+ . unwrap ( )
3101+ . with_value ( & output_amount)
3102+ . build ( )
3103+ . unwrap ( ) ,
3104+ )
3105+ . unwrap ( ) ;
3106+
3107+ let change_cred = StakeCredential :: from_keyhash ( & change_key. to_raw_key ( ) . hash ( ) ) ;
3108+ let change_addr = BaseAddress :: new (
3109+ NetworkInfo :: testnet ( ) . network_id ( ) ,
3110+ & change_cred,
3111+ & stake_cred,
3112+ )
3113+ . to_address ( ) ;
3114+
3115+ let added_change = tx_builder. add_change_if_needed ( & change_addr) ;
3116+ assert ! ( added_change. is_err( ) ) ;
3117+ }
3118+
29243119 #[ ignore]
29253120 #[ test]
29263121 fn build_tx_with_native_assets_change ( ) {
0 commit comments