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

What is the definition of contract / abstract contract / interface / library for Solidity syntax

2025-02-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

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

This article mainly introduces "what is the definition of contract / abstract contract / interface / library of Solidity grammar". In daily operation, it is believed that many people have doubts about the definition of contract / abstract contract / interface / library of Solidity grammar. Xiaobian consulted all kinds of materials and sorted out simple and useful operation methods. I hope it will be helpful to answer the question of "what is the definition of contract / abstract contract / interface / library of Solidity grammar"! Next, please follow the editor to study!

1 contract definition (Contract)

Solidity contracts are similar to classes in object-oriented languages. There are state variables for data persistence and functions that can be modified in the contract. When the function of another contract instance is called, an EVM function call is executed, which changes the context of the execution so that the state variable of the previous contract cannot be accessed.

1.1 create contract

Contracts can be created "from the outside" through the ethersquare deal or from within the Solidity contract.

Some integrated development environments, such as Remix, make the creation process smoother by using some user interface elements. It is best to use JavaScript API web3.js when programming to create a contract on Ethernet Square. Now, we have a method called web3.eth.Contract that makes it easier to create contracts.

When a contract is created, a constructor (a function with the same name as the contract) is executed. The constructor is optional. Only one constructor is allowed, which means that overloading is not supported.

Internally, constructor parameters are passed through ABI coding after the contract code, but you don't have to worry about it if you use web3.js.

If a contract wants to create another contract, the creator must know the source code (and binaries) of the contract being created. This means that it is not possible to cycle through the creation of dependencies.

