github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/contract_function_result.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 "encoding/binary" 25 "fmt" 26 "math/big" 27 "strings" 28 29 "github.com/ethereum/go-ethereum/accounts/abi" 30 "github.com/ethereum/go-ethereum/common/math" 31 "github.com/hashgraph/hedera-protobufs-go/services" 32 protobuf "google.golang.org/protobuf/proto" 33 "google.golang.org/protobuf/types/known/wrapperspb" 34 ) 35 36 // ContractFunctionResult is a struct which allows users to convert between solidity and Go types, and is typically 37 // returned by `ContractCallQuery` and is present in the transaction records of `ContractExecuteTransaction`. 38 // Use the methods `Get<Type>()` to get a parameter. Not all solidity types 39 // are supported out of the box, but the most common types are. The larger variants 40 // of number types return just the bytes for the integer instead of converting to a big int type. 41 // To convert those bytes into a usable integer using "github.com/ethereum/go-ethereum/common/math" and "math/big" do the following: 42 // ``` 43 // contractFunctionResult.GetUint256(<index>) 44 // bInt := new(big.Int) 45 // bInt.SetBytes(query.GetUint256(0)) 46 // ``` 47 type ContractFunctionResult struct { 48 // ContractID is the smart contract instance whose function was called 49 ContractID *ContractID 50 // ContractCallResult is the result returned by the function 51 ContractCallResult []byte 52 // ErrorMessage is the message returned in the case there was an error during smart contract execution 53 ErrorMessage string 54 // Bloom is the bloom filter for record 55 Bloom []byte 56 // GasUsed is the amount of gas used to execute the contract function 57 GasUsed uint64 58 // LogInfo is the log info for events returned by the function 59 LogInfo []ContractLogInfo 60 // Deprecated 61 CreatedContractIDs []ContractID 62 // Deprecated 63 ContractStateChanges []ContractStateChange 64 EvmAddress ContractID 65 GasAvailable int64 66 Amount Hbar 67 FunctionParameters []byte 68 ContractNonces []*ContractNonceInfo 69 SignerNonce int64 70 } 71 72 // GetBool gets a _Solidity bool from the result at the given index 73 func (result ContractFunctionResult) GetBool(index uint64) bool { 74 return result.GetUint32(index) == 1 75 } 76 77 // GetAddress gets a _Solidity address from the result at the given index 78 func (result ContractFunctionResult) GetAddress(index uint64) []byte { 79 return result.ContractCallResult[(index*32)+12 : (index*32)+32] 80 } 81 82 // GetInt8 gets a _Solidity int8 from the result at the given index 83 func (result ContractFunctionResult) GetInt8(index uint64) int8 { 84 return int8(result.ContractCallResult[index*32+31]) 85 } 86 87 // GetInt16 gets a _Solidity int16 from the result at the given index 88 func (result ContractFunctionResult) GetInt16(index uint64) int16 { 89 return int16(binary.BigEndian.Uint16(result.ContractCallResult[index*32+30 : (index+1)*32])) 90 } 91 92 // GetInt24 gets a _Solidity int24 from the result at the given index 93 func (result ContractFunctionResult) GetInt24(index uint64) int32 { 94 return int32(binary.BigEndian.Uint32(result.ContractCallResult[index*32+28 : (index+1)*32])) 95 } 96 97 // GetInt40 gets a _Solidity int40 from the result at the given index 98 func (result ContractFunctionResult) GetInt40(index uint64) int64 { 99 return int64(binary.BigEndian.Uint64(result.ContractCallResult[index*32+24 : (index+1)*32])) 100 } 101 102 // GetInt48 gets a _Solidity int48 from the result at the given index 103 func (result ContractFunctionResult) GetInt48(index uint64) int64 { 104 return int64(binary.BigEndian.Uint64(result.ContractCallResult[index*32+24 : (index+1)*32])) 105 } 106 107 // GetInt56 gets a _Solidity int56 from the result at the given index 108 func (result ContractFunctionResult) GetInt56(index uint64) int64 { 109 return int64(binary.BigEndian.Uint64(result.ContractCallResult[index*32+24 : (index+1)*32])) 110 } 111 112 // GetInt32 gets a _Solidity int32 from the result at the given index 113 func (result ContractFunctionResult) GetInt32(index uint64) int32 { 114 return int32(binary.BigEndian.Uint32(result.ContractCallResult[index*32+28 : (index+1)*32])) 115 } 116 117 // GetInt64 gets a _Solidity int64 from the result at the given index 118 func (result ContractFunctionResult) GetInt64(index uint64) int64 { 119 return int64(binary.BigEndian.Uint64(result.ContractCallResult[index*32+24 : (index+1)*32])) 120 } 121 122 // GetInt72 gets a _Solidity int72 from the result at the given index 123 func (result ContractFunctionResult) GetInt72(index uint64) []byte { 124 return result.ContractCallResult[index*32 : index*32+32] 125 } 126 127 // GetInt80 gets a _Solidity int80 from the result at the given index 128 func (result ContractFunctionResult) GetInt80(index uint64) []byte { 129 return result.ContractCallResult[index*32 : index*32+32] 130 } 131 132 // GetInt88 gets a _Solidity int88 from the result at the given index 133 func (result ContractFunctionResult) GetInt88(index uint64) []byte { 134 return result.ContractCallResult[index*32 : index*32+32] 135 } 136 137 // GetInt96 gets a _Solidity int96 from the result at the given index 138 func (result ContractFunctionResult) GetInt96(index uint64) []byte { 139 return result.ContractCallResult[index*32 : index*32+32] 140 } 141 142 // GetInt104 gets a _Solidity int104 from the result at the given index 143 func (result ContractFunctionResult) GetInt104(index uint64) []byte { 144 return result.ContractCallResult[index*32 : index*32+32] 145 } 146 147 // GetInt112 gets a _Solidity int112 from the result at the given index 148 func (result ContractFunctionResult) GetInt112(index uint64) []byte { 149 return result.ContractCallResult[index*32 : index*32+32] 150 } 151 152 // GetInt120 gets a _Solidity int120 from the result at the given index 153 func (result ContractFunctionResult) GetInt120(index uint64) []byte { 154 return result.ContractCallResult[index*32 : index*32+32] 155 } 156 157 // GetInt128 gets a _Solidity int128 from the result at the given index 158 func (result ContractFunctionResult) GetInt128(index uint64) []byte { 159 return result.ContractCallResult[index*32 : index*32+32] 160 } 161 162 // GetInt136 gets a _Solidity int136 from the result at the given index 163 func (result ContractFunctionResult) GetInt136(index uint64) []byte { 164 return result.ContractCallResult[index*32 : index*32+32] 165 } 166 167 // GetInt144 gets a _Solidity int144 from the result at the given index 168 func (result ContractFunctionResult) GetInt144(index uint64) []byte { 169 return result.ContractCallResult[index*32 : index*32+32] 170 } 171 172 // GetInt152 gets a _Solidity int152 from the result at the given index 173 func (result ContractFunctionResult) GetInt152(index uint64) []byte { 174 return result.ContractCallResult[index*32 : index*32+32] 175 } 176 177 // GetInt160 gets a _Solidity int160 from the result at the given index 178 func (result ContractFunctionResult) GetInt160(index uint64) []byte { 179 return result.ContractCallResult[index*32 : index*32+32] 180 } 181 182 // GetInt168 gets a _Solidity int168 from the result at the given index 183 func (result ContractFunctionResult) GetInt168(index uint64) []byte { 184 return result.ContractCallResult[index*32 : index*32+32] 185 } 186 187 // GetInt176 gets a _Solidity int176 from the result at the given index 188 func (result ContractFunctionResult) GetInt176(index uint64) []byte { 189 return result.ContractCallResult[index*32 : index*32+32] 190 } 191 192 // GetInt184 gets a _Solidity int184 from the result at the given index 193 func (result ContractFunctionResult) GetInt184(index uint64) []byte { 194 return result.ContractCallResult[index*32 : index*32+32] 195 } 196 197 // GetInt192 gets a _Solidity int192 from the result at the given index 198 func (result ContractFunctionResult) GetInt192(index uint64) []byte { 199 return result.ContractCallResult[index*32 : index*32+32] 200 } 201 202 // GetInt200 gets a _Solidity int200 from the result at the given index 203 func (result ContractFunctionResult) GetInt200(index uint64) []byte { 204 return result.ContractCallResult[index*32 : index*32+32] 205 } 206 207 // GetInt208 gets a _Solidity int208 from the result at the given index 208 func (result ContractFunctionResult) GetInt208(index uint64) []byte { 209 return result.ContractCallResult[index*32 : index*32+32] 210 } 211 212 // GetInt216 gets a _Solidity int216 from the result at the given index 213 func (result ContractFunctionResult) GetInt216(index uint64) []byte { 214 return result.ContractCallResult[index*32 : index*32+32] 215 } 216 217 // GetInt224 gets a _Solidity int224 from the result at the given index 218 func (result ContractFunctionResult) GetInt224(index uint64) []byte { 219 return result.ContractCallResult[index*32 : index*32+32] 220 } 221 222 // GetInt232 gets a _Solidity int232 from the result at the given index 223 func (result ContractFunctionResult) GetInt232(index uint64) []byte { 224 return result.ContractCallResult[index*32 : index*32+32] 225 } 226 227 // GetInt240 gets a _Solidity int240 from the result at the given index 228 func (result ContractFunctionResult) GetInt240(index uint64) []byte { 229 return result.ContractCallResult[index*32 : index*32+32] 230 } 231 232 // GetInt248 gets a _Solidity int248 from the result at the given index 233 func (result ContractFunctionResult) GetInt248(index uint64) []byte { 234 return result.ContractCallResult[index*32 : index*32+32] 235 } 236 237 // GetInt256 gets a _Solidity int256 from the result at the given index 238 func (result ContractFunctionResult) GetInt256(index uint64) []byte { 239 return result.ContractCallResult[index*32 : index*32+32] 240 } 241 242 // GetBigInt gets an _Solidity integer from the result at the given index and returns it as a big.Int 243 func (result ContractFunctionResult) GetBigInt(index uint64) *big.Int { 244 value := new(big.Int).SetBytes(result.ContractCallResult[index*32 : index*32+32]) 245 fromTwosComplement := math.S256(value) 246 return fromTwosComplement 247 } 248 249 // GetUint8 gets a _Solidity uint8 from the result at the given index 250 func (result ContractFunctionResult) GetUint8(index uint64) uint8 { 251 return result.ContractCallResult[index*32+31] 252 } 253 254 // GetUint16 gets a _Solidity uint16 from the result at the given index 255 func (result ContractFunctionResult) GetUint16(index uint64) uint16 { 256 return binary.BigEndian.Uint16(result.ContractCallResult[index*32+30 : (index+1)*32]) 257 } 258 259 // GetUint24 gets a _Solidity uint24 from the result at the given index 260 func (result ContractFunctionResult) GetUint24(index uint64) uint32 { 261 return binary.BigEndian.Uint32(result.ContractCallResult[index*32+28 : (index+1)*32]) 262 } 263 264 // GetUint32 gets a _Solidity uint32 from the result at the given index 265 func (result ContractFunctionResult) GetUint32(index uint64) uint32 { 266 return binary.BigEndian.Uint32(result.ContractCallResult[index*32+28 : (index+1)*32]) 267 } 268 269 // GetUint40 gets a _Solidity uint40 from the result at the given index 270 func (result ContractFunctionResult) GetUint40(index uint64) uint64 { 271 return binary.BigEndian.Uint64(result.ContractCallResult[index*32+24 : (index+1)*32]) 272 } 273 274 // GetUint48 gets a _Solidity uint48 from the result at the given index 275 func (result ContractFunctionResult) GetUint48(index uint64) uint64 { 276 return binary.BigEndian.Uint64(result.ContractCallResult[index*32+24 : (index+1)*32]) 277 } 278 279 // GetUint56 gets a _Solidity uint56 from the result at the given index 280 func (result ContractFunctionResult) GetUint56(index uint64) uint64 { 281 return binary.BigEndian.Uint64(result.ContractCallResult[index*32+24 : (index+1)*32]) 282 } 283 284 // GetUint64 gets a _Solidity uint64 from the result at the given index 285 func (result ContractFunctionResult) GetUint64(index uint64) uint64 { 286 return binary.BigEndian.Uint64(result.ContractCallResult[index*32+24 : (index+1)*32]) 287 } 288 289 // GetUint72 gets a _Solidity uint72 from the result at the given index 290 func (result ContractFunctionResult) GetUint72(index uint64) []byte { 291 return result.ContractCallResult[index*32+23 : (index+1)*32] 292 } 293 294 // GetUint80 gets a _Solidity uint80 from the result at the given index 295 func (result ContractFunctionResult) GetUint80(index uint64) []byte { 296 return result.ContractCallResult[index*32+22 : (index+1)*32] 297 } 298 299 // GetUint88 gets a _Solidity uint88 from the result at the given index 300 func (result ContractFunctionResult) GetUint88(index uint64) []byte { 301 return result.ContractCallResult[index*32+21 : (index+1)*32] 302 } 303 304 // GetUint96 gets a _Solidity uint96 from the result at the given index 305 func (result ContractFunctionResult) GetUint96(index uint64) []byte { 306 return result.ContractCallResult[index*32+20 : (index+1)*32] 307 } 308 309 // GetUint104 gets a _Solidity uint104 from the result at the given index 310 func (result ContractFunctionResult) GetUint104(index uint64) []byte { 311 return result.ContractCallResult[index*32+19 : (index+1)*32] 312 } 313 314 // GetUint112 gets a _Solidity uint112 from the result at the given index 315 func (result ContractFunctionResult) GetUint112(index uint64) []byte { 316 return result.ContractCallResult[index*32+18 : (index+1)*32] 317 } 318 319 // GetUint120 gets a _Solidity uint120 from the result at the given index 320 func (result ContractFunctionResult) GetUint120(index uint64) []byte { 321 return result.ContractCallResult[index*32+17 : (index+1)*32] 322 } 323 324 // GetUint128 gets a _Solidity uint128 from the result at the given index 325 func (result ContractFunctionResult) GetUint128(index uint64) []byte { 326 return result.ContractCallResult[index*32+16 : (index+1)*32] 327 } 328 329 // GetUint136 gets a _Solidity uint136 from the result at the given index 330 func (result ContractFunctionResult) GetUint136(index uint64) []byte { 331 return result.ContractCallResult[index*32+15 : (index+1)*32] 332 } 333 334 // GetUint144 gets a _Solidity uint144 from the result at the given index 335 func (result ContractFunctionResult) GetUint144(index uint64) []byte { 336 return result.ContractCallResult[index*32+14 : (index+1)*32] 337 } 338 339 // GetUint152 gets a _Solidity uint152 from the result at the given index 340 func (result ContractFunctionResult) GetUint152(index uint64) []byte { 341 return result.ContractCallResult[index*32+13 : (index+1)*32] 342 } 343 344 // GetUint160 gets a _Solidity uint160 from the result at the given index 345 func (result ContractFunctionResult) GetUint160(index uint64) []byte { 346 return result.ContractCallResult[index*32+12 : (index+1)*32] 347 } 348 349 // GetUint168 gets a _Solidity uint168 from the result at the given index 350 func (result ContractFunctionResult) GetUint168(index uint64) []byte { 351 return result.ContractCallResult[index*32+11 : (index+1)*32] 352 } 353 354 // GetUint176 gets a _Solidity uint176 from the result at the given index 355 func (result ContractFunctionResult) GetUint176(index uint64) []byte { 356 return result.ContractCallResult[index*32+10 : (index+1)*32] 357 } 358 359 // GetUint184 gets a _Solidity uint184 from the result at the given index 360 func (result ContractFunctionResult) GetUint184(index uint64) []byte { 361 return result.ContractCallResult[index*32+9 : (index+1)*32] 362 } 363 364 // GetUint192 gets a _Solidity uint192 from the result at the given index 365 func (result ContractFunctionResult) GetUint192(index uint64) []byte { 366 return result.ContractCallResult[index*32+8 : (index+1)*32] 367 } 368 369 // GetUint200 gets a _Solidity uint200 from the result at the given index 370 func (result ContractFunctionResult) GetUint200(index uint64) []byte { 371 return result.ContractCallResult[index*32+7 : (index+1)*32] 372 } 373 374 // GetUint208 gets a _Solidity uint208 from the result at the given index 375 func (result ContractFunctionResult) GetUint208(index uint64) []byte { 376 return result.ContractCallResult[index*32+6 : (index+1)*32] 377 } 378 379 // GetUint216 gets a _Solidity uint216 from the result at the given index 380 func (result ContractFunctionResult) GetUint216(index uint64) []byte { 381 return result.ContractCallResult[index*32+5 : (index+1)*32] 382 } 383 384 // GetUint224 gets a _Solidity uint224 from the result at the given index 385 func (result ContractFunctionResult) GetUint224(index uint64) []byte { 386 return result.ContractCallResult[index*32+4 : (index+1)*32] 387 } 388 389 // GetUint232 gets a _Solidity uint232 from the result at the given index 390 func (result ContractFunctionResult) GetUint232(index uint64) []byte { 391 return result.ContractCallResult[index*32+3 : (index+1)*32] 392 } 393 394 // GetUint240 gets a _Solidity uint240 from the result at the given index 395 func (result ContractFunctionResult) GetUint240(index uint64) []byte { 396 return result.ContractCallResult[index*32+2 : (index+1)*32] 397 } 398 399 // GetUint248 gets a _Solidity uint248 from the result at the given index 400 func (result ContractFunctionResult) GetUint248(index uint64) []byte { 401 return result.ContractCallResult[index*32+1 : (index+1)*32] 402 } 403 404 // GetUint256 gets a _Solidity uint256 from the result at the given index 405 func (result ContractFunctionResult) GetUint256(index uint64) []byte { 406 return result.ContractCallResult[index*32 : index*32+32] 407 } 408 409 // GetBytes32 gets a _Solidity bytes32 from the result at the given index 410 func (result ContractFunctionResult) GetBytes32(index uint64) []byte { 411 return result.ContractCallResult[index*32 : index*32+32] 412 } 413 414 // GetString gets a string from the result at the given index 415 func (result ContractFunctionResult) GetString(index uint64) string { 416 return string(result.GetBytes(index)) 417 } 418 419 // GetBytes gets a byte array from the result at the given index 420 func (result ContractFunctionResult) GetBytes(index uint64) []byte { 421 offset := result.GetUint64(index) 422 length := binary.BigEndian.Uint64(result.ContractCallResult[offset+24 : offset+32]) 423 return result.ContractCallResult[offset+32 : offset+32+length] 424 } 425 426 // AsBytes returns the raw bytes of the ContractCallResult 427 func (result ContractFunctionResult) AsBytes() []byte { 428 return result.ContractCallResult 429 } 430 431 // GetResult parses the result of a contract call based on the given types string and returns the result as an interface. 432 // The "types" string should specify the Ethereum Solidity type of the contract call output. 433 // This includes types like "uint256", "address", "bool", "string", "string[]", etc. 434 // The type provided must match the actual type of the data returned by the contract call, 435 // otherwise the function will fail to unpack and return an error. 436 // The method returns the parsed result encapsulated in an interface{}, 437 // allowing flexibility to handle various types of contract call results. 438 // For correct usage, the caller should perform a type assertion on the returned interface{} 439 // to convert it into the appropriate go type. 440 func (result ContractFunctionResult) GetResult(types string) (interface{}, error) { 441 def := fmt.Sprintf(`[{ "name" : "method", "type": "function", "outputs": [{ "type": "%s" }]}]`, types) 442 abi, err := abi.JSON(strings.NewReader(def)) 443 if err != nil { 444 return nil, err 445 } 446 parsedResult, err := abi.Unpack("method", result.ContractCallResult) 447 if err != nil { 448 return nil, err 449 } 450 return parsedResult, nil 451 } 452 453 func extractInt64OrZero(pb *services.ContractFunctionResult) int64 { 454 if pb.GetSignerNonce() != nil { 455 return pb.SignerNonce.Value 456 } 457 return 0 458 } 459 460 func _ContractFunctionResultFromProtobuf(pb *services.ContractFunctionResult) ContractFunctionResult { 461 infos := make([]ContractLogInfo, len(pb.LogInfo)) 462 463 for i, info := range pb.LogInfo { 464 infos[i] = _ContractLogInfoFromProtobuf(info) 465 } 466 467 createdContractIDs := make([]ContractID, 0) 468 for _, id := range pb.CreatedContractIDs { // nolint 469 temp := _ContractIDFromProtobuf(id) 470 if temp != nil { 471 createdContractIDs = append(createdContractIDs, *temp) 472 } 473 } 474 475 var evm ContractID 476 if len(pb.EvmAddress.GetValue()) > 0 { 477 evm = ContractID{ 478 Shard: 0, 479 Realm: 0, 480 Contract: 0, 481 EvmAddress: pb.EvmAddress.GetValue(), 482 checksum: nil, 483 } 484 } 485 486 var nonces []*ContractNonceInfo 487 if len(pb.ContractNonces) > 0 { 488 nonces = make([]*ContractNonceInfo, len(pb.ContractNonces)) 489 for i, nonce := range pb.ContractNonces { 490 nonces[i] = _ContractNonceInfoFromProtobuf(nonce) 491 } 492 } 493 494 result := ContractFunctionResult{ 495 ContractCallResult: pb.ContractCallResult, 496 ErrorMessage: pb.ErrorMessage, 497 Bloom: pb.Bloom, 498 GasUsed: pb.GasUsed, 499 LogInfo: infos, 500 CreatedContractIDs: createdContractIDs, 501 EvmAddress: evm, 502 GasAvailable: pb.Gas, 503 Amount: HbarFromTinybar(pb.Amount), 504 FunctionParameters: pb.FunctionParameters, 505 ContractNonces: nonces, 506 SignerNonce: extractInt64OrZero(pb), 507 } 508 509 if pb.ContractID != nil { 510 result.ContractID = _ContractIDFromProtobuf(pb.ContractID) 511 } 512 513 return result 514 } 515 516 func (result ContractFunctionResult) _ToProtobuf() *services.ContractFunctionResult { 517 infos := make([]*services.ContractLoginfo, len(result.LogInfo)) 518 519 for i, info := range result.LogInfo { 520 infos[i] = info._ToProtobuf() 521 } 522 523 return &services.ContractFunctionResult{ 524 ContractID: result.ContractID._ToProtobuf(), 525 ContractCallResult: result.ContractCallResult, 526 ErrorMessage: result.ErrorMessage, 527 Bloom: result.Bloom, 528 GasUsed: result.GasUsed, 529 LogInfo: infos, 530 EvmAddress: &wrapperspb.BytesValue{Value: result.EvmAddress.EvmAddress}, 531 Gas: result.GasAvailable, 532 Amount: result.Amount.AsTinybar(), 533 FunctionParameters: result.FunctionParameters, 534 SignerNonce: wrapperspb.Int64(result.SignerNonce), 535 } 536 } 537 538 // ToBytes returns the protobuf encoded bytes of the ContractFunctionResult 539 func (result *ContractFunctionResult) ToBytes() []byte { 540 data, err := protobuf.Marshal(result._ToProtobuf()) 541 if err != nil { 542 return make([]byte, 0) 543 } 544 545 return data 546 } 547 548 // ContractFunctionResultFromBytes returns a ContractFunctionResult from the protobuf encoded bytes of a ContractFunctionResult 549 func ContractFunctionResultFromBytes(data []byte) (ContractFunctionResult, error) { 550 if data == nil { 551 return ContractFunctionResult{}, errByteArrayNull 552 } 553 pb := services.ContractFunctionResult{} 554 err := protobuf.Unmarshal(data, &pb) 555 if err != nil { 556 return ContractFunctionResult{}, err 557 } 558 559 return _ContractFunctionResultFromProtobuf(&pb), nil 560 }