Deployment and Invocation

Smart Contract Deployment

Deploying a smart contract is to create a CreateSmartContract type transaction, which can be created through the fullnode api wallet/deploycontract, and after the creation, then to sign and broadcast the transaction:

curl --request POST \
     --url https://api.shasta.trongrid.io/wallet/deploycontract \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '
{
     "owner_address": "41D1E7A6BC354106CB410E65FF8B181C600FF14292",
     "abi": "[{\"constant\":false,\"inputs\":[{\"name\":\"key\",\"type\":\"uint256\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"key\",\"type\":\"uint256\"}],\"name\":\"get\",\"outputs\":[{\"name\":\"value\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]",
     "bytecode": "608060405234801561001057600080fd5b5060de8061001f6000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631ab06ee58114604d5780639507d39a146067575b600080fd5b348015605857600080fd5b506065600435602435608e565b005b348015607257600080fd5b50607c60043560a0565b60408051918252519081900360200190f35b60009182526020829052604090912055565b600090815260208190526040902054905600a165627a7a72305820fdfe832221d60dd582b4526afa20518b98c2e1cb0054653053a844cf265b25040029",
     "fee_limit": 1000000,
     "origin_energy_limit": 100000,
     "name": "SomeContract",
     "call_value": 0,
     "consume_user_resource_percent": 100
}
'

The return result:

{
  "visible": false,
  "txID": "e4eb4df3a64a33565059ee3cef29b93b79f58ece9e7e8153fda3bbfe40fb0524",
  "contract_address": "416c5d359d1836085cdad65788e1ce53d3d7a13dd6",
  "raw_data": {
    "contract": [
      {
        "parameter": {
          "value": {
            "owner_address": "41d1e7a6bc354106cb410e65ff8b181c600ff14292",
            "new_contract": {
              "bytecode": "608060405234801561001057600080fd5b5060de8061001f6000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631ab06ee58114604d5780639507d39a146067575b600080fd5b348015605857600080fd5b506065600435602435608e565b005b348015607257600080fd5b50607c60043560a0565b60408051918252519081900360200190f35b60009182526020829052604090912055565b600090815260208190526040902054905600a165627a7a72305820fdfe832221d60dd582b4526afa20518b98c2e1cb0054653053a844cf265b25040029",
              "consume_user_resource_percent": 100,
              "name": "SomeContract",
              "origin_address": "41d1e7a6bc354106cb410e65ff8b181c600ff14292",
              "abi": {
                "entrys": [
                  {
                    "inputs": [
                      {
                        "name": "key",
                        "type": "uint256"
                      },
                      {
                        "name": "value",
                        "type": "uint256"
                      }
                    ],
                    "name": "set",
                    "stateMutability": "Nonpayable",
                    "type": "Function"
                  },
                  {
                    "outputs": [
                      {
                        "name": "value",
                        "type": "uint256"
                      }
                    ],
                    "constant": true,
                    "inputs": [
                      {
                        "name": "key",
                        "type": "uint256"
                      }
                    ],
                    "name": "get",
                    "stateMutability": "View",
                    "type": "Function"
                  }
                ]
              },
              "origin_energy_limit": 100000
            }
          },
          "type_url": "type.googleapis.com/protocol.CreateSmartContract"
        },
        "type": "CreateSmartContract"
      }
    ],
    "ref_block_bytes": "0a49",
    "ref_block_hash": "975853d6629c8702",
    "expiration": 1652153760000,
    "fee_limit": 1000000,
    "timestamp": 1652153701556
  },
  "raw_data_hex": "0a020a492208975853d6629c87024080f2a6e08a305add03081e12d8030a30747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e437265617465536d617274436f6e747261637412a3030a1541d1e7a6bc354106cb410e65ff8b181c600ff142921289030a1541d1e7a6bc354106cb410e65ff8b181c600ff142921a5c0a2b1a03736574220e12036b65791a0775696e743235362210120576616c75651a0775696e74323536300240030a2d10011a03676574220e12036b65791a0775696e743235362a10120576616c75651a0775696e743235363002400222fd01608060405234801561001057600080fd5b5060de8061001f6000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631ab06ee58114604d5780639507d39a146067575b600080fd5b348015605857600080fd5b506065600435602435608e565b005b348015607257600080fd5b50607c60043560a0565b60408051918252519081900360200190f35b60009182526020829052604090912055565b600090815260208190526040902054905600a165627a7a72305820fdfe832221d60dd582b4526afa20518b98c2e1cb0054653053a844cf265b2504002930643a0c536f6d65436f6e747261637440a08d0670b4a9a3e08a309001c0843d"
}

