TRON supports Solidity, a developer-friendly smart contract development language, which has the following features:
Object-oriented, high-level language
Supports inheritance, libraries and complex user-defined types.
# The composition of a smart contract
A smart contract is consist of data and functions.
Any contract data must be assigned to a location: either to storage or memory. It is costly to modify storage in a smart contract so you need to consider where your data should live wisely.
Persistent data is referred to as storage and is represented by state variables. These values get stored permanently on the blockchain. You need to declare the type so that the contract can keep track of how much storage on the blockchain it needs when it compiles.
Types of variables include: address, boolean, integer, fixed point numbers, fixed-size byte arrays, dynamically-sized byte arrays, Rational and integer literals, String literals, Hexadecimal literals, Enums.
address`：In order to be compatible with Ethereum, the data of `
address` in Solidity is the value obtained by performing the following operations on the hex format address of the TRON network account:
Remove the prefix `
41` from the TRON Hex format address
Perform [Mixed-case checksum](🔗) on the results obtained in the previous step `
Mixed-case checksum` : According to a certain logic, some letters in the address are capitalized, together with the remaining lowercase letters to form a checksum, so that the address has the ability to self-check. On average, there will be 15 check bits per address, and the net probability that a randomly generated address if mistyped will accidentally pass a check is 0.0247%.
For example, this TRON network account `
TA9h822trLafTtsGXQc4g4ehPvyNzkQNsS`, the Hex format address is: `
4101fba20cb405734c6b2e704b9ed67c0b5ea74d9e` , the value in solidity is:
Values that are only stored for the lifetime of a contract function's execution are called memory variables. Since these are not stored permanently on the blockchain, they are much cheaper to use.
### Environment variables
In addition to the variables you define on your contract, there are some special global variables. They are primarily used to provide information about the blockchain or current transaction.
|block.timestamp||uint256||Timestamp of the current block in seconds|
|block.number||uint||Current block number|
|block.coinbase||address||Super representative's Node address producing the current block|
|msg.sender||address||Message sender (current smart contract caller)|
|msg.value||uint||The amount of SUN send with message|
|msg.data||bytes||complete call data|
|msg.sig||bytes4||first 4 bytes of call data (function identifier)|
|now||uint||current block timestamp (block.timestamp)|
There are two types of function calls:
internal` - these don't create an EVM call
Internal functions and state variables can only be accessed internally (i.e. from within the current contract or contracts deriving from it)
external` - these do create an EVM call
External functions are part of the contract interface, which means they can be called from other contracts and via transactions. An external function f cannot be called internally (i.e. f() does not work, but this.f() works).
They can also be public or private:
public` - public functions can be called internally from within the contract or externally via messages
private` - private functions are only visible for the contract they are defined in and not in derived contracts
Here's a function for updating a state variable on a contract, The parameter value of type string is passed into the function: update_name. It's declared public, meaning anyone can access it. It's not declared view, so it can modify the contract state.
### View functions
view` functions promise not to modify the state of the contract's data, such as query operations. Here is an example of a function that queries account balances:
What is considered modifying state:
Writing to state variables.
Creating other contracts.
Sending trx via calls.
Calling any function not marked `
view` or `
Using low-level calls.
Using inline assembly that contains certain opcodes.
### Constructor functions
constructor functions are only executed once when the contract is first deployed. Like constructor in many class-based programming languages, these functions often initialize state variables to their specified values.
### Built-in functions
In addition to the variables and functions you define on your contract, there are some special built-in functions. For example, `
address.send()`, it allows contract to send TRX to other accounts.
## Writing functions
Your function needs:
parameter variable and type (if it accepts parameters)
declaration of `
public` or `
declaration of `
pure` or `
view` or `
returns type (if it returns a value)
A complete contract might look something like this. Here the constructor function provides an initial value for the dapp_name variable.
## Events and Logs
Events allow us to easily query "things" that happened when a contract transaction was executed. Logs are used to "write" data to data structures outside of smart contracts. Log information cannot be accessed by smart contracts, but can provide information about transactions and what happened in blocks. When a contract transaction is successfully executed, the smart contract can emit events and write logs to the blockchain.
# Smart Contract Library
You don't need to write every smart contract in your project from scratch. There are many open source smart contract libraries available that provide reusable building blocks for your project that can save you from having to reinvent the wheel.
## What's in A Library
You can usually find two kinds of building blocks in smart contract libraries: reusable behaviors you can add to your contracts, and implementations of various standards.
When writing smart contracts, there is a good chance you'll find yourself writing similar patterns over and over, like assigning an admin address to carry out protected operations in a contract. Smart contract libraries usually provide reusable implementations of these behaviors as libraries or via inheritance in Solidity.
As an example, following is a simplified version of the Ownable contract from the OpenZeppelin Contracts library, which designates an address as the owner of a contract, and provides a modifier for restricting access to a method only to that owner.
To use a building block like this in your contract, you would need to first import it, and then extend from it in your own contracts. This will allow you to use the modifier provided by the base Ownable contract to secure your own functions.
Another popular example is [SafeMath](🔗). This library provides arithmetic functions with overflow checks, which are not provided by the language. It's a good practice to use it instead of native arithmetic operations to guard your contract against overflows, which can have disastrous consequences!
The TRON community has defined several standards in the form of TRCs: TRC10, TRC20, TRC721 etc. When including an TRC as part of your contracts, it's a good idea to look for standard implementations rather than trying to roll out your own.
## How to Add A Library
Always refer to the documentation of the library you are including for specific instructions on how to include it in your project. Several Solidity contract libraries are packaged using npm, so you can just npm install them. When including a library, always keep an eye on the language version. For instance, you cannot use a library for Solidity 0.6 if you are writing your contracts in Solidity 0.5.
## When to Use
Using a smart contract library for your project has several benefits. First and foremost, it saves you time by providing you with ready-to-use building blocks you can include in your system, rather than having to code them yourself. Security is also a major plus. Open source smart contract libraries are also often heavily scrutinized. Given many projects depend on them, there is a strong incentive by the community to keep them under constant review. It's much more common to find errors in application code than in reusable contract libraries. Some libraries also undergo external audits for additional security.
However, using smart contract libraries carry the risk of including code you are not familiar with into your project. Without a good understanding of what that contract does, you may be inadvertently introducing an issue in your system due to an unexpected behavior. Always make sure to read the documentation of the code you are importing, and then review the code itself before making it a part of your project!
Last, when deciding on whether to include a library, consider its overall usage. A widely-adopted one has the benefits of having a larger community and more eyes looking into it for issues. Security should be your primary focus when building with smart contracts!