智能合约学习笔记——solidity语法

Posted 无名函数

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了智能合约学习笔记——solidity语法相关的知识,希望对你有一定的参考价值。

Solidity 是一个面向合约开发的高级语言,借鉴了其他一些高级语言,例如 javascript 和 Python,的特性。它是一门静态类型语言,支持继承,支持各种库和用户自定义的类型。非常适合用来开发类似于投票,众筹,拍卖,多重签名钱包等各种功能。

有一定的编程基础非常好入门

测试可以直接在在线网址https://remix.ethereum.org
CryptoZombies是一个很有趣的学习网址

注意solidity在后续版本0.5.0之后有较大变革,但下面学习内容依旧是根据0.4版本来进行的,是想先熟悉了再看改变了什么

简单举例

把一个数据保存到链上

// 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;
    

// 是solidity中的注释

第一行是说明源代码是根据GPL 3.0版本授权的。

第二行的意思是告诉编译器源代码所适用的Solidity版本为>=0.4.16 及 <0.9.0 。

contract SimpleStorage是指建立一个名为SimpleStorage的合约。

uint storedData定义一个名为storedData的uint型数据。

function set(uint x) public 建立一个名为set的、参数是一个uint型数的函数。此处的public是一种solidity访问权限设定的一种,是公开的意思,将允许这个函数在合约外也能被调用

function get() public view returns (uint)建立一个名为get、不需要参数、返回一个uint型数的函数。此处的view是一种修饰符,意思是可以自由调用,但是它只能“查看”区块链的状态而不能够改变它,也就是说在这个函数中只能够查看函数外某参数的值,而当你试图改变这个变量时就不能做到。

以上代码,首先定义了一个uint型的数,然后用set函数,输入一个数对storedData进行赋值,这将使这个值被存储在区块链上面,让get函数是可以将这个storedData的值读出来的函数。

Remix IDE简单使用


左边建立一个文件,右边进行编写
点击compile examp进行编译,下一个选项中deploy实施部署

部署完成后点击下方函数名调用

上面可以查看账户余额

数据类型

int型:有符号整数,默认256位。也可以自己规定位数,比如想要一个8位的int型有符号整数numa,则int8 numa;

uint型:无符号整数,默认256位。同样可以自己规定位数

bool型:布尔型,有true、false两种。定义一个布尔型数,不赋值默认是false

bytes型:字节型数组,可自定义长度例如bytes1 public num1 = 0x12;,可以通过num1.length得到字节数组长度。这时数组长度是固定的,要想得到一个可变成长度的字节数组,定义方式为bytes arr1 = new bytes(3);这就定义了一个长度为3的字节型,可以通过arr1.length=a;来改变字节长度。注意,不能像int型那样不规定长度的定义。
另外,可以赋值的语句是arr1[0]=0x11;,输出时可以一位一位的输出,也可以直接输出整个数组。arr1.push(0x56);push函数可以在arr1后面追加一个字节的值,但是注意只能让长度加1,多了会报错。
注意,当你想再函数中改变数组的值时,不能对函数使用view修饰。

string型:字符型。定义变量方式string testword="helloworld";,这里用单引号和双引号是一样的效果。这里不需要提前定义长度,默认就是可变的,想知道当前长度也不能有直接加length函数,而是应该先将类型转换为字节型bytes(testword).length;改变值时依旧需要强制类型转换bytes(testword)[0]='A';。返回值时,可以直接返回字符型,想知道16进制值时就可以将类型转换,同样bytes型输出时也可以强制转换为string型。
注意一个字符长度是1,一个汉字长度为3;储存中文和一些其他语言时,solidity使用的时UTF-8格式存储的。

数组:除了字节型数组外,还可以有数字型数组,语法跟bytes型一样,例如uint[3] testarr1;定义一个长度为3的无符号型整数数组。这里想知道长度不需要转换类型。定义可变长度数组可以是uint[] testarr=[1,2,3,4,5];;此时可以改变数组长度testarr.length=10;变长之后后面默认置0,依旧支持push函数在数组后面追加一个数。