The transaction structure of different types of transactions are the same, but the content contained in raw_data is different, which is mainly reflected in the contract.parameter.value field of the transaction.

The contract.parameter.value in the contract deployment transaction contains the following:

  • owner_address: address of contract owner, that is Contract deployer address
  • new_contract: details of the new smart contract
    • origin_address:address of smart contract owner
    • contract_address:address of the smart contract
    • ABI:ABI of the smart contract
    • bytecode: bytecode of the smart contract
    • call_value:amount of TRX that send to the smart contract
    • consume_user_resource_percent:user energy payment percentage
    • name:the name of the smart contract
    • origin_energy_limit:limit of the owner’s energy consuming for each transaction, in sun
  • call_token_value: amount of TRC10 token sent to the newly created smart contract
  • token_id: TRC10 token id

Smart contract invocation and query

triggersmartcontract

The contract call is to create a TriggerSmartContract type transaction. You can create a triggering contract call transaction through the fullnode api wallet/triggersmartcontract , after the transaction is created, it needs to be signed, then broadcasted to the entire network.


curl -X POST https://api.shasta.trongrid.io/wallet/triggersmartcontract -d '{
"contract_address":"419E62BE7F4F103C36507CB2A753418791B1CDC182",
"function_selector":"transfer(address,uint256)",
"parameter":"00000000000000000000004115208EF33A926919ED270E2FA61367B2DA3753DA0000000000000000000000000000000000000000000000000000000000000032",
"fee_limit":100000000,
"call_value":0,
"owner_address":"41977C20977F412C2A1AA4EF3D49FEE5EC4C31CDFB"
}'

Parameter description:

  • contract_address:contract address
  • owner_address: caller address
  • function_selector:contract function
  • parameter:the encoded parameter value of contract method. In this example, there are two parameters that should be passed in, namely address and uint256 type. For details on how to encode and decode the parameters, please refer to Parameter Encoding and Decoding chapter
  • fee_limit:The upper limit of the energy consumed by the transaction that the caller is willing to undertake, please refer to the description of feelimit
  • call_value:amount of TRX that send to the smart contract

After the above command is executed successfully, the following results will be returned, including a contract calling transaction: transaction:

{
	"result": {
		"result": true
	},
	"transaction": {
		"visible": false,
		"txID": "d2ce86097df40287ad45ebc67f0d546ee98c2d7cd7c101e4d4d5b0c8a752d900",
		"raw_data": {
			"contract": [{
				"parameter": {
					"value": {
						"data": "a9059cbb00000000000000000000004115208ef33a926919ed270e2fa61367b2da3753da0000000000000000000000000000000000000000000000000000000000000032",
						"owner_address": "41977c20977f412c2a1aa4ef3d49fee5ec4c31cdfb",
						"contract_address": "419e62be7f4f103c36507cb2a753418791b1cdc182"
					},
					"type_url": "type.googleapis.com/protocol.TriggerSmartContract"
				},
				"type": "TriggerSmartContract"
			}],
			"ref_block_bytes": "1c51",
			"ref_block_hash": "74912b480b7b887c",
			"expiration": 1652169501000,
			"fee_limit": 100000000,
			"timestamp": 1652169442098
		},
		"raw_data_hex": "0a021c51220874912b480b7b887c40c8d2e7e78a305aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a1541977c20977f412c2a1aa4ef3d49fee5ec4c31cdfb1215419e62be7f4f103c36507cb2a753418791b1cdc1822244a9059cbb00000000000000000000004115208ef33a926919ed270e2fa61367b2da3753da000000000000000000000000000000000000000000000000000000000000003270b286e4e78a30900180c2d72f"
	}
}

The contract.parameter.value in the contract call transaction contains the following:

  • owner_address:caller address
  • contract_address:contract address
  • data:The contract function selector and its parameters, the first 4 bytes are the contract function selector, which is the first 4 bytes of the result obtained by performing the Keccak-256 operation on the contract function name and parameters, which is used for the virtual machine to find the function . The remaining bytes of data are the parameters of the function. For details on encoding and decoding, please refer to the Parameter Encoding and Decoding chapter.
  • call_value:amount of TRX that send to the smart contract
  • token_id:The token id of the TRC10 token sent to the contract
  • call_token_value:amount of TRC10 token sent to the smart contract

