Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use the advanced features of Solidity

2025-04-11 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces "how to use the advanced features of Solidity". In daily operation, I believe many people have doubts about how to use the advanced features of Solidity. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful to answer the doubts about "how to use the advanced features of Solidity". Next, please follow the editor to study!

Preface

FISCO BCOS uses the Solidity language for intelligent contract development. Solidity is a complete Turing programming language for blockchain platform design, supporting function calls, modifiers, overloading, events, inheritance, libraries and other high-level language features.

Reasonably control the types of functions and variables

Based on the classic object-oriented programming principle of the least known principle (Least Knowledge Principle), an object should have the least understanding of other objects. Good Solidity programming practice should also conform to this principle: each contract clearly and reasonably defines the visibility of functions, exposes the least information to the outside world, and manages the visibility of internal functions.

At the same time, the correct modification of the types of functions and variables can provide different levels of protection to the data within the contract to prevent unexpected operations in the program from causing data errors; it can also improve the readability and quality of the code, reduce misunderstandings and bug;, and optimize the cost of contract execution and improve the efficiency of the use of resources in the chain.

Guarding the door of function operation: function visibility

There are two ways for Solidity to call functions:

Internal call: also known as "message call". The common ones are the functions inside the contract, the functions of the parent contract and the calls of library functions. (for example, suppose there is an f function in the A contract, then within the A contract, the other functions call the f function as f (). )

External calls: also known as "EVM calls". It is generally a cross-contract function call. External calls can also be made within the same contract. (for example, assuming that the f function exists in contract A, it can be called in contract B by using A.F (). Within the A contract, you can call it with this.f (). ).

Functions can be decorated with external, public, internal, or private identifiers.

Based on the above table, we can get the visibility of the function public > external > internal > private.

In addition, if the function does not use the above type identifier, the function type is public by default.

To sum up, we can summarize the different usage scenarios of the above identifiers:

Public, public function, system default. It is usually used to modify a function that can be exposed to the outside, and the function may be called internally at the same time.

External, an external function, is recommended only for externally exposed functions. When one of the parameters of a function is very large, if you explicitly mark the function as external, you can force the storage location of the function to be set to calldata, which saves storage or computing resources when the function is executed.

Internal, an internal function, is recommended for all functions that are not exposed outside the contract to avoid the risk of being attacked due to permission exposure.

Private, a private function, is used in very few scenarios where contract functions are not open to the outside of the contract and cannot be inherited.

It is important to note, however, that no matter what identifier is used, even private, the entire function executes procedures and data that are visible to all nodes, and other nodes can validate and replay arbitrary historical functions. In fact, all the data of the whole intelligent contract is transparent to the participating nodes of the block chain.

Users who have just come into contact with the block chain often misunderstand that the privacy of the uplink data can be controlled and protected by permission control operations on the block chain.

This is a wrong view. In fact, under the premise that the business data of the blockchain is not specially encrypted, all the data in the same account book of the blockchain is sold to all nodes after consensus, and the data on the chain is globally open and the same. Intelligent contracts can only control and protect the execution rights of contract data.

How to correctly select function modifiers is a required course in contract programming practice. Only by mastering this section can you freely control the access to contract functions and improve the security of contracts.

Least exposed necessary information: visibility of variables

As with functions, for state variables, you need to pay attention to visibility modifiers. The modifier of the state variable is internal by default and cannot be set to external. In addition, when a state variable is modified to public, the compiler generates a function with the same name as the state variable.

For more information, please see the following example:

This mechanism is a bit like the @ Getter annotation provided by the lombok library in the Java language, which generates a get function for a POJO class variable by default, greatly simplifying the writing of some contract code.

Similarly, the visibility of variables needs to be reasonably modified, and variables that should not be disclosed are decisively modified with private to make the contract code more in line with the "least known" design principle.

Classify functions precisely: types of functions

Functions can be declared as pure and view, as shown in the following figure.

So, what is read or modified state? Simply put, the two states read or modify the data related to the ledger.

In FISCO BCOS, the read status may be:

Read the status variable.

Access block,tx, any member of msg (except msg.sig and msg.data).

Call any function that is not marked pure.

Use inline assembly that contains some opcodes.

The modification status may be:

Modify the status variable.

To produce an event.

Create additional contracts.

Use selfdestruct.

Call any function that is not marked view or pure.

Use the underlying call.

Use inline assembly that contains specific opcodes.

It is important to note that in some versions of the compiler, there is no forced syntax checking for these two keywords.