二维数组:首先要明确定义二维数组时,例如uint[i][j] :代表的是有j个元素,每个元素包含i个值,这和其他许多语言相反。支持使用length函数获取长度,对数组直接用length函数得到的是j的值,也可以对uint[0]用length函数得到的是i的值。另外在对二维数组进行增删改等操作时又和其他语言一样了,即uint[i][j]表示第i个元素的第j个值,注意不用于初始化的语法整反。
想要可变长度的数组时,同样可以用uint[][] testarr1=[[1,2],[3,4],[5,6]];这样的语法来定义,跟一维数组不一样的是,二维不再支持push函数。依然支持对长度进行修改,但是注意未声明的值不能直接赋值,修改长度之后默认有值才可以,修改长度后未赋值的一样默认为0。

struct型:结构体,例如struct Person uint age; string name; 定义了一个名为Person类型的结构体,然后Person就可以像上面描述的类型一样被运用了。

常规运算

加减乘除:+ - * /
取余%
平方**
与或&& ||
按位与或非& | ~
!
异或^
左移右移<< >>

注意:
关于赋值,solidity是先将赋值语句之中所有的都计算出来之后再进行赋值操作的,这样就保证了精确度。
另外要注意每种类型变量的长度,注意溢出问题

修饰符

solidity的四种可见度/访问权限

public:任何人都可以调用该函数,包括DApp的使用者。
private:只有合约本身可以调用该函数(在另一个函数中)。
internal:只有这份合同以及由此产生的所有合同才能称之为合同。
external:只有外部可以调用该函数,而合约内部不能调用。

solidity的三种修饰符

view: 可以自由调用,因为它只是“查看”区块链的状态而不改变它
pure: 也可以自由调用,既不读取也不写入区块链
payable:常常用于将代币发送给合约地址。

需要注意的小tip

运算中的类型转换

在数据进行运算时,有时你需要变换数据类型。例如:

uint8 a = 5;
uint b = 6;

uint8 c = a * b;  // 将会抛出错误,因为 a * b 返回 uint, 而不是 uint8
// 我们需要将 b 转换为 uint8:
uint8 c = a * uint8(b);

上面, a * b 返回类型是 uint, 但是当我们尝试用 uint8 类型接收时, 就会造成潜在的错误。如果把它的数据类型转换为 uint8, 就可以了,编译器也不会出错。

伪随机数的一种

Ethereum 内部有一个散列函数keccak256,它用了SHA3版本。一个散列函数基本上就是把一个字符串转换为一个256位的16进制数字。
字符串的一个微小变化会引起散列数据极大变化。这在 Ethereum 中有很多应用。然后我们就可以根据这个思路来造一个伪随机数,尽管它是不安全的,却依然可以有一些地方可以使用。

区块链Solidity智能合约语言学习笔记

Solidity简介

以太坊拥有多种高级语言,可用于编写智能合约,每种语言都受到另一种广泛使用的语言的启发。最流行的一种叫做Solidity,它基于JavaScript。由于Solidity是迄今为止最成熟的以太坊语言,因此它是社区大力鼓励开发人员现在使用的语言。

Solidity是一种语法类似JavaScript的高级语言。它被设计成以编译的方式生成以太坊虚拟机代码。使用它很容易创建用于投票、众筹、封闭拍卖、多重签名钱包等等的合约。

编译环境

Remix在线编译器: http://remix.app.hubwiz.com/

VScode编译器也行,其插件:

                                        

第一个程序Hello world

参考:https://blog.csdn.net/weixin_45067603/article/details/105726491

pragma solidity ^0.4.0;

contract helloworld 
    string myword = "helloworld";
    
    function show() public view returns(string)
        return myword;
    
    
    function changMyword(string _newWord) public
        myword = _newWord;
    


solidity的四种可见度/访问权限

  • public:任何人都可以调用该函数,包括DApp的使用者。
  • private:只有合约本身可以调用该函数(在另一个函数中)。
  • internal:只有这份合同以及由此产生的所有合同才能称之为合同。
  • external:只有外部可以调用该函数,而合约内部不能调用。

solidity的三种修饰符

view: 可以自由调用,因为它只是“查看”区块链的状态而不改变它

pure: 也可以自由调用,既不读取也不写入区块链

payable:常常用于将代币发送给合约地址。

solidity的函数应有以下部分组成

function

你的函数名字(类型1 名字,类型2 名字,。。。,类型n 名字) 如果没有就什么都不填即可

可见度/访问权限,即public/private/internal/external 如果不写则系统默认为public并且警告

修饰符,即view/pure/payable 如果需要花费gas则不写

