Smart Contract¶
Smart contracts are the key feature of TRON network. Creating and interacting with smart contracts are made easy by TronPy.
Calling smart contract¶
There are two types of smart contract calls, const call and trigger call. For a const call, the contract method
must be marked pure or view. And the calling result will be returned immediately.
While the trigger call is just a type of system contract call, you sign the calling transaction, and broadcast it.
The calling result can be fetched and parsed through the API.
Const call¶
Const call is wrapped as a function object. The result is parsed according to ABI.
Take TRC20 as an example, the balance query is a very common task:
from tronpy import Tron
client = Tron(network="nile")
cntr = client.get_contract("THi2qJf6XmvTJSpZHc17HgQsmJop6kb3ia")
print(dir(cntr.functions)) # prints list of contract functions
for f in cntr.functions:
print(f) # prints function signature(i.e. type info)
# function allowance(address _owner, address _spender) view returns (uint256 remaining)
# function approve(address _spender, uint256 _amount) returns (bool success)
# function balanceOf(address _owner) view returns (uint256 balance)
# function decimals() view returns (uint8 )
# function name() view returns (string )
# function owner() view returns (address )
# function symbol() view returns (string )
# function totalSupply() view returns (uint256 theTotalSupply)
# function transfer(address _to, uint256 _amount) returns (bool success)
# function transferFrom(address _from, address _to, uint256 _amount) returns (bool success)
print("Symbol:", cntr.functions.symbol()) # The symbol string of the contract
# Symbol: RMB
precision = cntr.functions.decimals()
print("Balance:", cntr.functions.balanceOf("TJRabPrwbZy45sbavfcjinPJC18kjpRTv8") / 10**precision)
# Balance: 100000.0
Trigger call¶
Trigger call requires sign and broadcast.
>>> from tronpy import Tron
>>> from tronpy.keys import PrivateKey
>>> client = Tron(network='nile')
>>> contract = client.get_contract('THi2qJf6XmvTJSpZHc17HgQsmJop6kb3ia')
>>> print(contract.functions.transfer)
function transfer(address _to, uint256 _amount) returns (bool success)
>>> txn = (
... contract.functions.transfer('TVjsyZ7fYF3qLF6BQgPmTEZy1xrNNyVAAA', 1_000)
... .with_owner('TGQgfK497YXmjdgvun9Bg5Zu3xE15v17cu') # address of the private key
... .fee_limit(5_000_000)
... .build()
... .sign(priv_key)
... )
>>> txn.broadcast() # or txn.broadcast()
{'result': True, 'txid': '63609d84524b754a97c111eec152700f273979bb00dad993d8dcce5848b4dd9a'}
>>> _.wait()
{'id': '63609d84524b754a97c111eec152700f273979bb00dad993d8dcce5848b4dd9a',
'blockNumber': 6609475, 'blockTimeStamp': 1592539509000,
'contractResult': ['0000000000000000000000000000000000000000000000000000000000000001'],
'contract_address': 'THi2qJf6XmvTJSpZHc17HgQsmJop6kb3ia',
'receipt': {'energy_usage': 13062, 'energy_usage_total': 13062, 'net_usage': 344, 'result': 'SUCCESS'},
'log': [{'address': 'THi2qJf6XmvTJSpZHc17HgQsmJop6kb3ia',
'topics': ['ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'00000000000000000000000046a23e25df9a0f6c18729dda9ad1af3b6a131160',
'000000000000000000000000d8dd39e2dea27a40001884901735e3940829bb44'],
'data': '00000000000000000000000000000000000000000000000000000000000003e8'}]}
# trigger output can be parsed manually
>>> contract.functions.transfer.parse_output(_['contractResult'][0])
True
# or use `.result()` to parse it automatically
>>> txn.broadcast().result()
True
Trigger call with transfer¶
Use with_transfer or with_asset_transfer.
>>> txn = (
... contract.functions.transfer.with_transfer(100_000_000)
... .call('TVjsyZ7fYF3qLF6BQgPmTEZy1xrNNyVAAA', 1_000)
... .with_owner('TGQgfK497YXmjdgvun9Bg5Zu3xE15v17cu') # address of the private key
... .fee_limit(5_000_000)
... .build()
... .sign(priv_key)
... )
Creating smart contract¶
When you've compiled your contract code, you can deploy it on chain.
from tronpy import Tron, Contract
from tronpy.keys import PrivateKey
client = Tron(network="nile")
priv_key = PrivateKey(bytes.fromhex("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"))
bytecode = "608060405234801561001057600080fd5b5060c78061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806360fe47b11460375780636d4ce63c146062575b600080fd5b606060048036036020811015604b57600080fd5b8101908080359060200190929190505050607e565b005b60686088565b6040518082815260200191505060405180910390f35b8060008190555050565b6000805490509056fea2646970667358221220c8daade51f673e96205b4a991ab6b94af82edea0f4b57be087ab123f03fc40f264736f6c63430006000033"
abi = [
{
"inputs": [],
"name": "get",
"outputs": [{"internalType": "uint256", "name": "retVal", "type": "uint256"}],
"stateMutability": "view",
"type": "function",
}
]
cntr = Contract(name="SimpleStore", bytecode=bytecode, abi=abi)
txn = client.trx.deploy_contract("TGQgfK497YXmjdgvun9Bg5Zu3xE15v17cu", cntr).fee_limit(5_000_000).build().sign(priv_key)
print(txn)
result = txn.broadcast().wait()
print(result)
print("Created:", result["contract_address"])
created_cntr = client.get_contract(result["contract_address"])
Note
The constructor's parameters are provided via bytecode.
cntr = Contract(name="SimpleStore", bytecode=bytecode, abi=abi)
parameter = cntr.constructor.encode_parameter("TRh5N2iAmjyeJbbCXsDuo7PNZvyjVWtL2e", 18)
cntr.bytecode = bytecode + parameter
Default Fee Limit¶
The default fee limit is 5_000_000 for contract deploy or trigger, 0 otherwise.
Fee limit is set by .fee_limit() method of transaction.
It also can be set via conf object:
client = Tron(network="nile", conf={"fee_limit": 10_000_000})
Contract with Un-published ABI¶
You can set JSON ABI via cntr.abi = [...].
import json
from tronpy import Tron
from tronpy import keys
dzi_trade = "TS..........(omitted).............j"
from_addr = "TV..........(omitted).............a"
priv_key = keys.PrivateKey(bytes.fromhex("975a...............(omitted)..............8d97b"))
abi = """
[{"constant":false,
"inputs":[{"name":"min_tokens","type":"uint256"},{"name":"deadline","type":"uint256"}],
"name":"trxToTokenSwapInput",
"outputs":[{"name":"","type":"uint256"}],
"payable":true,
"stateMutability":"payable",
"type":"Function"}]
"""
client = Tron(network="nile")
cntr = client.get_contract(dzi_trade)
cntr.abi = json.loads(abi) # load ABI, while contract on chain has no ABI set.
# call contract functions with TRX transfer
txn = (
cntr.functions.trxToTokenSwapInput.with_transfer(1_000_000_000)(1_000_000_000_000, 5)
.with_owner(from_addr)
.fee_limit(1_000_000_000)
.build()
.sign(priv_key)
)
print("txn =>", txn)
print("broadcast and result =>", txn.broadcast().wait())
API reference¶
Contract
¶
Contract(
addr=None,
*,
bytecode: str | bytes = "",
name: str = None,
abi: dict | list[dict] | None = None,
user_resource_percent: int = 100,
origin_energy_limit: int = 1,
origin_address: str = None,
owner_address: str = "410000000000000000000000000000000000000000",
code_hash: str = None,
client=None,
)
A smart contract object.
Methods:
-
clear_abi–Clear contract ABI.
-
update_origin_energy_limit–Create a Transaction to update origin energy limit.
-
update_user_resource_percent–Create a Transaction to update user resource percent.
Attributes:
-
abi–ABI list of the contract
-
address–Address of the contract
-
bytecode–Bytecode of the contract, in
hexformat -
code_hash–Hash of smart contract bytecode.
-
constructor(ContractConstructor) –The constructor of the contract.
-
events(ContractEvents) –The
ContractEventsobject, wraps all contract events. -
functions(ContractFunctions) –The
ContractFunctionsobject, wraps all contract methods. -
name–Name of the contract
-
origin_address–Origin address of the contract, i.e. contract creator
-
origin_energy_limit–Origin energy limit, default 1
-
owner_address–Current transaction owner's address, to call or trigger contract
-
user_resource_percent–User resource percent, default 100
Source code in tronpy/contract.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | |
functions
property
¶
functions: ContractFunctions
The ContractFunctions object, wraps all contract methods.
origin_address
instance-attribute
¶
origin_address = origin_address
Origin address of the contract, i.e. contract creator
origin_energy_limit
instance-attribute
¶
origin_energy_limit = origin_energy_limit
Origin energy limit, default 1
owner_address
instance-attribute
¶
owner_address = owner_address
Current transaction owner's address, to call or trigger contract
user_resource_percent
instance-attribute
¶
user_resource_percent = user_resource_percent
User resource percent, default 100
clear_abi
¶
clear_abi() -> TransactionBuilder
Clear contract ABI.
Source code in tronpy/contract.py
139 140 141 142 143 144 145 146 147 148 149 150 | |
update_origin_energy_limit
¶
update_origin_energy_limit(limit: int) -> TransactionBuilder
Create a Transaction to update origin energy limit.
Source code in tronpy/contract.py
125 126 127 128 129 130 131 132 133 134 135 136 137 | |
update_user_resource_percent
¶
update_user_resource_percent(percent: int) -> TransactionBuilder
Create a Transaction to update user resource percent.
Source code in tronpy/contract.py
111 112 113 114 115 116 117 118 119 120 121 122 123 | |
ContractFunctions
¶
ContractFunctions(contract)
Methods:
-
__getattr__–Get the actual contract method object.
Source code in tronpy/contract.py
264 265 | |
__getattr__
¶
__getattr__(method: str)
Get the actual contract method object.
Source code in tronpy/contract.py
274 275 276 277 278 279 | |
ContractMethod
¶
ContractMethod(abi: dict, contract: Contract)
Methods:
-
__call__–Call the contract method.
-
call–Call the contract method.
-
parse_output–Parse contract result as result.
-
with_asset_transfer–Call a contract function with TRC10 token transfer.
-
with_owner–Set the calling owner address.
-
with_transfer–Call a contract function with TRX transfer.
amountinSUN.
Source code in tronpy/contract.py
335 336 337 338 339 340 341 342 343 344 345 346 | |
__call__
¶
__call__(*args, **kwargs) -> TransactionBuilder
Call the contract method.
Source code in tronpy/contract.py
383 384 385 386 | |
call
¶
call(*args, **kwargs) -> TransactionBuilder
Call the contract method.
Source code in tronpy/contract.py
370 371 372 | |
parse_output
¶
parse_output(raw: str) -> Any
Parse contract result as result.
Source code in tronpy/contract.py
374 375 376 377 378 379 380 381 | |
with_asset_transfer
¶
with_asset_transfer(amount: int, token_id: int) -> ContractMethod
Call a contract function with TRC10 token transfer.
Source code in tronpy/contract.py
364 365 366 367 368 | |
with_owner
¶
with_owner(addr: str) -> ContractMethod
Set the calling owner address.
Can also be changed through TransactionBuilder.with_owner().
Source code in tronpy/contract.py
351 352 353 354 355 356 357 | |
with_transfer
¶
with_transfer(amount: int) -> ContractMethod
Call a contract function with TRX transfer. amount in SUN.
Source code in tronpy/contract.py
359 360 361 362 | |
ContractEvents
¶
ContractEvents(contract)
Methods:
-
__getattr__–Get the actual contract event object.
Source code in tronpy/contract.py
192 193 | |
__getattr__
¶
__getattr__(event: str)
Get the actual contract event object.
Source code in tronpy/contract.py
202 203 204 205 206 207 | |