Skip to main content

hiero_sdk/contract/
contract_create_transaction.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use hiero_sdk_proto::services;
4use hiero_sdk_proto::services::smart_contract_service_client::SmartContractServiceClient;
5use time::Duration;
6use tonic::transport::Channel;
7
8use crate::hooks::HookCreationDetails;
9use crate::ledger_id::RefLedgerId;
10use crate::protobuf::FromProtobuf;
11use crate::staked_id::StakedId;
12use crate::transaction::{
13    AnyTransactionData,
14    ChunkInfo,
15    ToSchedulableTransactionDataProtobuf,
16    ToTransactionDataProtobuf,
17    TransactionData,
18    TransactionExecute,
19};
20use crate::{
21    AccountId,
22    BoxGrpcFuture,
23    Error,
24    FileId,
25    Hbar,
26    Key,
27    ToProtobuf,
28    Transaction,
29    ValidateChecksums,
30};
31
32/// Start a new smart contract instance.
33pub type ContractCreateTransaction = Transaction<ContractCreateTransactionData>;
34
35#[derive(Debug, Clone)]
36pub struct ContractCreateTransactionData {
37    bytecode: Option<Vec<u8>>,
38
39    bytecode_file_id: Option<FileId>,
40
41    admin_key: Option<Key>,
42
43    gas: u64,
44
45    initial_balance: Hbar,
46
47    auto_renew_period: Duration,
48
49    constructor_parameters: Vec<u8>,
50
51    contract_memo: String,
52
53    max_automatic_token_associations: i32,
54
55    auto_renew_account_id: Option<AccountId>,
56
57    /// ID of the account or node to which this contract is staking, if any.
58    staked_id: Option<StakedId>,
59
60    decline_staking_reward: bool,
61
62    /// Hooks to add immediately after creating this contract.
63    hooks: Vec<HookCreationDetails>,
64}
65
66impl Default for ContractCreateTransactionData {
67    fn default() -> Self {
68        Self {
69            bytecode: None,
70            bytecode_file_id: None,
71            admin_key: None,
72            gas: 0,
73            initial_balance: Hbar::ZERO,
74            auto_renew_period: Duration::days(90),
75            constructor_parameters: Vec::new(),
76            contract_memo: String::new(),
77            max_automatic_token_associations: 0,
78            auto_renew_account_id: None,
79            staked_id: None,
80            decline_staking_reward: false,
81            hooks: Vec::new(),
82        }
83    }
84}
85
86impl ContractCreateTransaction {
87    /// Returns the `FileId` to be used as the bytecode for this smart contract.
88    #[must_use]
89    pub fn get_bytecode_file_id(&self) -> Option<FileId> {
90        self.data().bytecode_file_id
91    }
92
93    /// Sets the file to use as the bytes for the smart contract.
94    pub fn bytecode_file_id(&mut self, file_id: FileId) -> &mut Self {
95        self.data_mut().bytecode_file_id = Some(file_id);
96        self
97    }
98
99    /// Returns the bytecode for the smart contract.
100    #[must_use]
101    pub fn get_bytecode(&self) -> Option<&[u8]> {
102        self.data().bytecode.as_deref()
103    }
104
105    /// Sets the bytes of the smart contract.
106    pub fn bytecode(&mut self, bytecode: impl AsRef<[u8]>) -> &mut Self {
107        self.data_mut().bytecode = Some(bytecode.as_ref().to_vec());
108        self
109    }
110
111    /// Returns the admin key.
112    #[must_use]
113    pub fn get_admin_key(&self) -> Option<&Key> {
114        self.data().admin_key.as_ref()
115    }
116
117    /// Sets the admin key.
118    pub fn admin_key(&mut self, key: impl Into<Key>) -> &mut Self {
119        self.data_mut().admin_key = Some(key.into());
120        self
121    }
122
123    /// Returns the gas limit to deploy the smart contract.
124    #[must_use]
125    pub fn get_gas(&self) -> u64 {
126        self.data().gas
127    }
128
129    /// Sets the gas limit to deploy the smart contract.
130    pub fn gas(&mut self, gas: u64) -> &mut Self {
131        self.data_mut().gas = gas;
132        self
133    }
134
135    /// Returns the initial balance to put into the cryptocurrency account associated with the new smart contract.
136    #[must_use]
137    pub fn get_initial_balance(&self) -> Hbar {
138        self.data().initial_balance
139    }
140
141    /// Sets the initial balance to put into the cryptocurrency account associated with the new
142    /// smart contract.
143    pub fn initial_balance(&mut self, balance: Hbar) -> &mut Self {
144        self.data_mut().initial_balance = balance;
145        self
146    }
147
148    /// Returns the auto renew period for this smart contract.
149    #[must_use]
150    pub fn get_auto_renew_period(&self) -> Duration {
151        self.data().auto_renew_period
152    }
153
154    /// Sets the auto renew period for this smart contract.
155    pub fn auto_renew_period(&mut self, period: Duration) -> &mut Self {
156        self.data_mut().auto_renew_period = period;
157        self
158    }
159
160    /// Returns the parameters to pass to the constructor.
161    #[must_use]
162    pub fn get_constructor_parameters(&self) -> &[u8] {
163        self.data().constructor_parameters.as_ref()
164    }
165
166    /// Sets the parameters to pass to the constructor.
167    pub fn constructor_parameters(&mut self, parameters: impl AsRef<[u8]>) -> &mut Self {
168        self.data_mut().constructor_parameters = parameters.as_ref().to_vec();
169        self
170    }
171
172    /// Returns the memo for the new smart contract.
173    #[must_use]
174    pub fn get_contract_memo(&self) -> &str {
175        self.data().contract_memo.as_str()
176    }
177
178    /// Sets the memo for the new smart contract.
179    pub fn contract_memo(&mut self, memo: impl Into<String>) -> &mut Self {
180        self.data_mut().contract_memo = memo.into();
181        self
182    }
183
184    /// Returns the maximum number of tokens that the contract can be automatically associated with.
185    #[must_use]
186    pub fn get_max_automatic_token_associations(&self) -> i32 {
187        self.data().max_automatic_token_associations
188    }
189
190    /// Sets the maximum number of tokens that this contract can be automatically associated with.
191    pub fn max_automatic_token_associations(&mut self, max: i32) -> &mut Self {
192        self.data_mut().max_automatic_token_associations = max;
193        self
194    }
195
196    /// Returns the account ot be used at the contract's expiration time to extend the
197    /// life of the contract
198    #[must_use]
199    pub fn get_auto_renew_account_id(&self) -> Option<AccountId> {
200        self.data().auto_renew_account_id
201    }
202
203    /// Sets the account to be used at the contract's expiration time to extend the
204    /// life of the contract.
205    pub fn auto_renew_account_id(&mut self, account_id: AccountId) -> &mut Self {
206        self.data_mut().auto_renew_account_id = Some(account_id);
207        self
208    }
209
210    /// Returns the ID of the account to which this contract is staking.
211    #[must_use]
212    pub fn get_staked_account_id(&self) -> Option<AccountId> {
213        self.data().staked_id.and_then(StakedId::to_account_id)
214    }
215
216    /// Sets the ID of the account to which this contract is staking.
217    ///
218    /// This is mutually exclusive with [`staked_node_id`](Self::staked_node_id).
219    pub fn staked_account_id(&mut self, id: AccountId) -> &mut Self {
220        self.data_mut().staked_id = Some(id.into());
221        self
222    }
223
224    /// Returns the ID of the node to which this contract is staking.
225    #[must_use]
226    pub fn get_staked_node_id(&self) -> Option<u64> {
227        self.data().staked_id.and_then(StakedId::to_node_id)
228    }
229
230    /// Sets the ID of the node to which this contract is staking.
231    /// This is mutually exclusive with [`staked_account_id`](Self::staked_account_id).
232    pub fn staked_node_id(&mut self, id: u64) -> &mut Self {
233        self.data_mut().staked_id = Some(id.into());
234        self
235    }
236
237    /// Returns `true` if the contract will decline receiving staking rewards, `false` otherwise.
238    #[must_use]
239    pub fn get_decline_staking_reward(&self) -> bool {
240        self.data().decline_staking_reward
241    }
242
243    /// If `true` the contract should declie receiving staking rewards. The default value is `false`.
244    pub fn decline_staking_reward(&mut self, decline: bool) -> &mut Self {
245        self.data_mut().decline_staking_reward = decline;
246        self
247    }
248
249    /// Returns the hooks to be created.
250    #[must_use]
251    pub fn get_hooks_to_create(&self) -> &[HookCreationDetails] {
252        &self.data().hooks
253    }
254
255    /// Adds a hook to be created.
256    pub fn add_hook(&mut self, hook: HookCreationDetails) -> &mut Self {
257        self.data_mut().hooks.push(hook);
258        self
259    }
260
261    /// Sets the hooks to be created.
262    pub fn set_hooks(&mut self, hooks: Vec<HookCreationDetails>) -> &mut Self {
263        self.data_mut().hooks = hooks;
264        self
265    }
266}
267
268impl TransactionData for ContractCreateTransactionData {
269    fn default_max_transaction_fee(&self) -> crate::Hbar {
270        crate::Hbar::new(20)
271    }
272}
273
274impl TransactionExecute for ContractCreateTransactionData {
275    fn execute(
276        &self,
277        channel: Channel,
278        request: services::Transaction,
279    ) -> BoxGrpcFuture<'_, services::TransactionResponse> {
280        Box::pin(async { SmartContractServiceClient::new(channel).create_contract(request).await })
281    }
282}
283
284impl ValidateChecksums for ContractCreateTransactionData {
285    fn validate_checksums(&self, ledger_id: &RefLedgerId) -> Result<(), Error> {
286        self.bytecode_file_id.validate_checksums(ledger_id)?;
287        self.auto_renew_account_id.validate_checksums(ledger_id)?;
288        self.staked_id.validate_checksums(ledger_id)
289    }
290}
291
292impl ToTransactionDataProtobuf for ContractCreateTransactionData {
293    fn to_transaction_data_protobuf(
294        &self,
295        chunk_info: &ChunkInfo,
296    ) -> services::transaction_body::Data {
297        let _ = chunk_info.assert_single_transaction();
298
299        services::transaction_body::Data::ContractCreateInstance(self.to_protobuf())
300    }
301}
302
303impl ToSchedulableTransactionDataProtobuf for ContractCreateTransactionData {
304    fn to_schedulable_transaction_data_protobuf(
305        &self,
306    ) -> services::schedulable_transaction_body::Data {
307        services::schedulable_transaction_body::Data::ContractCreateInstance(self.to_protobuf())
308    }
309}
310
311impl From<ContractCreateTransactionData> for AnyTransactionData {
312    fn from(transaction: ContractCreateTransactionData) -> Self {
313        Self::ContractCreate(transaction)
314    }
315}
316
317impl FromProtobuf<services::ContractCreateTransactionBody> for ContractCreateTransactionData {
318    fn from_protobuf(pb: services::ContractCreateTransactionBody) -> crate::Result<Self> {
319        use services::contract_create_transaction_body::InitcodeSource;
320        let (bytecode, bytecode_file_id) = match pb.initcode_source {
321            Some(InitcodeSource::FileId(it)) => (None, Some(FileId::from_protobuf(it)?)),
322            Some(InitcodeSource::Initcode(it)) => (Some(it), None),
323            None => (None, None),
324        };
325
326        Ok(Self {
327            bytecode,
328            bytecode_file_id,
329            admin_key: Option::from_protobuf(pb.admin_key)?,
330            gas: pb.gas as u64,
331            initial_balance: Hbar::from_tinybars(pb.initial_balance),
332            auto_renew_period: pb_getf!(pb, auto_renew_period)?.into(),
333            constructor_parameters: pb.constructor_parameters,
334            contract_memo: pb.memo,
335            max_automatic_token_associations: pb.max_automatic_token_associations,
336            auto_renew_account_id: Option::from_protobuf(pb.auto_renew_account_id)?,
337            staked_id: Option::from_protobuf(pb.staked_id)?,
338            decline_staking_reward: pb.decline_reward,
339            hooks: pb
340                .hook_creation_details
341                .into_iter()
342                .map(HookCreationDetails::from_protobuf)
343                .collect::<Result<Vec<_>, _>>()?,
344        })
345    }
346}
347
348impl ToProtobuf for ContractCreateTransactionData {
349    type Protobuf = services::ContractCreateTransactionBody;
350
351    fn to_protobuf(&self) -> Self::Protobuf {
352        let admin_key = self.admin_key.to_protobuf();
353        let auto_renew_period = self.auto_renew_period.into();
354        let auto_renew_account_id = self.auto_renew_account_id.to_protobuf();
355
356        let initcode_source = match (&self.bytecode, &self.bytecode_file_id) {
357            (_, Some(file_id)) => {
358                Some(services::contract_create_transaction_body::InitcodeSource::FileId(
359                    file_id.to_protobuf(),
360                ))
361            }
362
363            (Some(bytecode), _) => {
364                Some(services::contract_create_transaction_body::InitcodeSource::Initcode(
365                    bytecode.clone(),
366                ))
367            }
368
369            _ => None,
370        };
371
372        let staked_id = match self.staked_id {
373            Some(StakedId::NodeId(node_id)) => Some(
374                services::contract_create_transaction_body::StakedId::StakedNodeId(node_id as i64),
375            ),
376
377            Some(StakedId::AccountId(account_id)) => {
378                Some(services::contract_create_transaction_body::StakedId::StakedAccountId(
379                    account_id.to_protobuf(),
380                ))
381            }
382
383            _ => None,
384        };
385
386        #[allow(deprecated)]
387        services::ContractCreateTransactionBody {
388            admin_key,
389            gas: self.gas as i64,
390            initial_balance: self.initial_balance.to_tinybars(),
391            proxy_account_id: None,
392            auto_renew_period: Some(auto_renew_period),
393            constructor_parameters: self.constructor_parameters.clone(),
394            shard_id: None,
395            realm_id: None,
396            new_realm_admin_key: None,
397            memo: self.contract_memo.clone(),
398            max_automatic_token_associations: self.max_automatic_token_associations,
399            auto_renew_account_id,
400            decline_reward: self.decline_staking_reward,
401            initcode_source,
402            staked_id,
403            hook_creation_details: self.hooks.iter().map(|hook| hook.to_protobuf()).collect(),
404        }
405    }
406}
407
408#[cfg(test)]
409mod tests {
410
411    use expect_test::expect;
412    use hiero_sdk_proto::services;
413    use time::Duration;
414
415    use crate::contract::ContractCreateTransactionData;
416    use crate::protobuf::{
417        FromProtobuf,
418        ToProtobuf,
419    };
420    use crate::transaction::test_helpers::{
421        check_body,
422        transaction_body,
423        unused_private_key,
424    };
425    use crate::{
426        AccountId,
427        AnyTransaction,
428        ContractCreateTransaction,
429        ContractId,
430        EvmHook,
431        EvmHookSpec,
432        FileId,
433        Hbar,
434        HookCreationDetails,
435        HookExtensionPoint,
436        PublicKey,
437    };
438
439    const BYTECODE: [u8; 4] = [0xde, 0xad, 0xbe, 0xef];
440    const BYTECODE_FILE_ID: FileId = FileId::new(0, 0, 3003);
441
442    fn admin_key() -> PublicKey {
443        unused_private_key().public_key()
444    }
445
446    const GAS: u64 = 0;
447    const INITIAL_BALANCE: Hbar = Hbar::from_tinybars(1000);
448    const MAX_AUTOMATIC_TOKEN_ASSOCIATIONS: i32 = 101;
449    const AUTO_RENEW_PERIOD: Duration = Duration::hours(10);
450    const CONSTRUCTOR_PARAMETERS: [u8; 5] = [10, 11, 12, 13, 25];
451    const AUTO_RENEW_ACCOUNT_ID: AccountId = AccountId::new(0, 0, 30);
452    const STAKED_ACCOUNT_ID: AccountId = AccountId::new(0, 0, 3);
453    const STAKED_NODE_ID: u64 = 4;
454
455    fn make_transaction() -> ContractCreateTransaction {
456        let mut tx = ContractCreateTransaction::new_for_tests();
457
458        tx.bytecode_file_id(BYTECODE_FILE_ID)
459            .admin_key(admin_key())
460            .gas(GAS)
461            .initial_balance(INITIAL_BALANCE)
462            .staked_account_id(STAKED_ACCOUNT_ID)
463            .max_automatic_token_associations(MAX_AUTOMATIC_TOKEN_ASSOCIATIONS)
464            .auto_renew_period(AUTO_RENEW_PERIOD)
465            .constructor_parameters(CONSTRUCTOR_PARAMETERS)
466            .auto_renew_account_id(AUTO_RENEW_ACCOUNT_ID)
467            .freeze()
468            .unwrap();
469
470        tx
471    }
472
473    fn make_transaction2() -> ContractCreateTransaction {
474        let mut tx = ContractCreateTransaction::new_for_tests();
475
476        tx.bytecode(&BYTECODE)
477            .admin_key(admin_key())
478            .gas(GAS)
479            .initial_balance(INITIAL_BALANCE)
480            .staked_node_id(STAKED_NODE_ID)
481            .max_automatic_token_associations(MAX_AUTOMATIC_TOKEN_ASSOCIATIONS)
482            .auto_renew_period(AUTO_RENEW_PERIOD)
483            .constructor_parameters(CONSTRUCTOR_PARAMETERS)
484            .auto_renew_account_id(AUTO_RENEW_ACCOUNT_ID)
485            .freeze()
486            .unwrap();
487
488        tx
489    }
490
491    #[test]
492    fn serialize() {
493        let tx = make_transaction();
494
495        let tx = transaction_body(tx);
496
497        let tx = check_body(tx);
498
499        expect![[r#"
500            ContractCreateInstance(
501                ContractCreateTransactionBody {
502                    admin_key: Some(
503                        Key {
504                            key: Some(
505                                Ed25519(
506                                    [
507                                        224,
508                                        200,
509                                        236,
510                                        39,
511                                        88,
512                                        165,
513                                        135,
514                                        159,
515                                        250,
516                                        194,
517                                        38,
518                                        161,
519                                        60,
520                                        12,
521                                        81,
522                                        107,
523                                        121,
524                                        158,
525                                        114,
526                                        227,
527                                        81,
528                                        65,
529                                        160,
530                                        221,
531                                        130,
532                                        143,
533                                        148,
534                                        211,
535                                        121,
536                                        136,
537                                        164,
538                                        183,
539                                    ],
540                                ),
541                            ),
542                        },
543                    ),
544                    gas: 0,
545                    initial_balance: 1000,
546                    proxy_account_id: None,
547                    auto_renew_period: Some(
548                        Duration {
549                            seconds: 36000,
550                        },
551                    ),
552                    constructor_parameters: [
553                        10,
554                        11,
555                        12,
556                        13,
557                        25,
558                    ],
559                    shard_id: None,
560                    realm_id: None,
561                    new_realm_admin_key: None,
562                    memo: "",
563                    max_automatic_token_associations: 101,
564                    auto_renew_account_id: Some(
565                        AccountId {
566                            shard_num: 0,
567                            realm_num: 0,
568                            account: Some(
569                                AccountNum(
570                                    30,
571                                ),
572                            ),
573                        },
574                    ),
575                    decline_reward: false,
576                    hook_creation_details: [],
577                    initcode_source: Some(
578                        FileId(
579                            FileId {
580                                shard_num: 0,
581                                realm_num: 0,
582                                file_num: 3003,
583                            },
584                        ),
585                    ),
586                    staked_id: Some(
587                        StakedAccountId(
588                            AccountId {
589                                shard_num: 0,
590                                realm_num: 0,
591                                account: Some(
592                                    AccountNum(
593                                        3,
594                                    ),
595                                ),
596                            },
597                        ),
598                    ),
599                },
600            )
601        "#]]
602        .assert_debug_eq(&tx)
603    }
604
605    #[test]
606    fn to_from_bytes() {
607        let tx = make_transaction();
608
609        let tx2 = AnyTransaction::from_bytes(&tx.to_bytes().unwrap()).unwrap();
610
611        let tx = transaction_body(tx);
612
613        let tx2 = transaction_body(tx2);
614
615        assert_eq!(tx, tx2);
616    }
617
618    #[test]
619    fn serialize2() {
620        let tx = make_transaction2();
621
622        let tx = transaction_body(tx);
623
624        let tx = check_body(tx);
625
626        expect![[r#"
627            ContractCreateInstance(
628                ContractCreateTransactionBody {
629                    admin_key: Some(
630                        Key {
631                            key: Some(
632                                Ed25519(
633                                    [
634                                        224,
635                                        200,
636                                        236,
637                                        39,
638                                        88,
639                                        165,
640                                        135,
641                                        159,
642                                        250,
643                                        194,
644                                        38,
645                                        161,
646                                        60,
647                                        12,
648                                        81,
649                                        107,
650                                        121,
651                                        158,
652                                        114,
653                                        227,
654                                        81,
655                                        65,
656                                        160,
657                                        221,
658                                        130,
659                                        143,
660                                        148,
661                                        211,
662                                        121,
663                                        136,
664                                        164,
665                                        183,
666                                    ],
667                                ),
668                            ),
669                        },
670                    ),
671                    gas: 0,
672                    initial_balance: 1000,
673                    proxy_account_id: None,
674                    auto_renew_period: Some(
675                        Duration {
676                            seconds: 36000,
677                        },
678                    ),
679                    constructor_parameters: [
680                        10,
681                        11,
682                        12,
683                        13,
684                        25,
685                    ],
686                    shard_id: None,
687                    realm_id: None,
688                    new_realm_admin_key: None,
689                    memo: "",
690                    max_automatic_token_associations: 101,
691                    auto_renew_account_id: Some(
692                        AccountId {
693                            shard_num: 0,
694                            realm_num: 0,
695                            account: Some(
696                                AccountNum(
697                                    30,
698                                ),
699                            ),
700                        },
701                    ),
702                    decline_reward: false,
703                    hook_creation_details: [],
704                    initcode_source: Some(
705                        Initcode(
706                            [
707                                222,
708                                173,
709                                190,
710                                239,
711                            ],
712                        ),
713                    ),
714                    staked_id: Some(
715                        StakedNodeId(
716                            4,
717                        ),
718                    ),
719                },
720            )
721        "#]]
722        .assert_debug_eq(&tx)
723    }
724
725    #[test]
726    fn to_from_bytes2() {
727        let tx = make_transaction2();
728
729        let tx2 = AnyTransaction::from_bytes(&tx.to_bytes().unwrap()).unwrap();
730
731        let tx = transaction_body(tx);
732
733        let tx2 = transaction_body(tx2);
734
735        assert_eq!(tx, tx2);
736    }
737
738    #[test]
739    fn from_proto_body() {
740        #[allow(deprecated)]
741        let contract_id = ContractId::new(0, 0, 1);
742        let hooks = vec![HookCreationDetails::new(
743            HookExtensionPoint::AccountAllowanceHook,
744            0,
745            Some(EvmHook::new(EvmHookSpec::new(Some(contract_id)), vec![])),
746        )];
747
748        let tx = services::ContractCreateTransactionBody {
749            admin_key: Some(admin_key().to_protobuf()),
750            initial_balance: INITIAL_BALANCE.to_tinybars(),
751            proxy_account_id: None,
752            auto_renew_period: Some(AUTO_RENEW_PERIOD.to_protobuf()),
753            shard_id: None,
754            realm_id: None,
755            new_realm_admin_key: None,
756            memo: String::new(),
757            max_automatic_token_associations: MAX_AUTOMATIC_TOKEN_ASSOCIATIONS,
758            decline_reward: false,
759            staked_id: Some(services::contract_create_transaction_body::StakedId::StakedAccountId(
760                STAKED_ACCOUNT_ID.to_protobuf(),
761            )),
762            gas: GAS as _,
763            constructor_parameters: CONSTRUCTOR_PARAMETERS.to_vec(),
764            auto_renew_account_id: Some(AUTO_RENEW_ACCOUNT_ID.to_protobuf()),
765            initcode_source: Some(
766                services::contract_create_transaction_body::InitcodeSource::FileId(
767                    BYTECODE_FILE_ID.to_protobuf(),
768                ),
769            ),
770            hook_creation_details: hooks.iter().map(|h| h.to_protobuf()).collect(),
771        };
772        let tx = ContractCreateTransactionData::from_protobuf(tx).unwrap();
773
774        assert_eq!(tx.bytecode, None);
775        assert_eq!(tx.bytecode_file_id, Some(BYTECODE_FILE_ID));
776        assert_eq!(tx.admin_key, Some(admin_key().into()));
777        assert_eq!(tx.gas, GAS);
778        assert_eq!(tx.initial_balance, INITIAL_BALANCE);
779        assert_eq!(tx.staked_id, Some(crate::staked_id::StakedId::AccountId(STAKED_ACCOUNT_ID)));
780        assert_eq!(tx.max_automatic_token_associations, MAX_AUTOMATIC_TOKEN_ASSOCIATIONS);
781        assert_eq!(tx.auto_renew_period, AUTO_RENEW_PERIOD);
782        assert_eq!(tx.constructor_parameters, CONSTRUCTOR_PARAMETERS);
783        assert_eq!(tx.auto_renew_account_id, Some(AUTO_RENEW_ACCOUNT_ID));
784    }
785
786    #[test]
787    fn get_set_bytecode() {
788        let mut tx = ContractCreateTransaction::new();
789        tx.bytecode(BYTECODE);
790
791        assert_eq!(tx.get_bytecode(), Some(BYTECODE.as_slice()));
792    }
793
794    #[test]
795    #[should_panic]
796    fn get_set_bytecode_frozen_panics() {
797        make_transaction().bytecode(BYTECODE);
798    }
799
800    #[test]
801    fn get_set_bytecode_file_id() {
802        let mut tx = ContractCreateTransaction::new();
803        tx.bytecode_file_id(BYTECODE_FILE_ID);
804
805        assert_eq!(tx.get_bytecode_file_id(), Some(BYTECODE_FILE_ID));
806    }
807
808    #[test]
809    #[should_panic]
810    fn get_set_bytecode_file_id_frozen_panics() {
811        make_transaction().bytecode_file_id(BYTECODE_FILE_ID);
812    }
813
814    #[test]
815    fn get_set_admin_key() {
816        let mut tx = ContractCreateTransaction::new();
817        tx.admin_key(admin_key());
818
819        assert_eq!(tx.get_admin_key(), Some(&admin_key().into()));
820    }
821
822    #[test]
823    #[should_panic]
824    fn get_set_admin_key_frozen_panics() {
825        make_transaction().admin_key(admin_key());
826    }
827
828    #[test]
829    fn get_set_gas() {
830        let mut tx = ContractCreateTransaction::new();
831        tx.gas(GAS);
832
833        assert_eq!(tx.get_gas(), GAS);
834    }
835
836    #[test]
837    #[should_panic]
838    fn get_set_gas_frozen_panics() {
839        make_transaction().gas(GAS);
840    }
841
842    #[test]
843    fn get_set_initial_balance() {
844        let mut tx = ContractCreateTransaction::new();
845        tx.initial_balance(INITIAL_BALANCE);
846
847        assert_eq!(tx.get_initial_balance(), INITIAL_BALANCE);
848    }
849
850    #[test]
851    #[should_panic]
852    fn get_set_initial_balance_frozen_panics() {
853        make_transaction().initial_balance(INITIAL_BALANCE);
854    }
855
856    #[test]
857    fn get_set_max_automatic_token_associations() {
858        let mut tx = ContractCreateTransaction::new();
859        tx.max_automatic_token_associations(MAX_AUTOMATIC_TOKEN_ASSOCIATIONS);
860
861        assert_eq!(tx.get_max_automatic_token_associations(), MAX_AUTOMATIC_TOKEN_ASSOCIATIONS);
862    }
863
864    #[test]
865    #[should_panic]
866    fn get_set_max_automatic_token_associations_frozen_panics() {
867        make_transaction().max_automatic_token_associations(MAX_AUTOMATIC_TOKEN_ASSOCIATIONS);
868    }
869
870    #[test]
871    fn get_set_auto_renew_period() {
872        let mut tx = ContractCreateTransaction::new();
873        tx.auto_renew_period(AUTO_RENEW_PERIOD);
874
875        assert_eq!(tx.get_auto_renew_period(), AUTO_RENEW_PERIOD);
876    }
877
878    #[test]
879    #[should_panic]
880    fn get_set_auto_renew_period_frozen_panics() {
881        make_transaction().auto_renew_period(AUTO_RENEW_PERIOD);
882    }
883
884    #[test]
885    fn get_set_constructor_parameters() {
886        let mut tx = ContractCreateTransaction::new();
887        tx.constructor_parameters(CONSTRUCTOR_PARAMETERS);
888
889        assert_eq!(tx.get_constructor_parameters(), CONSTRUCTOR_PARAMETERS);
890    }
891
892    #[test]
893    #[should_panic]
894    fn get_set_constructor_parameters_frozen_panics() {
895        make_transaction().constructor_parameters(CONSTRUCTOR_PARAMETERS);
896    }
897
898    #[test]
899    fn get_set_auto_renew_account_id() {
900        let mut tx = ContractCreateTransaction::new();
901        tx.auto_renew_account_id(AUTO_RENEW_ACCOUNT_ID);
902
903        assert_eq!(tx.get_auto_renew_account_id(), Some(AUTO_RENEW_ACCOUNT_ID));
904    }
905
906    #[test]
907    #[should_panic]
908    fn get_set_auto_renew_account_id_frozen_panics() {
909        make_transaction().auto_renew_account_id(AUTO_RENEW_ACCOUNT_ID);
910    }
911
912    #[test]
913    fn get_set_staked_account_id() {
914        let mut tx = ContractCreateTransaction::new();
915        tx.staked_account_id(STAKED_ACCOUNT_ID);
916
917        assert_eq!(tx.get_staked_account_id(), Some(STAKED_ACCOUNT_ID));
918    }
919
920    #[test]
921    #[should_panic]
922    fn get_set_staked_account_id_frozen_panics() {
923        make_transaction().staked_account_id(STAKED_ACCOUNT_ID);
924    }
925
926    #[test]
927    fn get_set_staked_node_id() {
928        let mut tx = ContractCreateTransaction::new();
929        tx.staked_node_id(STAKED_NODE_ID);
930
931        assert_eq!(tx.get_staked_node_id(), Some(STAKED_NODE_ID));
932    }
933
934    #[test]
935    #[should_panic]
936    fn get_set_staked_node_id_frozen_panics() {
937        make_transaction().staked_node_id(STAKED_NODE_ID);
938    }
939}