returns(类型1 名字,类型2 名字,。。。,类型n 名字)

布尔值bool

pragma solidity ^0.4.0;

contract helloworld 
    bool boola=true; //声明一个布尔类型的值,只用一个等号
    function booltesta() public view returns(bool)
        return boola;
    
    
    function booltestb(int a,int b) public pure returns(bool)
        return a==b;
    
    
    function boolteston(int a,int b) public pure returns(bool)
        return !(a==b);
    

  

与,或

即: &&  ||

通常运算符

即+,-,*,/,%以及特殊的符号**代表x的x次幂

位运算符

1.& 操作数之间转换成二进制之后每位进行与运算操作(同1取1)

2.| 操作数之间转换成二进制之后每位进行或运算操作(有1取1)

3.~ 操作数转换成二进制之后每位进行取反操作(直接相反)

4.^ 操作数之间转换成二进制之后每位进行异或操作(不同取1)

5.<<操作数转换成二进制之后每位向左移动x位的操作

6.>>操作数转换成二进制之后每位向右移动x位的操作

可变长度byte数组

声明方法

bytes arr = new bytes(length);

function arrlengthchange(uint a) public  arr1.length=a;  

String型

pragma solidity ^0.4.0;
contract stringtest1
    string testword='helloworld'; //68656c6c6f776f726c64为这串字符的16进制
    
    function stringlength() public view returns (uint)
        //return testword.length;  直接返回长度会报错
        return bytes(testword).length;  //强制类型转换之后可以
    
    
    function stringchange() public  
        //testword[0]='A'; 直接进行变更会报错
        bytes(testword)[0]='A'; //41为A的16进制值,强制类型转换之后可以修改
    
    
    function getname() public view returns(bytes)
        return bytes(testword); //查看16进制的string
    
    
    function stringchangetest() public view returns(byte)
        return bytes(testword)[0]; //查看第一位是否被修改
    
    

string类型是怎么存储数据的