It is recommended to use pure and view to declare functions whenever possible, such as declaring library functions that do not read or modify any state as pure, which not only improves the readability of the code, but also makes it more pleasing to the eye.

Value determined at compile time: state constant

The so-called state constant refers to the state variable declared as constant.

Once a state variable is declared as constant, the value of the variable can only be determined at compile time and cannot be modified. The compiler usually calculates the actual value of this variable in the compiled state and does not reserve storage space for the variable. Therefore, constant only supports decorated value types and strings.

State constants are generally used to define business constant values with clear meaning.

Slice-oriented programming: function modifier (modifier)

Solidity provides a powerful syntax for changing the behavior of functions: function modifiers (modifier). Once a function is added with a modifier, the code defined within the modifier can be executed as a decoration for that function, similar to the concept of a decorator in other high-level languages.

This is abstract, so let's look at a concrete example:

As shown above, after defining the onlyOwner modifier, the require statement requires that msg.sender must be equal to owner within the modifier. The following "_;" represents the code in the decorated function.

So, the actual execution order of the code is as follows:

Execute the statement of the onlyOwner modifier, first execute the require statement. (execute line 9)

Executes the statement of the changeOwner function. (executive line 15)

Because the changeOwner function is decorated with onlyOwner, this function can be called successfully only if msg.sender is owner, otherwise an error rollback will be reported.

At the same time, the modifier can also pass in parameters, for example, the above modifier can also be written as:

The same function can have multiple modifiers, separated by spaces, and the modifiers are checked and executed in turn. In addition, modifiers can be inherited and overridden.

Because of its powerful functions, modifiers are also often used to achieve access control, input checking, logging and so on.

For example, we can define a modifier that tracks the execution of a function:

In this way, any function modified by the logMethod modifier can record the log before and after the execution of its function, realizing the log wrapping effect. If you are used to using the AOP of the Spring framework, you can also try to implement a simple AOP function in modifier.

The most common way to open modifier is by providing a function validator. In practice, some check statements of contract code are often abstracted and defined as a modifier. For example, onlyOwner in the above example is a classic permission verifier. In this way, even the logic of checking can be quickly reused, and users no longer have to worry about the fact that smart contracts are full of parameter checking or other check code.

Can debug's log: events in the contract (Event)

After introducing functions and variables, let's talk about one of the more unique advanced features of Solidity-the event mechanism.

Events allow us to easily use EVM's logging infrastructure, while Solidity events do the following:

Record the parameters defined by the event and store them in the log of the blockchain transaction, providing cheap storage.

A callback mechanism is provided. After the event is executed successfully, the node sends a callback notification to the registered listener SDK, triggering the callback function to be executed.

Provides a filter to support parameter retrieval and filtering.

The use of events is very simple and can be played in two steps.

The first step is to define an event using the keyword "event". It is recommended that the naming of events start with a specific prefix or end with a specific suffix, which is easier to distinguish from functions, and in this article we will uniformly name events with the "Log" prefix. Next, we use "event" to define an event tracked by a function call:

Event LogCallTrace (address indexed from, address indexed to, bool result)

Events can be inherited in the contract. When they are called, the parameters are stored in the transaction log. These logs are saved in the block chain and associated with the address. In the above example, the parameters are searched with indexed, otherwise they are stored in the log data and cannot be searched.

The second step is to trigger the definition event within the corresponding function. When invoking an event, add the keyword "emit" before the event name:

In this way, when the function body is executed, the execution LogCallTrace will be triggered.

Finally, in the Java SDK of FISCO BCOS, the contract event push function provides an asynchronous push mechanism for contract events. The client sends a registration request to the node, carries the contract event parameters concerned by the client in the request, and the node filters the Event Log of the request block according to the request parameters, and pushes the results to the client in stages. For more details, please refer to the contract event push feature documentation. In SDK, you can search based on a specific value based on the indexed property of the event.

Contract event push function document: https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/sdk/java_sdk.html#id14

However, logs and events cannot be accessed directly, even in the contracts created.

But the good news is that the definition and declaration of logs are very convenient for traceability and export "after the event."

For example, we can define and bury enough events in the writing of the contract, and through the data export subsystem of WeBASE, we can export all logs to databases such as MySQL. This is especially suitable for scenarios such as generating reconciliation files, generating reports, and OLTP queries for complex businesses. In addition, WeBASE provides a dedicated code generation subsystem to help analyze specific business contracts and automatically generate the corresponding code.

