Solidity Document
Chúng ta sẽ đến với những ví dụ cơ bản trước khi đi sâu vào chi tiết của ngôn ngữ Solidity
Các ví dụ cơ bản
Storage Example
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;
contract SimpleStorage {
uint storedData;
function set(uint x) public {
storedData = x;
}
function get() public view returns (uint) {
return storedData;
}
}
Dòng số 2 chúng ta có thể thấy đây là phiên bản solidity sử dụng để viết smart contract, điều này đảm bảo rằng hợp đồng không thể biên dịch với phiên bản nhỏ hơn0.4.16
và lớn hơn hoặc bằng phiên bản0.9.0
Hợp đồng trong solidity về cơ bản là một tập hợp các mã (các chức năng của nó) và dữ liệu (các trạng thái của nó) được nằm tại những địa chỉ cụ thể trên Ethereum Blockchain. Dòng uint storedData;
khai báo biến trạng thái storedData
có kiểu uint
( unsigned integer of 256 bits)
Để truy cập vào biến trạng thái bạn cần sử dụng tiền tố this.
Bất kỳ ai cũng có thể ghi đè giá trị storedData
của bạn bằng cách thực hiện hàm set
nhưng giá trị cũ của bạn vẫn được lưu trữ trong lịch sử của blockchain. Trong những ví dụ tiếp, bạn sẽ có thể cài đặt các giới hạn truy cập mà chỉ có bạn mới có thể thay đổi giá trị storedData
Hãy cẩn thận khi sử dụng văn bản Unicode, các ký tự trông giống nhau (hoặc giống hệt nhau) có thể có các code points khác nhau và như vậy khi mã hóa sẽ thành một mảng byte khác nhau
Subcurrency Example
Ví dụ sau sẽ tạo ra một form triển khai hợp đồng thông minh của tiền điện tử. Hợp đồng này chỉ cho phép người dùng tạo ra đồng tiền mới. Bất kỳ ai cũng có thể gửi tiền cho nhau mà không cần đăng ký với tên người dùng và mật khẩu từ trước. Tất cả những gì bạn cần là Ethereum keypair.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Coin {
// The keyword "public" makes variables
// accessible from other contracts
address public minter;
mapping (address => uint) public balances;
// Events allow clients to react to specific
// contract changes you declare
event Sent(address from, address to, uint amount);
// Constructor code is only run when the contract
// is created
constructor() {
minter = msg.sender;
}
// Sends an amount of newly created coins to an address
// Can only be called by the contract creator
function mint(address receiver, uint amount) public {
require(msg.sender == minter);
require(amount < 1e60);
balances[receiver] += amount;
}
// Sends an amount of existing coins
// from any caller to an address
function send(address receiver, uint amount) public {
require(amount <= balances[msg.sender], "Insufficient balance.");
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
}
The line address public minter;
khai báo biến có kiểu address
. address
là giá trị 160 bit không cho phép bất kỳ phép toán số học nào. Nó phù hợp để lưu trữ địa chỉ của hợp đồng, hoặc public key của keypair thuộc về tài khoản bên ngoài.
public
tự động sinh ra một function cho phép bạn truy cập vào giá trị hiện tại của biến trạng thái từ bên ngoài hợp đồng. Nếu không có từ khóa này, các hợp đồng khác không có cách nào có thể truy cập được vào biến. Mã của từ khóa public
sau khi được biên dịch tương đương với
function minter() external view returns (address) { return minter; }
Tiếp theo đến mapping (address => uint) public balances;
cũng tạo ra một public state variable, nhưng có kiểu dữ liệu phức tạp hơn, nó sẽ ánh xạ từ address
đến uint
Mappings có thể trông như một bảng hash được khởi tạo sao cho mỗi khóa sẽ ánh xạ tới một giá trị có kiểu byte là tất cả các số 0. Tuy nhiên, không thể lấy danh sách tất cả các khóa của ánh xạ, cũng như danh sách tất cả các giá trị. Nó chỉ ghi lại những gì bạn thêm vào
Hàm getter (hàm này được tạo tự động trong trình biên dịch) được tạo bởi từ khóa public phức tạp hơn trong trường hợp mapping. Nó trông giống như sau:
function balances(address _account) external view returns (uint) {
return balances[_account];
}
Bạn có thể sử dụng chức năng này để truy vấn số dư của một tài khoản.
The line event Sent(address from, address to, uint amount);
declares an "event", which is emitted in the last line of the function send
.Các ứng dụng Ethereum client như ứng dụng web có thể lắng nghe các sự kiện này được emitted trên blockchain mà không tốn nhiều chi phí. Ngay sau khi nó được emitted, bên máy client sẽ nhận các tham số from, to, amount điều này giúp bạn theo dõi các giao dịch.
Để lắng nghe các sự kiện, bên phía client, chúng ta sử dụng web3.js. Trước tiên, chúng ta tạo Coin
contract object trong web3.js và bất kỳ giao diện người dùng nào cũng gọi balances
function được tạo tự động từ bên trên:
Coin.Sent().watch({}, '', function(error, result) {
if (!error) {
console.log("Coin transfer: " + result.args.amount +
" coins were sent from " + result.args.from +
" to " + result.args.to + ".");
console.log("Balances now:\n" +
"Sender: " + Coin.balances.call(result.args.from) +
"Receiver: " + Coin.balances.call(result.args.to));
}
})
The functions that make up the contract, and that users and contracts can call are mint
and send
.
The mint
function có chức năng gửi số tiền mới được tạo đến một tài khoản khác. The require function call defines conditions that reverts all changes if not met. In this example, require(msg.sender == minter);
ensures that only the creator of the contract can call mint
(quan sát hàm constractor ta có thể thấy minter = msg.sender
tức là khi bắt đầu người dùng tạo hợp đồng (sender
) thì giá trị minter
chỉ thuộc về duy nhất 1 người. Do đó nếu không có điều kiện msg.sender == minter
thì chỉ cần một ai đó mạo danh sender
bất kỳ thì hàm mint
sẽ được chạy ), and require(amount < 1e60);
ensures a maximum amount of tokens. This ensures that there are no overflow errors in the future.
The send
function can be used by anyone (who already has some of these coins) to send coins to anyone else. If the sender does not have enough coins to send, the require
call fails and provides the sender with an appropriate error message string.
Cấu trúc Solidity source file
Các mã nguồn có thể chứa một số lượng tùy ý các định nghĩa hợp đồng, chỉ thị nhập, chỉ thị pragma và các định nghĩa cấu trúc, enum, hàm và biến hằng số.
SPDX License Identifier
Trust in smart contract can be better established if their source code is available. Since making source code available always touches on legal problems with regards to copyright, the Solidity compiler encourages the use of machine-readable SPDX license identifiers. Every source file should start with a comment indicating its license:
Ví dụ: // SPDX-License-Identifier: MIT
Trình biên dịch sẽ không xác nhận giấy phép là một phần trong tập danh sách được cấp phép bởi SPDX, nhưng nó bao gồm chuỗi được cung cấp trong bytecode metadata. Nếu bạn không muốn chỉ định giấy phép hoặc nếu mã nguồn không phải là mã nguồn mở, vui lòng sử dụng giá trị đặc biệt UNLICENSED. Pragmas Từ khóa pragma được sử dụng để kích hoạt các tính năng hoặc kiểm tra trình biên dịch nhất định. Một chỉ thị pragma luôn là cục bộ cho một tệp nguồn, vì vậy bạn phải thêm pragma vào tất cả các tệp của mình nếu bạn muốn kích hoạt nó trong toàn bộ dự án của mình.
Structure of a Contract
Hợp đồng trong Solidity giống với classes trong ngôn ngữ hướng đối tượng. Trong mỗi hợp đồng có thể được khai báo: State Variables
, Functions
, Function modifiers
, Events
, Struct Types
và Enum Type. Hơn nữa các hợp đồng có thể thừa kế các hợp đồng khác. Có 2 loại hợp đồng đặc biệt đó là: Libraries
và Interfaces
.
State Variables
State Variables
là các biến có giá trị được lưu trữ vĩnh viễn trong bộ lưu trữ hợp đồng.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;
contract SimpleStorage {
uint storedData; // State variable
// ...
}
Function
Các hàm là các đơn vị mã có thể thực thi được. Các chức năng thường được xác định bên trong hợp đồng, nhưng chúng cũng có thể được định nghĩa bên ngoài hợp đồng.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >0.7.0 <0.9.0;
contract SimpleAuction {
function bid() public payable { // Function
// ...
}
}
// Helper function defined outside of a contract
function helper(uint x) pure returns (uint) {
return x * 2;
}
Function calls
có thể xảy ra bên trong hoặc bên ngoài và có các mức độ hiển thị khác nhau đối với các hợp đồng khác.
Function Modifiers
Function Modifiers
có thể được sử dụng để sửa đổi ngữ nghĩa của các hàm theo cách khai báo
Giống như các hàm, modifiers
có thể overriden.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.9.0;
contract Purchase {
address public seller;
modifier onlySeller() { // Modifier
require(
msg.sender == seller,
"Only seller can call this."
);
_;
}
function abort() public view onlySeller { // Modifier usage
// ...
}
}
Events
Events are convenience interfaces with the EVM logging facilities.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.21 <0.9.0;
contract SimpleAuction {
event HighestBidIncreased(address bidder, uint amount); // Event
function bid() public payable {
// ...
emit HighestBidIncreased(msg.sender, msg.value); // Triggering event
}
}
Struct Types
Structs are custom defined types that can group several variables.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;
contract Ballot {
struct Voter { // Struct
uint weight;
bool voted;
address delegate;
uint vote;
}
}
Enum Types
Enums can be used to create custom types with a finite set of ‘constant values’.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;
contract Purchase {
enum State { Created, Locked, Inactive } // Enum
}
Last updated
Was this helpful?