英文字符(A-z)以及特殊字符(&*@#&%())等为一个字节
中文字符为3个字节 PS.solidity中文输入支持很差

pragma solidity ^0.4.0;

contract stringstoragetest
    string testword1='asldhlkasdh';
    string testword2='^*^*%*()*-/';
    string testword3='中文字符';
    string testword4='中文字符6666';
    
    function getest1() public view returns(uint)
        return bytes(testword1).length;
    
    function getest2() public view returns(uint)
        return bytes(testword2).length;
    
    function getest3() public view returns(uint)
        return bytes(testword3).length;
    
     function getest4() public view returns(uint)
        return bytes(testword4).length;
    

  

固定长度字节数组bytes的截断 

结论:位数足够则保留前面的,位数不够再后面加0

pragma solidity ^0.4.0;

contract bytetest1
    bytes10 testword=0x68656c6c6f776f726c64; //helloworld
    function transbytes1() public view returns(bytes1)
        return bytes1(testword);
    
    function transbytes2() public view returns(bytes5)
        return bytes5(testword);
    
    function transbytes3() public view returns(bytes12)
        return bytes12(testword);
       

固定长度数组入门

结论:
1.如果不赋值,那么默认所有位均为0
2.支持直接使用.length查看数组长度,但不支持对数组长度做修改
3.不支持通过.push添加数据

pragma solidity ^0.4.0;

contract fixedarrtest
    uint[3] testarr1;//不进行赋值直接声明数组
    uint[3] testarr2=[1,2,3];//声明数组并进行赋值
    
    function showarr1() public view returns(uint[3])
        return testarr1; //如果不赋值,那么默认所有位均为0
    
    
    function showarr2() public view returns(uint[3])
        return testarr2;
    
    
    function initarr() public
        testarr1[0]=12;//进行赋值操作
    
    
    function lengthtest() public view returns(uint)
        return testarr1.length;//solidity支持直接查看数组长度
    
    
    function changelengthtest() public view returns(uint)
        //testarr1.length=testarr1.length+3;//solidity不支持直接修改数组长度
    
    
    function pushtest() public view 
        //testarr2.push(2);//solidity不支持直接push数据到数组
    
    

可变长度数组入门

注意:与固定数组区别在于创建时是否定义长度
结论:
1.如果不初始化就无法单独赋值,但可以push或者改长度使有值之后再进行赋值。即必须修改的这一位不能为空 
2.支持直接使用.length查看数组长度,也支持对数组长度做修改。
将数组长度缩小则会从前往后保留
将数组长度增长则后面原本没有值的位会被默认置0
3.支持直接通过.push方法在末尾添加数值

pragma solidity ^0.4.0;

contract dynamicarrtest
    uint[] testarr=[1,2,3,4,5];
    
    function showarr() public view returns (uint[])
        return testarr;
    
    
    function changearr() public
        //for(uint i=0;i<5;i++)
            testarr[0] = 2;//如果不使0位有值,那么该函数无用
        //
    
    
    function lengthtest() public view returns(uint)
        return testarr.length;
    
    
    function changelengthtest1() public
        testarr.length=1;
    
    
    function changelengthtest2() public
        testarr.length=10;//变长之后后面默认置0
    
    
    function pushtest() public
        testarr.push(6);//可变数组支持此操作
    
    

 固定长度二维数组


结论
1.初始化时,uint[ i ] [ j ]表示有j个元素,每个元素包含i个值(和其他许多语言不同)
2.二维数组可以直接获取长度,既可以获得所有元素个数,也可以获得单独元素有多少值
3.对二维数组进行增删改等操作时时是与初始化时反过来的,即uint[ i ] [ j ]表示第i个元素的第j个值(和其他许多语言一样)
4.不支持push方法,也不支持对长度进行修改
原文链接:https://blog.csdn.net/weixin_45067603/article/details/105751748

 可变长度二维数组


结论
1.初始化时,uint[ i ] [ j ]表示有j个元素,每个元素包含i个值(和其他许多语言不同)
2.可变长度二维数组可以直接获取长度,既可以获得所有元素个数,也可以获得单独元素有多少值
3.对二维数组进行增删改等操作时时是与初始化时反过来的,即uint[ i ] [ j ]表示第i个元素的第j个值(和其他许多语言一样)
4.不支持push方法
5.支持对长度进行修改,修改后默认值为0
6.未声明的值不能直接赋值,修改长度之后默认有值才可以
 原文链接:https://blog.csdn.net/weixin_45067603/article/details/105751748

数组字面量


结论:
1.返回数组时,returns()括号里面的类型要与return的数据类型相同。
通过getarr1和getarr2可以知道,return之后的会默认最小数据类型,比如小于255的就默认为uint8类型, return [1,2,3]就默认uint8,return [256,2,3]就默认uint16等等,然而returns()里面的uint默认为uint256,所以报错,需注意
2.可以通过对return里面任意一个数值来进行强制转换来改变数据类型
3.可以直接接受参数来进行计算

pragma solidity ^0.4.0;

contract finaltest
    function getarr1() public view returns(uint[3])
    //    return [1,2,3];  报错,此处为uint8,而需要返回的是uint256
    
    function getarr2() public view returns(uint[3])
    //    return [256,2,3];报错,此处为uint16,而需要返回的是uint256
    
    function getarr3() public view returns(uint8[3])
        return [1,2,3];    //成功
    
    function getarr4() public view returns(uint16[3])
        return [256,2,3];  //成功
    
    function getarr5() public view returns(uint32[3])
        return [uint32(1),2,3]; //可以通过对return里面任意一个数值来
                                //进行强制转换来改变数据类型
    
    function getarr6(uint[] num) public view returns(uint)
        uint sum=0;
        for(uint i=0;i<num.length;i++)
            sum+=num[i]; //可以直接接受参数来进行计算,
           //参数需要按照格式来,此处就应该为[x1,x2,x3,x4,...,xn]
        
        return sum;
    

以上是关于智能合约学习笔记——solidity语法的主要内容,如果未能解决你的问题,请参考以下文章

智能合约实战 solidity 语法学习 10 [ BNB合约解读 ] 附代码

智能合约实战 solidity 语法学习 10 [ BNB合约解读 ] 附代码

智能合约实战 solidity 语法学习 10 [ BNB合约解读 ] 附代码

智能合约实战 solidity 语法学习 09 [ 访问函数getter 合约创建 合约对象 合约继承IS ]

智能合约实战 solidity 语法学习 08 [ 访问函数getter 合约创建 合约对象 合约继承IS ]

智能合约实战 solidity 语法学习 11 [ 以太坊发币 验证合约 体验下过程 ] 附代码