Solidity的方方面面

2023-10-17 17:10
文章标签 solidity 方方面面

本文主要是介绍Solidity的方方面面,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Solidity的方方面面

未标题-3

img

什么是Soilidity?

Solidity是一种面向合约的高级编程语言,用于实现智能合约。Solidity已经被设计用于以太坊虚拟机。

Solidity===智能合约。

Solidity的代码封装在合约中。合约是以太坊应用程序的基本构建块——所有变量和函数都属于一个合约,这将是所有项目的起点。

pragma solidity >=0.5.0 <0.6.0;
contract HelloWorld {
}

在上面的代码中,我们提供了考虑到我们的代码与b/w 0.5到0.6的任何版本兼容的版本。我们还创建了一个名为“HelloWorld”的合约。

状态变量和整数

状态变量永久存储在合约存储中。这意味着它们被写入以太坊区块链。可以把它们想象成写入DB。

contract Example {
// This will be stored permanently in the blockchain
uint myUnsignedInteger = 100;
string name = “vivek”
}

Uint数据类型是一个无符号整数。它应该是非负的。

数据类型

值类型:

Boolean(true / false),Integers(int / uint), Address(以太坊地址的大小),String, enum

引用类型:

数组、结构、映射

数学运算

Addition: x + y
Subtraction: x — y,
Multiplication: x * y
Division: x / y
Modulus / remainder: x % y (for example, 13 % 5 is 3, because if you divide 5 into 13, 3 is the remainder)
Exponential Operation
uint x = 5 ** 2; // equal to 5² = 25

结构

类似于C语言中的struct。当我们需要创建具有多个属性的复杂数据类型时,我们使用结构体。

