github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/contract_create_transaction.go (about) 1 package hedera 2 3 /*- 4 * 5 * Hedera Go SDK 6 * 7 * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 */ 22 23 import ( 24 "time" 25 26 "github.com/hashgraph/hedera-protobufs-go/services" 27 ) 28 29 // ContractCreateTransaction which is used to start a new smart contract instance. 30 // After the instance is created, the ContractID for it is in the receipt, and can be retrieved by the Record or with a GetByKey query. 31 // The instance will run the bytecode, either stored in a previously created file or in the transaction body itself for 32 // small contracts. 33 type ContractCreateTransaction struct { 34 Transaction 35 byteCodeFileID *FileID 36 proxyAccountID *AccountID 37 adminKey Key 38 gas int64 39 initialBalance int64 40 autoRenewPeriod *time.Duration 41 parameters []byte 42 memo string 43 initcode []byte 44 autoRenewAccountID *AccountID 45 maxAutomaticTokenAssociations int32 46 stakedAccountID *AccountID 47 stakedNodeID *int64 48 declineReward bool 49 } 50 51 // NewContractCreateTransaction creates ContractCreateTransaction which is used to start a new smart contract instance. 52 // After the instance is created, the ContractID for it is in the receipt, and can be retrieved by the Record or with a GetByKey query. 53 // The instance will run the bytecode, either stored in a previously created file or in the transaction body itself for 54 // small contracts. 55 func NewContractCreateTransaction() *ContractCreateTransaction { 56 tx := ContractCreateTransaction{ 57 Transaction: _NewTransaction(), 58 } 59 60 tx.SetAutoRenewPeriod(131500 * time.Minute) 61 tx._SetDefaultMaxTransactionFee(NewHbar(20)) 62 63 return &tx 64 } 65 66 func _ContractCreateTransactionFromProtobuf(tx Transaction, pb *services.TransactionBody) *ContractCreateTransaction { 67 key, _ := _KeyFromProtobuf(pb.GetContractCreateInstance().GetAdminKey()) 68 autoRenew := _DurationFromProtobuf(pb.GetContractCreateInstance().GetAutoRenewPeriod()) 69 stakedNodeID := pb.GetContractCreateInstance().GetStakedNodeId() 70 71 var stakeNodeAccountID *AccountID 72 if pb.GetContractCreateInstance().GetStakedAccountId() != nil { 73 stakeNodeAccountID = _AccountIDFromProtobuf(pb.GetContractCreateInstance().GetStakedAccountId()) 74 } 75 76 var autoRenewAccountID *AccountID 77 if pb.GetContractCreateInstance().AutoRenewAccountId != nil { 78 autoRenewAccountID = _AccountIDFromProtobuf(pb.GetContractCreateInstance().GetAutoRenewAccountId()) 79 } 80 81 return &ContractCreateTransaction{ 82 Transaction: tx, 83 byteCodeFileID: _FileIDFromProtobuf(pb.GetContractCreateInstance().GetFileID()), 84 adminKey: key, 85 gas: pb.GetContractCreateInstance().Gas, 86 initialBalance: pb.GetContractCreateInstance().InitialBalance, 87 autoRenewPeriod: &autoRenew, 88 parameters: pb.GetContractCreateInstance().ConstructorParameters, 89 memo: pb.GetContractCreateInstance().GetMemo(), 90 initcode: pb.GetContractCreateInstance().GetInitcode(), 91 autoRenewAccountID: autoRenewAccountID, 92 maxAutomaticTokenAssociations: pb.GetContractCreateInstance().MaxAutomaticTokenAssociations, 93 stakedAccountID: stakeNodeAccountID, 94 stakedNodeID: &stakedNodeID, 95 declineReward: pb.GetContractCreateInstance().GetDeclineReward(), 96 } 97 } 98 99 // SetBytecodeFileID 100 // If the initcode is large (> 5K) then it must be stored in a file as hex encoded ascii. 101 func (tx *ContractCreateTransaction) SetBytecodeFileID(byteCodeFileID FileID) *ContractCreateTransaction { 102 tx._RequireNotFrozen() 103 tx.byteCodeFileID = &byteCodeFileID 104 tx.initcode = nil 105 return tx 106 } 107 108 // GetBytecodeFileID returns the FileID of the file containing the contract's bytecode. 109 func (tx *ContractCreateTransaction) GetBytecodeFileID() FileID { 110 if tx.byteCodeFileID == nil { 111 return FileID{} 112 } 113 114 return *tx.byteCodeFileID 115 } 116 117 // SetBytecode 118 // If it is small then it may either be stored as a hex encoded file or as a binary encoded field as part of the transaction. 119 func (tx *ContractCreateTransaction) SetBytecode(code []byte) *ContractCreateTransaction { 120 tx._RequireNotFrozen() 121 tx.initcode = code 122 tx.byteCodeFileID = nil 123 return tx 124 } 125 126 // GetBytecode returns the bytecode for the contract. 127 func (tx *ContractCreateTransaction) GetBytecode() []byte { 128 return tx.initcode 129 } 130 131 /** 132 * Sets the state of the instance and its fields can be modified arbitrarily if this key signs a transaction 133 * to modify it. If this is null, then such modifications are not possible, and there is no administrator 134 * that can override the normal operation of this smart contract instance. Note that if it is created with no 135 * admin keys, then there is no administrator to authorize changing the admin keys, so 136 * there can never be any admin keys for that instance. 137 */ 138 func (tx *ContractCreateTransaction) SetAdminKey(adminKey Key) *ContractCreateTransaction { 139 tx._RequireNotFrozen() 140 tx.adminKey = adminKey 141 return tx 142 } 143 144 // GetAdminKey returns the key that can sign to modify the state of the instance 145 // and its fields can be modified arbitrarily if this key signs a transaction 146 func (tx *ContractCreateTransaction) GetAdminKey() (Key, error) { 147 return tx.adminKey, nil 148 } 149 150 // Sets the gas to run the constructor. 151 func (tx *ContractCreateTransaction) SetGas(gas uint64) *ContractCreateTransaction { 152 tx._RequireNotFrozen() 153 tx.gas = int64(gas) 154 return tx 155 } 156 157 // GetGas returns the gas to run the constructor. 158 func (tx *ContractCreateTransaction) GetGas() uint64 { 159 return uint64(tx.gas) 160 } 161 162 // SetInitialBalance sets the initial number of Hbar to put into the account 163 func (tx *ContractCreateTransaction) SetInitialBalance(initialBalance Hbar) *ContractCreateTransaction { 164 tx._RequireNotFrozen() 165 tx.initialBalance = initialBalance.AsTinybar() 166 return tx 167 } 168 169 // GetInitialBalance gets the initial number of Hbar in the account 170 func (tx *ContractCreateTransaction) GetInitialBalance() Hbar { 171 return HbarFromTinybar(tx.initialBalance) 172 } 173 174 // SetAutoRenewPeriod sets the time duration for when account is charged to extend its expiration date. When the account 175 // is created, the payer account is charged enough hbars so that the new account will not expire for the next 176 // auto renew period. When it reaches the expiration time, the new account will then be automatically charged to 177 // renew for another auto renew period. If it does not have enough hbars to renew for that long, then the remaining 178 // hbars are used to extend its expiration as long as possible. If it is has a zero balance when it expires, 179 // then it is deleted. 180 func (tx *ContractCreateTransaction) SetAutoRenewPeriod(autoRenewPeriod time.Duration) *ContractCreateTransaction { 181 tx._RequireNotFrozen() 182 tx.autoRenewPeriod = &autoRenewPeriod 183 return tx 184 } 185 186 func (tx *ContractCreateTransaction) GetAutoRenewPeriod() time.Duration { 187 if tx.autoRenewPeriod != nil { 188 return *tx.autoRenewPeriod 189 } 190 191 return time.Duration(0) 192 } 193 194 // Deprecated 195 // SetProxyAccountID sets the ID of the account to which this account is proxy staked. If proxyAccountID is not set, 196 // is an invalID account, or is an account that isn't a _Node, then this account is automatically proxy staked to a _Node 197 // chosen by the _Network, but without earning payments. If the proxyAccountID account refuses to accept proxy staking , 198 // or if it is not currently running a _Node, then it will behave as if proxyAccountID was not set. 199 func (tx *ContractCreateTransaction) SetProxyAccountID(proxyAccountID AccountID) *ContractCreateTransaction { 200 tx._RequireNotFrozen() 201 tx.proxyAccountID = &proxyAccountID 202 return tx 203 } 204 205 // Deprecated 206 func (tx *ContractCreateTransaction) GetProxyAccountID() AccountID { 207 if tx.proxyAccountID == nil { 208 return AccountID{} 209 } 210 211 return *tx.proxyAccountID 212 } 213 214 // SetConstructorParameters Sets the constructor parameters 215 func (tx *ContractCreateTransaction) SetConstructorParameters(params *ContractFunctionParameters) *ContractCreateTransaction { 216 tx._RequireNotFrozen() 217 tx.parameters = params._Build(nil) 218 return tx 219 } 220 221 // SetConstructorParametersRaw Sets the constructor parameters as their raw bytes. 222 func (tx *ContractCreateTransaction) SetConstructorParametersRaw(params []byte) *ContractCreateTransaction { 223 tx._RequireNotFrozen() 224 tx.parameters = params 225 return tx 226 } 227 228 // GetConstructorParameters returns the constructor parameters 229 func (tx *ContractCreateTransaction) GetConstructorParameters() []byte { 230 return tx.parameters 231 } 232 233 // SetContractMemo Sets the memo to be associated with this contract. 234 func (tx *ContractCreateTransaction) SetContractMemo(memo string) *ContractCreateTransaction { 235 tx._RequireNotFrozen() 236 tx.memo = memo 237 return tx 238 } 239 240 // GetContractMemo returns the memo associated with this contract. 241 func (tx *ContractCreateTransaction) GetContractMemo() string { 242 return tx.memo 243 } 244 245 // SetAutoRenewAccountID 246 // An account to charge for auto-renewal of this contract. If not set, or set to an 247 // account with zero hbar balance, the contract's own hbar balance will be used to 248 // cover auto-renewal fees. 249 func (tx *ContractCreateTransaction) SetAutoRenewAccountID(id AccountID) *ContractCreateTransaction { 250 tx._RequireNotFrozen() 251 tx.autoRenewAccountID = &id 252 return tx 253 } 254 255 // GetAutoRenewAccountID returns the account to be used at the end of the auto renewal period 256 func (tx *ContractCreateTransaction) GetAutoRenewAccountID() AccountID { 257 if tx.autoRenewAccountID == nil { 258 return AccountID{} 259 } 260 261 return *tx.autoRenewAccountID 262 } 263 264 // SetMaxAutomaticTokenAssociations 265 // The maximum number of tokens that this contract can be automatically associated 266 // with (i.e., receive air-drops from). 267 func (tx *ContractCreateTransaction) SetMaxAutomaticTokenAssociations(max int32) *ContractCreateTransaction { 268 tx._RequireNotFrozen() 269 tx.maxAutomaticTokenAssociations = max 270 return tx 271 } 272 273 // GetMaxAutomaticTokenAssociations returns the maximum number of tokens that this contract can be automatically associated 274 func (tx *ContractCreateTransaction) GetMaxAutomaticTokenAssociations() int32 { 275 return tx.maxAutomaticTokenAssociations 276 } 277 278 // SetStakedAccountID sets the account ID of the account to which this contract is staked. 279 func (tx *ContractCreateTransaction) SetStakedAccountID(id AccountID) *ContractCreateTransaction { 280 tx._RequireNotFrozen() 281 tx.stakedAccountID = &id 282 return tx 283 } 284 285 // GetStakedAccountID returns the account ID of the account to which this contract is staked. 286 func (tx *ContractCreateTransaction) GetStakedAccountID() AccountID { 287 if tx.stakedAccountID != nil { 288 return *tx.stakedAccountID 289 } 290 291 return AccountID{} 292 } 293 294 // SetStakedNodeID sets the node ID of the node to which this contract is staked. 295 func (tx *ContractCreateTransaction) SetStakedNodeID(id int64) *ContractCreateTransaction { 296 tx._RequireNotFrozen() 297 tx.stakedNodeID = &id 298 return tx 299 } 300 301 // GetStakedNodeID returns the node ID of the node to which this contract is staked. 302 func (tx *ContractCreateTransaction) GetStakedNodeID() int64 { 303 if tx.stakedNodeID != nil { 304 return *tx.stakedNodeID 305 } 306 307 return 0 308 } 309 310 // SetDeclineStakingReward sets if the contract should decline to pay the account's staking revenue. 311 func (tx *ContractCreateTransaction) SetDeclineStakingReward(decline bool) *ContractCreateTransaction { 312 tx._RequireNotFrozen() 313 tx.declineReward = decline 314 return tx 315 } 316 317 // GetDeclineStakingReward returns if the contract should decline to pay the account's staking revenue. 318 func (tx *ContractCreateTransaction) GetDeclineStakingReward() bool { 319 return tx.declineReward 320 } 321 322 // ---- Required Interfaces ---- // 323 324 // Sign uses the provided privateKey to sign the transaction. 325 func (tx *ContractCreateTransaction) Sign( 326 privateKey PrivateKey, 327 ) *ContractCreateTransaction { 328 tx.Transaction.Sign(privateKey) 329 return tx 330 } 331 332 // SignWithOperator signs the transaction with client's operator privateKey. 333 func (tx *ContractCreateTransaction) SignWithOperator( 334 client *Client, 335 ) (*ContractCreateTransaction, error) { 336 // If the transaction is not signed by the _Operator, we need 337 // to sign the transaction with the _Operator 338 _, err := tx.Transaction.signWithOperator(client, tx) 339 if err != nil { 340 return nil, err 341 } 342 return tx, nil 343 } 344 345 // SignWith executes the TransactionSigner and adds the resulting signature data to the Transaction's signature map 346 // with the publicKey as the map key. 347 func (tx *ContractCreateTransaction) SignWith( 348 publicKey PublicKey, 349 signer TransactionSigner, 350 ) *ContractCreateTransaction { 351 tx.Transaction.SignWith(publicKey, signer) 352 return tx 353 } 354 355 // AddSignature adds a signature to the transaction. 356 func (tx *ContractCreateTransaction) AddSignature(publicKey PublicKey, signature []byte) *ContractCreateTransaction { 357 tx.Transaction.AddSignature(publicKey, signature) 358 return tx 359 } 360 361 // When execution is attempted, a single attempt will timeout when tx deadline is reached. (The SDK may subsequently retry the execution.) 362 func (tx *ContractCreateTransaction) SetGrpcDeadline(deadline *time.Duration) *ContractCreateTransaction { 363 tx.Transaction.SetGrpcDeadline(deadline) 364 return tx 365 } 366 367 func (tx *ContractCreateTransaction) Freeze() (*ContractCreateTransaction, error) { 368 return tx.FreezeWith(nil) 369 } 370 371 func (tx *ContractCreateTransaction) FreezeWith(client *Client) (*ContractCreateTransaction, error) { 372 _, err := tx.Transaction.freezeWith(client, tx) 373 return tx, err 374 } 375 376 // SetMaxTransactionFee sets the maximum transaction fee the operator (paying account) is willing to pay. 377 func (tx *ContractCreateTransaction) SetMaxTransactionFee(fee Hbar) *ContractCreateTransaction { 378 tx._RequireNotFrozen() 379 tx.Transaction.SetMaxTransactionFee(fee) 380 return tx 381 } 382 383 // SetRegenerateTransactionID sets if transaction IDs should be regenerated when `TRANSACTION_EXPIRED` is received 384 func (tx *ContractCreateTransaction) SetRegenerateTransactionID(regenerateTransactionID bool) *ContractCreateTransaction { 385 tx._RequireNotFrozen() 386 tx.Transaction.SetRegenerateTransactionID(regenerateTransactionID) 387 return tx 388 } 389 390 // SetTransactionMemo sets the memo for this ContractCreateTransaction. 391 func (tx *ContractCreateTransaction) SetTransactionMemo(memo string) *ContractCreateTransaction { 392 tx._RequireNotFrozen() 393 tx.Transaction.SetTransactionMemo(memo) 394 return tx 395 } 396 397 // SetTransactionValidDuration sets the valid duration for this ContractCreateTransaction. 398 func (tx *ContractCreateTransaction) SetTransactionValidDuration(duration time.Duration) *ContractCreateTransaction { 399 tx._RequireNotFrozen() 400 tx.Transaction.SetTransactionValidDuration(duration) 401 return tx 402 } 403 404 // ToBytes serialise the tx to bytes, no matter if it is signed (locked), or not 405 func (tx *ContractCreateTransaction) ToBytes() ([]byte, error) { 406 bytes, err := tx.Transaction.toBytes(tx) 407 if err != nil { 408 return nil, err 409 } 410 return bytes, nil 411 } 412 413 // SetTransactionID sets the TransactionID for this ContractCreateTransaction. 414 func (tx *ContractCreateTransaction) SetTransactionID(transactionID TransactionID) *ContractCreateTransaction { 415 tx._RequireNotFrozen() 416 417 tx.Transaction.SetTransactionID(transactionID) 418 return tx 419 } 420 421 // SetNodeAccountIDs sets the _Node AccountID for this ContractCreateTransaction. 422 func (tx *ContractCreateTransaction) SetNodeAccountIDs(nodeID []AccountID) *ContractCreateTransaction { 423 tx._RequireNotFrozen() 424 tx.Transaction.SetNodeAccountIDs(nodeID) 425 return tx 426 } 427 428 // SetMaxRetry sets the max number of errors before execution will fail. 429 func (tx *ContractCreateTransaction) SetMaxRetry(count int) *ContractCreateTransaction { 430 tx.Transaction.SetMaxRetry(count) 431 return tx 432 } 433 434 // SetMaxBackoff The maximum amount of time to wait between retries. 435 // Every retry attempt will increase the wait time exponentially until it reaches this time. 436 func (tx *ContractCreateTransaction) SetMaxBackoff(max time.Duration) *ContractCreateTransaction { 437 tx.Transaction.SetMaxBackoff(max) 438 return tx 439 } 440 441 // SetMinBackoff sets the minimum amount of time to wait between retries. 442 func (tx *ContractCreateTransaction) SetMinBackoff(min time.Duration) *ContractCreateTransaction { 443 tx.Transaction.SetMinBackoff(min) 444 return tx 445 } 446 447 func (tx *ContractCreateTransaction) SetLogLevel(level LogLevel) *ContractCreateTransaction { 448 tx.Transaction.SetLogLevel(level) 449 return tx 450 } 451 452 func (tx *ContractCreateTransaction) Execute(client *Client) (TransactionResponse, error) { 453 return tx.Transaction.execute(client, tx) 454 } 455 456 func (tx *ContractCreateTransaction) Schedule() (*ScheduleCreateTransaction, error) { 457 return tx.Transaction.schedule(tx) 458 } 459 460 // ----------- Overridden functions ---------------- 461 462 func (tx *ContractCreateTransaction) getName() string { 463 return "ContractCreateTransaction" 464 } 465 466 func (tx *ContractCreateTransaction) validateNetworkOnIDs(client *Client) error { 467 if client == nil || !client.autoValidateChecksums { 468 return nil 469 } 470 471 if tx.byteCodeFileID != nil { 472 if err := tx.byteCodeFileID.ValidateChecksum(client); err != nil { 473 return err 474 } 475 } 476 477 if tx.proxyAccountID != nil { 478 if err := tx.proxyAccountID.ValidateChecksum(client); err != nil { 479 return err 480 } 481 } 482 483 return nil 484 } 485 486 func (tx *ContractCreateTransaction) build() *services.TransactionBody { 487 pb := services.TransactionBody{ 488 TransactionFee: tx.transactionFee, 489 Memo: tx.Transaction.memo, 490 TransactionValidDuration: _DurationToProtobuf(tx.GetTransactionValidDuration()), 491 TransactionID: tx.transactionID._ToProtobuf(), 492 Data: &services.TransactionBody_ContractCreateInstance{ 493 ContractCreateInstance: tx.buildProtoBody(), 494 }, 495 } 496 497 return &pb 498 } 499 func (tx *ContractCreateTransaction) buildScheduled() (*services.SchedulableTransactionBody, error) { 500 return &services.SchedulableTransactionBody{ 501 TransactionFee: tx.transactionFee, 502 Memo: tx.Transaction.memo, 503 Data: &services.SchedulableTransactionBody_ContractCreateInstance{ 504 ContractCreateInstance: tx.buildProtoBody(), 505 }, 506 }, nil 507 } 508 509 func (tx *ContractCreateTransaction) buildProtoBody() *services.ContractCreateTransactionBody { 510 body := &services.ContractCreateTransactionBody{ 511 Gas: tx.gas, 512 InitialBalance: tx.initialBalance, 513 ConstructorParameters: tx.parameters, 514 Memo: tx.memo, 515 MaxAutomaticTokenAssociations: tx.maxAutomaticTokenAssociations, 516 DeclineReward: tx.declineReward, 517 } 518 519 if tx.autoRenewPeriod != nil { 520 body.AutoRenewPeriod = _DurationToProtobuf(*tx.autoRenewPeriod) 521 } 522 523 if tx.adminKey != nil { 524 body.AdminKey = tx.adminKey._ToProtoKey() 525 } 526 527 if tx.byteCodeFileID != nil { 528 body.InitcodeSource = &services.ContractCreateTransactionBody_FileID{FileID: tx.byteCodeFileID._ToProtobuf()} 529 } else if len(tx.initcode) != 0 { 530 body.InitcodeSource = &services.ContractCreateTransactionBody_Initcode{Initcode: tx.initcode} 531 } 532 533 if tx.autoRenewAccountID != nil { 534 body.AutoRenewAccountId = tx.autoRenewAccountID._ToProtobuf() 535 } 536 537 if tx.stakedAccountID != nil { 538 body.StakedId = &services.ContractCreateTransactionBody_StakedAccountId{StakedAccountId: tx.stakedAccountID._ToProtobuf()} 539 } else if tx.stakedNodeID != nil { 540 body.StakedId = &services.ContractCreateTransactionBody_StakedNodeId{StakedNodeId: *tx.stakedNodeID} 541 } 542 543 return body 544 } 545 546 func (tx *ContractCreateTransaction) getMethod(channel *_Channel) _Method { 547 return _Method{ 548 transaction: channel._GetContract().CreateContract, 549 } 550 } 551 552 func (tx *ContractCreateTransaction) _ConstructScheduleProtobuf() (*services.SchedulableTransactionBody, error) { 553 return tx.buildScheduled() 554 }