triggerconstantcontract

To invoke the constant function of the contract through the fullnode api wallet/triggerconstantcontract, because it is a query operation and does not need to be chained, so no signature and broadcast are required :

curl -X POST https://127.0.0.1:8090/wallet/triggerconstantcontract -d '{
"contract_address":"419E62BE7F4F103C36507CB2A753418791B1CDC182",
"function_selector":"balanceOf(address)",
"parameter":"000000000000000000000041977C20977F412C2A1AA4EF3D49FEE5EC4C31CDFB",
"owner_address":"41977C20977F412C2A1AA4EF3D49FEE5EC4C31CDFB"
}'

Parameter description:

  • contract_address:contract address
  • owner_address:caller address
  • function_selector:triggered contract method
  • parameter:The parameters to be passed in the contract method. For details on encoding and decoding, please refer to the chapter on parameter encoding and decoding.

The return result is as follows:

{
	"result": {
		"result": true
	},
	"constant_result": ["0000000000000000000000000000000000000000000000000000000430e1b700"],
	"transaction": {
		"ret": [{}],
		"visible": false,
		"txID": "7f47212aed2fdab232195feece54fc302bde2ce379e92ffd0d0e95206ce7a3bb",
		"raw_data": {
			"contract": [{
				"parameter": {
					"value": {
						"data": "70a08231000000000000000000000041977c20977f412c2a1aa4ef3d49fee5ec4c31cdfb",
						"owner_address": "41977c20977f412c2a1aa4ef3d49fee5ec4c31cdfb",
						"contract_address": "419e62be7f4f103c36507cb2a753418791b1cdc182"
					},
					"type_url": "type.googleapis.com/protocol.TriggerSmartContract"
				},
				"type": "TriggerSmartContract"
			}],
			"ref_block_bytes": "5ab1",
			"ref_block_hash": "f24f075df912f43e",
			"expiration": 1590382815000,
			"timestamp": 1590382762536
		},
		"raw_data_hex": "0a025ab12208f24f075df912f43e4098cecfd1a42e5a8e01081f1289010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412540a1541977c20977f412c2a1aa4ef3d49fee5ec4c31cdfb1215419e62be7f4f103c36507cb2a753418791b1cdc182222470a08231000000000000000000000041977c20977f412c2a1aa4ef3d49fee5ec4c31cdfb70a8b4ccd1a42e"
	}
}
  • constant_result:It is the result of querying the contract. In this example, the return value is of type uint256. For details on how to encode and decode the return value, please refer to the Parameter Encoding and Decoding chapter.

consume_user_resource_percent

Contract invocation requires payment of a certain resource fee. In order to encourage users to conduct contract transactions and reduce their invocation costs, the TRON network supports contract deployers to share part of the contract invocation fee. When deploying the contract, the user's energy payment ratio can be set through the parameter consume_user_resource_percent.

The user energy payment ratio is the ratio of the energy paid by the user for smart contract execution. For example, if the user energy payout ratio is set to 60, the user pays 60% of the energy required for contract execution, and the developer (contract deployer) pays the remaining 40% of the energy. This parameter can only be an integer between 0 and 100 (inclusive 0 and 100). Developers are advised to appropriately increase the user's energy payment ratio to prevent users from attacking the contract and exhausting the contract owner's account resources.

After the contract is successfully deployed, the user energy payment ratio can also be modified. For example, the contract owner can modify it through the fullnode HTTP API wallet/updatesetting.

Note: Although the contract developer may need to share a certain percentage of the energy cost of the contract invocation, when the energy of the developer's account is not enough to pay for the part he or she need undertake, or the energy of the developer's account consumed by this invocation exceeds the value of origin_energy_limit, the rest is borne by the caller.

feelimit

The feelimit refers to the upper limit of the energy cost that the caller is willing to undertake for the deployment or invocation of the smart contract, in sun (1TRX = 1e6 sun). Currently, the upper limit of the energy cost that can be set is 15000 TRX. If the feelimit is set greater than 15000TRX, an error will be occurred.

When executing the contract, Energy is calculated and deducted one by one instruction. If the energy used is exceeded, the contract execution will fail and the deducted Energy will not be refunded;

Before deploying the contract to the mainnet, it is best to set a reasonable feelimit. For example, when deploying large contracts or running complex functions, a larger feelimit is necessary. However, due to the existence of contract execution timeouts, infinite loops in contracts, illegal operations, and transfers to non-existing accounts, relatively low feelimit would be the better option.