struct Person {
uint age;
string name;

数组

数据的集合称为数组。两种类型:固定数组和动态数组。

顾名思义,固定数组有预定义的大小,而动态数组没有大小。

// Array with a fixed length of 2 elements:
uint[2] fixedArray;
// another fixed Array, can contain 5 strings:
string[5] stringArray;
// a dynamic Array — has no fixed size, can keep growing:
uint[] dynamicArray;

我们可以组合结构和数组。创建一个结构,然后拥有一个结构数组。就像在面向对象范例(如Java)中有一个对象和一个对象数组一样。

pragma solidity >=0.5.0 <0.6.0;
contract StudentFactory {
struct student {
string name;
uint roll;
}
student[] public students; // creates an array named students of student type objects

函数声明

function eatHamburgers(string memory _name, uint _amount) public {
}

函数的可见性是公开的。有两种方式可以传递参数给Solidity函数:

按值和按引用

eatHamburgers(“vitalik”, 100);

私人/公共函数

在Solidity中,函数默认是公共的,因此任何人都可以在网络中调用公共函数。然而,出于安全考虑,我们将函数设为私有,这样只有所有者才能调用函数。

function _eatHamburgers(string memory _name, uint _amount) private {
}

按照惯例,私有函数的开头带有下划线。

内部/外部关键字-

还有两种类型的函数可见性。内部类似于私有,除了它可以被继承的合约访问,即继承。

外部类似于公共。除了声明了这个函数的联系人之外,所有的合约都可以调用这个函数。

在函数中返回

函数声明包含返回值的类型。

function sayHi() public view/pure returns (string memory) {
return “Hi”;
}

这些函数可以标记为pure/view。当我们甚至没有访问传递的数据时,我们就将函数标记为pure。如果函数不修改数据,只查看数据,那么它将被标记为view。

类型转换

数据类型之间的转换称为类型转换。

uint8 a = 5;
uint b = 6;
// line below throws an error because a*b returns a uint, not uint8:
uint8 c = a * b;
// we have to typecast b as a uint8 to make it work:
uint8 c = a * uint8(b);

事件

事件用于向前端传达后端区块链网络上发生了一些事情。

// declare the event
event NotifyOnFrontend(uint x);
function add(uint _x, uint _y) public returns (uint) {
uint result = _x + _y;
//fire an event to let the frontend know the function was called
emit NotifyOnFrontend(result);
return result;
}

我们的前端代码应该已经安装了web3,并且应该监听“NotifyOnFrontend”事件,这样才能工作。我们的JavaScript框架或普通JS将不得不监听这个事件来接收它:

YourContract.NotifyOnFrontend(function(error, result) {
// do something with result
})

映射

这是存储有组织数据(如数组和结构)的另一种方法

mapping (address => uint) public accountBalance;

这是一个键值存储。address是键,accountBalance是值。

这可以用于在区块链中存储多个对象(数据)。检查示例如下:

例子:

contract Example {
struct UserInfo {
unit age;
string dob;
}
mapping(string => UserInfo) allusers;

function setUserInfo(string _name, uint _age, string _dob) public {allusers[_name].age = _age;allusers[_name].dob = _dob;
}

function getUserInfo(string _name) public view returns(uint, string) {
return (allusers[_name].age, allusers[_name].dob);
}

}

现在,如果可以用不同的值多次调用setUserInfo,比如:

setuserInfo(“Vivek”,26, 25/05/1995)
setuserInfo(“Supu”, 23, 01/09/1998)

要获得这些值,只需传递名称:

getUserInfo(“Vivek”); // 26 25/05/1995
getuserInfo(“Supu”); // 24 01/09/1998

全局变量

这些变量可用于像msg.sender这样的所有函数。我们所编写的任何Solidity程序,都应该由所有者调用。发送者的地址存储在msg.sender 全局变量中。

require

require用于验证这两个语句,并据此做出决定。如果条件为真,则代码成功运行,否则就抛出错误

function sayHi(string memory _name) public returns (string memory) {
/**Compares if _name equals “Vivek” Throws an error and exits if not true. Solidity doesn’t have native string comparison, so we
compare their keccak256 hashes to see if the strings are equaq **/
require(keccak256(abi.encodePacked(_name)) == keccak256(abi.encodePacked(“Vivek”)));
// If it’s true, proceed with the function:
return “Hi!”;
}
sayHi(“Vivek”) // executes successfully
sayHi(“Supu”) // throws an error

因此,require对于在运行函数之前验证某些条件必须为真非常有用。

继承

有时候,与其制定一个非常长的合约,还不如将代码逻辑拆分为多个合约来组织代码。

contract Animal {
function catchphrase() public returns (string memory) {
return “Animal”;
}
}
contract Cat is Animal {
function anotherCatchphrase() public returns (string memory) {
return “Cat is an Animal”;
}
}

import

将代码拆分为多个文件,并使用import来使用另一个文件中的功能。

这通常是在Solidity项目中处理长代码库的方式。

存储和内存

存储是指永久存储在区块链上的变量。内存变量是临时的,在对合约的外部函数调用之间会被删除。可以把它想象成电脑的硬盘与内存。

与区块链网络中的其他合约交互

关于这一点,我将写一篇单独的文章。现在,保持简短:

为了与其他合约交互,我们声明了一个类似object的接口。我们创建了一个合约,并在里面声明了一个函数,我们想要从另一个合约调用或使用它。函数只是骨架,它不包含主体。

contract GetNumber {
function getNum(uint _num) public returns(uint){
return _num;
}

假设有一个合约,我们想要使用上面的getNum函数。为此,我们将在项目中创建一个合约,并声明一个getNum函数框架(没有函数体)。

contract NumberInterface {
function getNum(uint _num) public returns(uint);
}

现在我们可以从NumberInterface合约中调用getNum函数。

在将合约部署到以太坊后,它就变成了不可变的,也就是说它不能被修改。部署到合约中的初始代码将永久地停留在区块链上。这就是安全性在Solidity中如此重要的原因之一。如果我们的合约代码中有一个缺陷,就没有办法在以后修补它。必须告诉我们的用户开始使用具有修复功能的不同智能合约地址。

函数修饰符

函数修饰符看起来就像函数,但是使用关键字修饰符而不是关键字函数。这些用于特殊情况,例如当您只希望您的所有者而不是所有人做某事时。

这有助于更新DApp的关键部分,同时防止其他用户破坏我们的合约。我处理过的一个用例是——当我们想在执行任何用例之前验证语句时。

gas

用户支付gas费来在以太坊网络上运行合约。gas以以太(以太坊上的货币)为单位计算。我们的函数的总gas成本等于它所有单独操作的总gas成本。

更多关于存储的内容

存储内存被永久写入到区块链中。全世界成千上万的节点需要将这些数据存储在它们的硬盘上,并且随着区块链的增长,这些数据量也会随着时间的推移而增长。所以这样做是有代价的。

为了降低成本,我们希望避免将数据写入存储,除非绝对必要。有时,这涉及到看似低效的编程逻辑——比如每次调用函数时都要在内存中重新构建数组,而不是简单地将该数组保存在全局存储变量中以便快速查找。

因此,建议尽可能使用内存类型,这样数据就不会永久存储,从而节省成本。循环在Solidity中将比使用存储更便宜。所以尽可能for 循环中使用内存。这与Java、Python等语言中所做的完全相反,因为for循环的计算成本更高。

For循环

Syntax类似于Javascript。

for (uint i = 1; i <= 10; i++) {
// body
}

应付修饰符

支付功能是使Solidity和以太坊如此酷的部分原因——它们是一种可以接收以太坊的特殊类型的功能。当我们在一个普通的web服务器上调用一个API函数时,我们不能在调用函数的同时发送美元——也不能发送比特币。

但在以太坊中,因为货币(以太坊)、数据(交易有效载荷)和合约代码本身都在以太坊上,所以我们可以同时调用一个函数并向合约支付费用。

这允许一些非常有趣的逻辑,比如为了执行一个函数,需要向合约支付一定的费用。

注意:

在以太坊中,当我们在合约上调用一个函数时,我们将其作为交易广播到网络上的一个或多个节点。节点在网络上收集一些交易,试图成为第一个解决计算密集型数学问题的“工作证明”,然后将这组交易连同他们的工作证明(PoW)发布为一个块到网络的其余部分。

代币

所以基本上,代币只是一个合约,它记录了谁拥有多少代币,以及一些函数,以便这些用户可以将他们的代币转移到其他地址。

assert 与 require 的差异

Assert类似于require,如果为false则抛出错误。assert和require之间的区别是,当一个函数失败时,require会退还用户剩余的gas,而assert不会。

Metamask

这是Chrome和Firefox的浏览器扩展,允许用户安全地管理他们的以太坊账户和私钥,并使用这些账户与使用Web3.js的网站进行交互。

应用程序二进制接口。

在部署的合约之后,它会在以太坊上得到一个固定的地址,在那里它将永远存在。在以太坊网络中部署智能合约后,还会生成一个ABI。基本上,它是以JSON格式表示的合约方法,告诉Web3.js如何以我们的合约能够理解的方式格式化函数调用。

Web3Js

以太坊的JS前端库被称为web3.js。

Source:https://medium.com/coinmonks/learn-all-about-solidity-ethereum-45d709c4de77

关于

ChinaDeFi - ChinaDeFi.com 是一个研究驱动的DeFi创新组织,同时我们也是区块链开发团队。每天从全球超过500个优质信息源的近900篇内容中,寻找思考更具深度、梳理更为系统的内容,以最快的速度同步到中国市场提供决策辅助材料。

Layer 2道友 - 欢迎对Layer 2感兴趣的区块链技术爱好者、研究分析人与Gavin(微信: chinadefi)联系,共同探讨Layer 2带来的落地机遇。敬请关注我们的微信公众号 “去中心化金融社区”

640

这篇关于Solidity的方方面面的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/226789

相关文章

以太坊区块链 Solidity solc是什么

Solidity与Java类似。代码写好后,都需要通过编译器将代码转换成二进制。 在Java中,编译器是Javac,对于Solidity,是solc。 生成后的二进制代码,会放到虚拟机里执行。 Java代码在Java虚拟机(JVM)中执行,在Solidity中,是一个区块链上的虚拟机EVM。

FISCO BCOS 控制台 console solidity合约编译工具 生成abi bin java文件

下载控制台 https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/console/console_of_java_sdk.html   # 若控制台版本小于v2.8.0,脚本sol2java.sh的使用方法如下:$ bash sol2java.sh -h# Compile Solidity Tool./s

solidity一些内置的常用函数和关键字(含智能合约简单代码示例)

solidity一些内置的常用函数和关键字: 1. msg.sender 描述: msg.sender 是全局变量,代表当前调用者的地址,即谁发起了当前的合约调用。 **功能:**用于识别调用者的身份,通常用于权限控制。 示例: contract MyContract {address public owner;constructor() {owner = msg.sender; //

【Solidity】支付

以太比的单位 wei、gwei、finney 和 ether 是以太币(Ether)的不同单位。 wei 是以太币的最小单位,1 ether = 10^18 wei;这是 Solidity 中的默认单位 uint public oneWei = 1 wei; gwei 是 wei 的 10^9 倍,1 ether = 10^9 gwei;常用于表示交易费用 (gas price) ui

【solidity 学习】错误处理机制汇总

最近发现了一个很好的学习 web3 知识的平台 hackquest,也是一个社区,不仅可以学习 web3 知识,并且经常组织一些线上线下的活动鼓励大家稳步学习。 hackquest 网址 最近我在 solidity ,其中关于错误处理机制有三种:revert、require、assert、error、try\catch。他们的用法类似,容易产生混淆,这里记录一下他们的使用场景以及区别,以便容易

[Android源码分析]蓝牙打开流程分析——jni层之上的方方面面

在前面的UI分析的文章中我们已经发现,其实不管是设置中的开关和fragment之后的开关最终都是关联到BluetoothEnabler中去的,所以,我们直接去看这个里面对于开关的处理,开关的处理当然就是onCheckedChanged这个函数了,哈哈~~直接分析。。 1、蓝牙打开的按键处理 public void onCheckedChanged(CompoundButto

[Android源码解析]Property之十月怀胎到茁壮成长所涉及的方方面面

其实在网上讲Property的文章还是蛮多的,不过源码级分析的倒是不多,晓东正好做好了一个项目,其中涉及到了Property的一些内容,折腾了一段时间,心想不如来读读源码,看看究竟是怎么回事。 1、property内存区域的申请          在网上通常都是这样开始讲的“属性服务运行于init进程中。init进程首先创建一个共享内存区域,并保存一个指向该区域的描述符fd。

solidity上实现BLS签名机制

原文地址:https://ethereum.stackexchange.com/questions/59293/does-ethereum-support-pairing-operations BLS签名机制说明:http://www.ymcall.com/artinfo/698628886830280666.html   pragma solidity ^0.4.14;/*Exampl

Solidity选择使用 require 语句还是条件语句结合手动触发 revert 操作?

文章目录 Solidity选择使用 require 语句还是条件语句结合手动触发 revert 操作? Solidity选择使用 require 语句还是条件语句结合手动触发 revert 操作? IERC721 nft = IERC721(nftAddress); // 声明IERC721接口合约变量if (nft.getApproved(tokenId) != addre

OnlyOwner在Solidity中是一个修饰符,TypeError:

目录 OnlyOwner在Solidity中是一个修饰符 TypeError: Data location must be "memory" or "calldata" for parameter in function, but none was given. function AddDOm (address dataOwnermAddress, string dataProduct,