WeBASE data export subsystem: https://webasedoc.readthedocs.io/zh_CN/latest/docs/WeBASE-Collect-Bee/index.html code generation subsystem: https://webasedoc.readthedocs.io/zh_CN/latest/docs/WeBASE-Codegen-Monkey/index.html

In Solidity, events are a very useful mechanism. If the biggest difficulty in intelligent contract development is debug, then making good use of event mechanisms can allow you to quickly subdue Solidity development.

Object-oriented overloading

Overloading refers to a function of the same name that a contract has several different parameters. For the caller, you can use the same function name to call multiple functions with the same function but different parameters. In some scenarios, this operation can make the code clearer and easier to understand, and readers with some programming experience must have a deep understanding of this.

A typical overloaded syntax is shown below:

It is important to note that there is only one constructor per contract, which means that the contract constructor does not support overloading.

We can imagine a world without overloading, where programmers must rack their brains and find ways to name functions, and people may lose a few more hairs.

Object-oriented inheritance

Solidity uses "is" as the inheritance keyword. Therefore, the following code indicates that contract B inherits contract A.

Inherited contract B can access all non-private functions and state variables of inherited contract A.

In Solidity, the underlying implementation principle of inheritance is that when a contract inherits from multiple contracts, only one contract is created on the block chain, and the code of all base class contracts is copied into the created contract.

Compared with the inheritance mechanism of languages such as C++ or Java, Solidity's inheritance mechanism is somewhat similar to Python and supports multiple inheritance mechanisms. Therefore, a single contract can be used in Solidity to inherit multiple contracts.

In some high-level languages, such as Java, for the sake of security and reliability, only single inheritance is supported, and multiple inheritance is implemented by using interface mechanisms. For most scenarios, the mechanism of inheritance alone can meet the requirements.

Multi-inheritance will bring many complex technical problems, such as the so-called "diamond inheritance". It is suggested to avoid complex multi-inheritance as much as possible in practice.

Inheritance simplifies people's understanding and description of abstract contract model, clearly reflects the hierarchical relationship between related contracts, and provides the function of software reuse. In this way, code and data redundancy can be avoided and the reusability of the program can be increased.

Object-oriented abstract classes and interfaces

According to the principle of dependency inversion, smart contracts should be interface-oriented as much as possible, without relying on specific implementation details.

Solidity supports mechanisms for abstracting contracts and interfaces.

If a contract has an unimplemented method, then it is an abstract contract. For example:

Abstract contracts cannot be compiled successfully, but can be inherited.

The interface uses the keyword interface, and the above abstraction can also be defined as an interface.

Interfaces are similar to abstract contracts, but do not implement any functions, and there are further restrictions:

Cannot inherit other contracts or interfaces.

Unable to define constructor.

Unable to define variable.

Unable to define structure

Unable to define enumeration.

Appropriate use of interfaces or abstract contracts can help enhance the scalability of contract design. However, due to the limitations of computing and storage resources on the blockchain EVM, do not overdesign, which is also a sinkhole that veteran drivers who move from high-level language technology stack to Solidity development often fall into.

Avoid repeating wheels: library (Library)

In software development, many classical principles can improve the quality of software, the most classic of which is to reuse high-quality code that has been tested, polished and strictly tested as much as possible. In addition, reusing mature library code can also improve the readability, maintainability, and even extensibility of the code.

Like all major languages, Solidity provides a mechanism for Library. Solidity's library has the following basic characteristics:

Users can use the keyword library to create contracts just as they do with contracts.

Libraries can neither be inherited nor be inherited.

The library's internal function is visible to the caller.

The library is stateless and cannot define state variables, but the state variables explicitly provided by the calling contract can be accessed and modified.

Next, let's look at a simple example. Here is a code base for LibSafeMath in the FISCO BCOS community. We have streamlined this, leaving only the function of addition:

We just need to import the library file in the contract, and then use L.F () to call the function, (for example, LibSafeMath.add (aforce b)).

Next, we write a test contract that invokes the library, which is as follows:

In the FISCO BCOS console, we can test the results of the contract (for more information on the introduction to the console, please see the details of the FISCO BCOS console, Flying Block chain experience). The running results are as follows:

From the above example, we can clearly understand how libraries should be used in Solidity.

Similar to Python, in some scenarios, the instruction "using A for B;" can be used to attach library functions (from library A) to any type (B). These functions will receive the object that called them as the first argument (like the self variable of Python). This feature makes the use of the library easier and more intuitive.

For example, we make the following simple changes to the code:

Verify that the results are still correct.

At this point, the study on "how to use the advanced features of Solidity" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report