Introduction to Smart Contracts
What is a Smart Contract?
The concept of smart contracts was first proposed by Nick Szabo in 1995. A Smart contract is a computer protocol designed to disseminate, verify or execute contracts in an informational manner. Smart contracts allow transactions to be executed without a trusted third party, and the transactions are traceable and irreversible.
Its purpose is to provide a secure method that outperforms traditional contracts and reduces other transaction costs associated with contracts.
For Conflux network, a "smart contract" is a simple program that runs on the Conflux chain. Each instance of a smart contract is a collection of code and data that resides at a specific address on the Conflux chain. Since the state on the blockchain is fully deterministic, operations on smart contracts are guaranteed to produce the same results on all blockchain nodes. Furthermore, since smart contracts run on the blockchain, the decentralization and non-tamperable characteristics of the blockchain ensure certainty and security in the operation of the contract. Therefore, a wide range of decentralized applications (DApps) are created based on smart contracts, including games, digital collectibles, online voting systems, financial products, etc.
There are two account types on the Conflux chain: user accounts and smart contract accounts. Once the smart contract is deployed, a corresponding smart contract account is created. Smart contract accounts have a CFX balance and they can also interact with other accounts. However, they are not controlled by users but by the program deployed on the network. User accounts are able to interact with smart contracts by submitting transactions that execute the functions defined on the smart contract. The smart contract enables us to define rules just like traditional contracts and automates the execution through codes.
Nick Szabo used the example of a vending machine to describe how real-world contractual obligations can be programmed into software and hardware systems. Each person simply puts the correct number of coins into the machine and can expect to receive a product in exchange. Similarly, on Conflux, a smart contract is able to perform a certain task and get a certain result under specified conditions.
Let's look at one of the simplest smart contract implementations of a vending machine.
This contract has two functions: method
refill enables administrators to refill the products; method
purchase enables the customers to purchase products using CFX tokens. Just like how vending machines eliminate the need for salesmen, smart contracts can eliminate intermediaries in many industries.
The smart contract is a set of code (contract function) and data (contract state variables). For the line
mapping (address => uint) public cupcakeBalances; , it declares a state variable named cupcakeBalances with type
mapping (address => uint). You can see it as a table in the database. Meanwhile, the contract methods
purchase are used to read or modify the state of the data in that database table.
This contract is written in
solidity, whose syntax is similar to
pragma solidity ^0.8.0;indicates that this contract needs to be compiled with a
VendingMachineassigns the contract name as
address public owner;defines a public state variable with the name
event Purchase(address customer, uint amount);defines the
eventwith the name
eventis similar to the logging function in other languages. Its role is mainly to record some important information when the contract is executed. For example,
Purchaseis an event that generates a purchase record when a customer purchases an item.
constructorunction is executed exactly once when the contract is deployed;
balanceOffunction (marked as
view) is a read-only function that can't be used to modify the contract state;
refillfunction is an ordinary function, can be called by sending a transaction. This function will change the contract state;
require(msg.sender == owner,..);indicates that only when the condition
msg.sender == owneris fulfilled (that is, the caller is the administrator), the state of contract variable
cupcakeBalancescan be modified to refill the products;
payable, indicating that you can send CFX at the same time when the function is called. Since customers need to pay CFX to purchase, it is marked as
require(msg.value >= amount * 1 ether,..)indicates the full amount of CFX must be paid in order to complete the purchase.
- The number of products in the vending machines decreases after a successful purchase and the number of goods owned by the customers (indicated by
After writing the contract, you need to first compile the contract and then deploy it to the Conflux chain by sending a transaction. Then, you can interact with the contract by calling it.
Once the contract is deployed, anyone can call it. However, the state of the contract will be changed only when a certain condition is satisfied.
For further instructions on the Solidity language, please refer to the official Solidity Documentation
Next, we will introduce the process of compilation, deployment, invocation, and contract execution.
Contract compilation is the process of generating the elements required when deploying the contract from the contract code through the compiler. There are two main parts in the compilation result,
Bytecode: smart contracts are executed on the Ethereum Virtual Machine (EVM). The bytecode is the hexadecimal value corresponding to the contract that the EVM can recognize.
ABI: ABI refers to Application Binary Interface, which describes function name, modifier, visibility, parameter name, and its type, returns value name and its type, and description of events in the public interface of contract (in JSON format). When we call the contract function externally and encode it in a certain way based on the description of the function in the ABI, we can get a value that the EVM can recognize and display in hexadecimal format. You can use this value to interact with the contract.
You can use
solc, conflux-truffle to compile the smart contract.
Here, we take solc as an example
Attention: The compiler version needs to match the version specified in the contract, to download the v0.6.12 version, use
npm install -g [email protected]
The contract deployment is creating a contract instance on the Conflux blockchain by sending a transaction with
to left empty.
If the constructor contains parameters,
datashould be a combination of
bytecodeand the ABI encoding of the
We will use
js-conflux-sdk to demonstrate.
As shown in the example above, the contract is deployed after sending a transaction with data as bytecode. The
contractCreated field of the
transaction receipt is the contract address after deployment.
The example directly sending transaction for demostration purpose. If the contract constructor contains parameters, a better way is to use contract development tools like
conflux-truffle to deploy.
#Calling smart contracts
After the contract is deployed, you can interact with the contract. There are two ways:
Calling through the RPC
cfx_call: this type of contract calling is only executed in the EVM but does not actually change the state. This is usually used to call read-only contract functions or to simulate the execution of a transaction to see if it can be executed successfully.
Sending transaction: this type of contract call will change the contract state when executed.
The data used when calling the contract is generated by ABI encoding based on the function information described by the ABI. The first 4 bytes are the function selector (the first 4 bytes of the Keccak (SHA-3) hash of the function signature), and the fifth byte starts with the ABI-encoded parameter.
We will use js-conflux-sdk to demonstrate.
From the log, we can see that the corresponding RPC information of
contract.cupcakeBalances(me.address) is as follows.
rpc method is
cfx_call, data is the result of
function selector + ABI-encoded result of parameter list. The first 4 bytes
0xe18a7b92 is the function selector of function
balanceOf. The calculation takes keccak operation
keccak256("balanceOf(address)") on the signature
balanceOf and then takes the first 4 bytes.
00000000000000000000000019f4bcf113e0b896d9b34294fd3da86b4adf0302is the ABI-encoded value of paramter
The returned value is
0x0000000000000000000000000000000000000000000000000000000000000000, which is the result of ABI-encoded value 0 with
The RPC method for
cfx_sendRawTransaction, which is sending transaction. This will change the state of the contract. The encoding method for the transaction's data is also
function selector + ABI-encoded result of parameter list. You can check this through getTransactionByHash
We can see a record from the
logs field of
logs indicate the event that happened in the transaction.
The event analysis result is
This indicates that one
Purchase event happened, customer is
cfxtest:aap9kthvctunvf030rbkk9k7zbzyz12dajp1u3sp4g, quantity is 2.
purchase is complete,
cupcakeBalances[0x19f4bcf113e0b896d9b34294fd3da86b4adf0302] changed from 0 to 2. State has changed.
Attention: When deploying or calling contracts on the Conflux chain, if new storage space is occupied in the contract, some CFX will be collateralized for the occupied space; this will be refunded after the storage is released. For more information, please visit storage collateral mechanism of Conflux.
In addition to solidity, you can also use vyper for smart contract development.
Conflux also has more friendly and efficient smart development tools for developers.