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.
#
ExampleLet'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 refill
and 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 javascript
.
pragma solidity ^0.8.0;
indicates that this contract needs to be compiled with a>=0.8.0<0.9.0
compiler.- contract
VendingMachine
assigns the contract name asVendingMachine
; address public owner;
defines a public state variable with the nameowner
and typeaddress
;event Purchase(address customer, uint amount);
defines theevent
with the namePurchase
.event
is similar to the logging function in other languages. Its role is mainly to record some important information when the contract is executed. For example,Purchase
is an event that generates a purchase record when a customer purchases an item.- The
constructor
unction is executed exactly once when the contract is deployed; - The
balanceOf
function (marked asview
) is a read-only function that can't be used to modify the contract state; refill
function 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 conditionmsg.sender == owner
is fulfilled (that is, the caller is the administrator), the state of contract variablecupcakeBalances
can be modified to refill the products;purchase
function includespayable
, 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 aspayable
.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
cupcakeBalances[msg.sender]
) increases.
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.
#
CompilationContract 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, abi
and bytecode
.
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
Install solc
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]
Compilation
Generating bytecode
file __...VendingMachine.bin
and abi
file __...VendingMachine.abi
__...VendingMachine.bin
__...VendingMachine.abi
#
DeployThe contract deployment is creating a contract instance on the Conflux blockchain by sending a transaction with data
as bytecode
and to
left empty.
If the constructor contains parameters,
data
should be a combination ofbytecode
and the ABI encoding of theconstructor
.
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 js-conflux-sdk
contract
and conflux-truffle
to deploy.
#
Calling smart contractsAfter 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(address)
of balanceOf
and then takes the first 4 bytes. 00000000000000000000000019f4bcf113e0b896d9b34294fd3da86b4adf0302
is the ABI-encoded value of paramter 0x19f4bcf113e0b896d9b34294fd3da86b4adf0302
The returned value is 0x0000000000000000000000000000000000000000000000000000000000000000
, which is the result of ABI-encoded value 0 with uint
type
The RPC method for purchase
is 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 transaction receipt
. 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.
After 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.
#
Additional resourcesIn addition to solidity, you can also use vyper for smart contract development.
Conflux also has more friendly and efficient smart development tools for developers.
Others