Pragma solidity ^ 0.4.16 position contract OwnedToken {/ / TokenCreator is the contract type defined below. / / if you do not create a new contract, you can also refer to it. TokenCreator creator; address owner; bytes32 name; / / this is the constructor that registers the creator and sets the name. The function OwnedToken (bytes32 _ name) public {/ / status variable is accessed by its name, not by, for example, this.owner. / / this also applies to functions, especially in constructors, where you can only call them like this ("internally"), / / because the contract itself does not yet exist. Owner = msg.sender; / / from `address` to `TokenCreator` makes an explicit type conversion / / and assumes that the type of the calling contract is TokenCreator. There is no real way to check this. Creator = TokenCreator (msg.sender); name = _ name;} function changeName (bytes32 newName) public {/ / only creator (that is, the contract that creates the current contract) can change the name-- because the contract is implicitly converted to an address, / / so the comparison here is feasible. If (msg.sender = = address (creator)) name = newName;} function transfer (address newOwner) public {/ / only the current owner can send token. If (msg.sender! = owner) return; / / We would also like to ask if creator can be sent. / / notice that a function in the contract defined below is called. / / if the call fails (for example, due to insufficient gas), execution will be stopped immediately. If (creator.isTokenTransferOK (owner, newOwner) owner = newOwner;}} contract TokenCreator {function createToken (bytes32 name) public returns (OwnedToken tokenAddress) {/ / create a new Token contract and return its address. / / in terms of JavaScript, the return type is a simple `address` type, because / / this is the closest type available in ABI. Return new OwnedToken (name);} function changeName (OwnedToken tokenAddress, bytes32 name) public {/ / similarly, the external type of `tokenAddress` is also `address`. TokenAddress.changeName (name);} function isTokenTransferOK (address currentOwner, address newOwner) public view returns (bool ok) {/ / check some arbitrary cases. Address tokenAddress = msg.sender; return (keccak256 (newOwner) & 0xff) = (bytes20 (tokenAddress) & 0xff);}} 2 Abstract contract (Abstract Contract)

The contract function can be missing implementation, as shown in the following example (note that the function declaration begins with; ends):

Pragma solidity ^ 0.4.0X contract Feline {function utterance () public returns (bytes32);}

These contracts cannot be compiled successfully (even if they contain other implemented functions in addition to unimplemented functions), but they can be used as base class contracts:

Pragma solidity ^ 0.4.0X contract Feline {function utterance () public returns (bytes32);} contract Cat is Feline {function utterance () public returns (bytes32) {return "contract";}}

If a contract inherits from an abstract contract and does not implement all unimplemented functions through rewriting, then it itself is abstract.

3 Interface (Interface)

Interfaces are similar to abstract contracts, but they cannot implement any functions. 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. Some of the restrictions here may be lifted in the future.

The interface is basically limited to what the contract ABI can represent, and the conversion between the ABI and the interface should not lose any information.

Interfaces are represented by their own keywords:

Pragma solidity ^ 0.4.11 X interface Token {function transfer (address recipient, uint amount) public;} 4 Library (Libary)

Libraries are similar to contracts in that they only need to be deployed once at a specific address, and their code can be reused through EVM's DELEGATECALL (use the CALLCODE keyword before Homestead) feature. This means that if the library function is called, its code is executed in the context of the calling contract, that is, the this points to the calling contract, especially the storage of the calling contract. Because each library is a separate piece of code, it can only access the state variables explicitly provided by the calling contract (otherwise it cannot access these variables by name). Because we assume that libraries are stateless, if they do not modify the state (that is, if they are view or pure functions), library functions can only be used through direct calls (that is, without using the DELEGATECALL keyword). In particular, it is impossible to destroy any libraries unless you can circumvent Solidity's type system.

Libraries can be thought of as implicit base contracts that use their contracts. Although they are not explicitly visible in inheritance relationships, calling a library function is very similar to calling an explicit base class contract (if L is a library, you can use L.F () to call the library function). In addition, just as the library is a base class contract, the library's internal function is visible to all contracts that use the library. Of course, you need to use internal calling conventions to call internal functions, which means that all internal types, memory types, are passed by reference rather than copy. To do this in EVM, the code of the internal library function and all functions called from it are pulled into the calling contract at compile time, and then a JUMP call is used instead of DELEGATECALL.

The following example shows how to use libraries (but be sure to see that using for- https://solidity-cn.readthedocs.io/zh/develop/contracts.html?highlight=view#using-for has a better example of implementing set).

Library Set {/ / We have defined a new structure data type to hold the data in the call contract. Struct Data {mapping (uint = > bool) flags;} / / Note that the first parameter is of type "storage reference", so in the call the parameter passes only its storage address, not its content. / / this is a feature of library functions. If the function can be treated as a method of an object, the first parameter is customarily called `self`. Function insert (Data storage self, uint value) public returns (bool) {if (self.flags [value]) return false; / / already exists self.flags [value] = true; return true;} function remove (Data storage self, uint value) public returns (bool) {if (! self.flags [value]) return false / / there is no self.flags [value] = false; return true;} function contains (Data storage self, uint value) public view returns (bool) {return self.flags [value];}} contract C {Set.Data knownValues; function register (uint value) public {/ / you can call library functions without a specific instance of the library, / / because the current contract is "instance". Require (Set.insert (knownValues, value));} / / We can also access knownValues.flags directly in this contract if we like. }

Of course, you don't have to use libraries this way: they can also be used without defining structural data types. The function also does not need to store any reference parameters, the library can appear anywhere and can have multiple storage reference parameters.

Calls to Set.contains,Set.insert and Set.remove are compiled into external calls (DELEGATECALL). If you use libraries, note that external function calls are actually performed. Msg.sender, msg.value, and this will retain their values in the call (before Homestead, msg.sender and msg.value were changed because of the use of CALLCODE).

The following example shows how to use memory types and internal functions in the library to implement custom types without paying the overhead of external function calls:

Library BigInt {struct bigint {uint [] limbs;} function fromUint (uint x) internal pure returns (bigint r) {r.limbs = new uint [] (1); r.limbs [0] = x;} function add (bigint _ a, bigint _ b) internal pure returns (bigint r) {r.limbs = new uint [] (max (_ a.limbs.length, _ b.limbs.length)); uint carry = 0 For (uint I = 0; I

< r.limbs.length; ++i) { uint a = limb(_a, i); uint b = limb(_b, i); r.limbs[i] = a + b + carry; if (a + b < a || (a + b == uint(-1) && carry >

0) carry = 1; else carry = 0;} if (carry > 0) {/ / too bad, we need to add a limb uint [] memory newLimbs = new uint [] (r.limbs.length + 1); for (I = 0; I

< r.limbs.length; ++i) newLimbs[i] = r.limbs[i]; newLimbs[i] = carry; r.limbs = newLimbs; } } function limb(bigint _a, uint _limb) internal pure returns (uint) { return _limb < _a.limbs.length ? _a.limbs[_limb] : 0; } function max(uint a, uint b) private pure returns (uint) { return a >

B? A: B;}} contract C {using BigInt for BigInt.bigint; function f () public pure {var x = BigInt.fromUint (7); var y = BigInt.fromUint (uint (- 1)); var z = x.add (y);}}

Since the compiler cannot know where the library is deployed, we need to fill these addresses into the final bytecode through the linker (see using the command-line compiler-https://solidity-cn.readthedocs.io/zh/develop/using-the-compiler.html#commandline-compiler to learn how to link the bytecode using the command-line compiler). If these addresses are not passed as arguments to the compiler, the compiled hexadecimal code will contain placeholders in the form of Set____ (where Set is the name of the library). You can manually fill in the address to replace those 40 characters with the hexadecimal code of the library contract address.

Compared with the contract, the limitations of the library:

There are no state variables

Unable to inherit or be inherited

Cannot receive Ethernet coins

(these restrictions may be lifted in the future)

4.1 call protection of the library

If the code of the library is executed through CALL, instead of DELEGATECALL or CALLCODE, the result of execution will be rolled back unless it is a call to the view or pure function.

EVM does not provide a direct way for contracts to detect whether CALL is used, but contracts can use ADDRESS opcodes to find out where they are running. The generated code determines the invocation pattern by comparing this address with the address at the time of construction.

More specifically, the runtime code of the library always starts with a push instruction, which is 20 bytes zero at compile time. When the deployment code runs, this constant is replaced by the current address in memory, and the modified code is stored in the contract. At run time, this causes the deployment-time address to be the first constant to be push onto the stack, and for any non-view and non-pure functions, the scheduler code will compare whether the current address matches this constant.

4.2 Using For

The instruction using A for B; can be used to attach library functions (from library A) to any type (B). These functions receive the object that called them as their first argument (like the self variable of Python).

The effect of using A for *; is that the functions in library An are appended to any type.

In both cases, all functions are appended with a parameter, even if their first parameter type does not match the type of the object. Type checking is done only when function calls and parsing are overloaded.

The using A for B; directive is valid only in the current scope, currently in the current contract, and may be promoted to the global scope later. By introducing a module, you can use data types, including library functions, without adding code.

Let's rewrite the set example in the library in this way:

/ / this is the same code as before, but with no comments. Library Set {struct Data {mapping (uint = > bool) flags;} function insert (Data storage self, uint value) public returns (bool) {if (self.flags [value]) return false; / / self.flags [value] = true; return true;} function remove (Data storage self, uint value) public returns (bool) {if (! self.flags [value]) return false / / there is no self.flags [value] = false; return true;} function contains (Data storage self, uint value) public view returns (bool) {return self.flags [value];}} contract C {using Set for Set.Data; / / here is the key to modify Set.Data knownValues Function register (uint value) public {/ / Here, all variables of type Set.Data have / / corresponding member functions. / / The following function call is identical to / / `Set.insert (knownValues, value) `/ / here, all variables of type Set.Data have corresponding member functions. / / the following function calls have exactly the same effect as `Set.insert (knownValues, value) `. Require (knownValues.insert (value));}} can also extend the basic type like this: library Search {function indexOf (uint [] storage self, uint value) public view returns (uint) {for (uint I = 0; I < self.length; I +) if (self [I] = = value) return i; return uint (- 1);}} contract C {using Search for uint [] Uint [] data; function append (uint value) public {data.push (value);} function replace (uint _ old, uint _ new) public {/ / execute library function call uint index = data.indexOf (_ old); if (index = = uint (- 1) data.push (_ new); else data [index] = _ new;}}

Note that all library calls are actual EVM function calls. This means that if memory or value types are passed, a copy will be made, even if it is a self variable. Using stored reference variables is the only case where a copy does not occur.

At this point, the study of "what is the definition of contract / abstract contract / interface / library of Solidity grammar" 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