Solidity

pragma solidity ^0.4.0;contract demo {string name = "chj";function getName() view public returns(string) {return name;}function setName(string _name) public {name = _name;}// 相当于仅是一个普通函数,不会改变值,单节约 gasfunction pureTest(string _name) pure public returns(string) {return _name;}// 事实上它支持 c 语言一样的逻辑判断符function judge() public returns(bool) {bool a = false;return a;}
}

不加 view 这些玩意会被系统认为调用外部资源

pragma solidity ^0.4.0;contract demo {// int 与 uint 都是 256 位int a = 12;uint b = 12;uint8 c = 12;function add(uint a, uint b) pure public returns(uint) {return a + b;}// 溢出的现象其实和 C 语言里的一样function flow() view public returns(uint) {return 256;}
}

bytes 是固定长度字节数组

bytes1 是八位,其他类推,通常用 16 进制表示

固定长度数组

pragma solidity ^0.4.0;contract demo {// 注意:固定长度数组是不能修改的,类似于 Python 的元祖// 0111 1010bytes1 num1 = 0x7a;// 0111 1010 0110 1000bytes2 num2 = 0x7a68;// 1function getLength1() returns(uint) {return num1.length;}// 2function getLength2() returns(uint) {return num2.length;}
}

动态长度数组

pragma solidity ^0.4.0;contract demo {bytes public name = new bytes(2);function InitName() {name[0] = 0x7a;name[1] = 0x68;}function getLength() view returns(uint) {return name.length;}function changeName() {name[0] = 0x88;}function changeLength() {name.length = 5;}// 动态添加数据function pushTest() {name.push(0x99);}
}

单引号和双引号没有区别

string 是特殊动态数组,utf8 类型

string 没有 Length 这个属性,因此不能获取它的长度

通过下标只能获取 Bytes 数据,不能将它强制转换为 string !!!

string 支持中文,但是注意,它是三个字节的

pragma solidity ^0.4.0;contract demo {string name = "zhangsan";function getLength() view returns(uint) {// 只能通过这种方式获取长度return bytes(name).length;}function getByte() returns(bytes1) {// 只能通过这种方式获取指定下标的数据return bytes(name)[0];}function getName() returns(bytes) {return bytes(name);}function setByte() {bytes(name)[0] = 'L';}
}s

固定长度字节数组的转换

pragma solidity ^0.4.0;contract demo {bytes3 name = 0x7a6865;// 0x7afunction getBytes1() returns(bytes1) {return bytes1(name);}// 0x7a68function getBytes2() returns(bytes2) {return bytes2(name);}// 0x7a6865function getBytes3() returns(bytes3) {return bytes3(name);}
}

固定长度数组转动态长度数组

pragma solidity ^0.4.0;contract demo {bytes3 name = 0x7a6865;function toDynamic() view returns(bytes) {// 之前没有 memory 是因为声明在函数体外部bytes memory newName = new bytes(name.length);// 索引必须是 uintfor (uint i = 0; i < name.length; i++) {newName[i] = name[i];}return newName;}
}

bytes 转 string(动态长度数组转化为 string)

pragma solidity ^0.4.0;contract demo {bytes name = new bytes(2);function Init() {name[0] = 0x7a;name[1] = 0x68;}function toString() view returns(string) {return string(name);}
}

固定长度数组转换为 string(事实上只能通过间接的手段得到)

pragma solidity ^0.4.0;contract demo {bytes2 name = 0x7a68;// 不能直接通过 string() 强制转化固定长度字节数组来得到 stringfunction toString() public returns(string) {bytes memory newName = new bytes(name.length);for (uint i = 0; i < name.length; i++) {newName[i] = name[i];}return string(newName);}
}

仅仅转换有效位(非0位)的数据为 string

pragma solidity ^0.4.0;contract demo {bytes2 name = 0x7a68;// 不能直接通过 string() 强制转化固定长度字节数组来得到 stringfunction toString() public returns(string) {bytes memory newName = new bytes(name.length);for (uint i = 0; i < name.length; i++) {newName[i] = name[i];}return string(newName);}bytes32 name2 = 0x7a68;function toString2() returns(string) {uint count = 0;for (uint i = 0; i < name2.length; i++) {bytes1 char = name2[i];if (char != 0) {count++;}}bytes memory newName = new bytes(count);for (uint j = 0; j < count; j++) {newName[j] = name2[j];}return string(newName);}
}
1. string 不能直接获取长度和内容,需要转换为 bytes、特殊字符,特别是中文占三个字节
2. 固定长度转化为 string ,必须将其转换为动态长度字节数组,再转换为 string

固定数组(就是普通概念上的数组)

pragma solidity ^0.4.0;contract demo {uint[5] arr = [1, 2, 3, 4, 5];function Init() {arr[0] = 100;arr[1] = 200;}// 如果定义时没有初始化那么默认全为 0function getArr() view returns(uint[5]) {return arr;}function getSum() view returns(uint) {uint count = 0;for (uint i = 0; i < arr.length; i++) {count += arr[i];}return count;}
}

动态长度数组

pragma solidity ^0.4.0;contract demo {uint[] grade = [1, 2, 3, 4, 5];// 没初始化的话默认长度为 0,没有任何内容function getGrade() view returns(uint[]) {return grade;}function getLength() view returns(uint) {return grade.length;}function getSum() view returns(uint) {uint sum = 0;for (uint i = 0; i < grade.length; i++)sum += grade[i];return sum;}// 小于长度则会舍弃后面,大于长度则在后面填充 0// 这个例子说明动态数组的长度是可以人为改变的function setLength() {grade.length = 1;}function pushContent() {grade.push(12);}
}

solidity 支持多维数组

不支持返回动态多维数组,仅支持动态一维数组

可对动态二维数组进行扩容,不过只是针对 arr[0] arr[1]… 这些

数组字面量最有用的地方是放在参数列表里

pragma solidity ^0.4.0;contract demo {// 默认推断原则:最小原则,所以推导返回类型是 uint8function getArrDefault() returns(uint8[3]) {// 这是数组字面量哦return [1, 2, 3];}// 传入数组字面量function getSum(uint[3] grade) returns(uint) {uint sum = 0;for (uint i = 0; i < grade.length; i++)sum += grade[i];return sum;}
}

比特币网络没有账户的概念,以太坊网络有

地址使用 uint160 存储,两者之间可以相互强制转化

地址之间可以相互比较,按照 uint160 的样子来判断

pragma solidity ^0.4.0;contract demo {address public account = 0xcD6a42782d230D7c13A74ddec5dD140e55499Df9;function getUint160() returns(uint160) {return uint160(account);}
}

合约有地址,所以它也是一个账户,因此可往里面存以太币

部署合约时可往合约里充钱

payable 这个关键字使我们可以往合约里充钱

pragma solidity ^0.4.0;contract demo {function pay() payable {}// 单位是 wei   1 eth = 10 ^ 8 weifunction getBalance() returns(uint) {return this.balance;}
}

任何转账操作都必须加上 payable 关键字

别人要给合约转账,合约里必须包含回滚函数(没有名字的函数,这个函数必须 payable)

pragma solidity ^0.4.0;contract demo {function pay() payable {}// 单位是 wei   1 eth = 10 ^ 8 weifunction getBalance() returns(uint) {return this.balance;}// 说明 this 代表的是合约地址,此函数返回合约地址function getThis() returns(address) {return this;}// 获取任意账户金额function getRandomBalance() returns(uint) {address account = 0xaE036c65C649172b43ef7156b009c6221B596B8b;return account.balance;}function transfer() payable {address to = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;// 合约调用者向 to 这个账户转账to.transfer(10 * 10 ** 18);}// 外部账户向合约转账function transferThis() payable {this.transfer(msg.value);}// 这是回滚函数function () payable {}
}

全局属性一些尝鲜

pragma solidity ^0.4.0;contract demo {// 返回合约调用者的地址function getMsgSender() returns(address) {return msg.sender;}// 返回当前块的挖矿困难度function getBlockDifficult() returns(uint) {return block.difficulty;}// 返回当前区块块号,代表合约部署时所在的区块function getBlockNumber() returns(uint) {return block.number;}// 返回当前块是被哪个矿工挖取的function getBlcokMiner() returns(address) {return block.coinbase;}
}

转账 msg.value 过多,那么多的钱会转账给合约,少的话退回调用者

send() 和 transfer() 非常危险,虽然作用一样

send() 返回值是 bool

mapping:一一对应的关系

pragma solidity ^0.4.0;contract demo {mapping(address => uint) idMap;mapping(uint => string) nameMap;uint sum = 0;function register(string name) {address account = msg.sender;sum++;idMap[account] = sum;nameMap[sum] = name;}function getIdByAddress(address are) returns(uint) {return idMap[are];}
}

函数返回值不能作为重载的依据,只要参数列表不一样就是重载

address 和 uint160 在函数重载中是不冲突的!!!,但在调用时会冲突,因为会在调用时解析为同一种类型!!!,所以最好不要这样子来冲突它们

pragma solidity ^0.4.0;contract demo {function fun(uint160 name) {}function fun(string name) {}
}

sol 支持函数命名参数

函数不指定修饰符时默认为 public

修饰符 描述
public 任何人都可调用该函数,包括 Dapp 的使用者
private 只有合约本身可以调用该函数
internal 只有这份合同以及由此产生的所有合同才能称之为合同
external 只有外部可以调用该函数,而合约内部不能调用

重载

pragma solidity ^0.4.0;contract demo {uint public age;string public name;function setParam(uint _age, string _name) {age = _age;name = _name;}function test1() {setParam(10, "zhangsan");}function test2() {setParam({_age: 10, _name: "zhangsan"});}
}

函数返回值

pragma solidity ^0.4.0;contract demo {function returnTest1() returns(uint mul) {mul = 100;}// 返回 10,以 a 为准function returnTest2() returns(uint mul) {mul = 100;uint a = 10;return a;}/*多个返回值*/function returnTest3(uint a, uint b) returns(uint add, uint mul) {add = a + b;mul = a * b;}function returnTest4(uint a, uint b) returns(uint add, uint mul) {return (a + b, a * b);}function returnTest5() returns(uint add, uint mul) {return (10, 20);}
}

全局变量和局部变量的知识和 C语言 一样

合约是可以调用外部合约的

合约继承和一些操作

pragma solidity ^0.4.0;contract demo {// 但它可被 new 出来的合约对象直接调用function dahan() external pure returns(string) {return "dahan";}function dahanTest() public view {// external 修饰的方法只能通过这种方法调用// 并且也不能在继承合约内部使用this.dahan();}
}// is 关键字实现继承
contract son is demo {function hello() returns(string) {return "hello";}
}contract Test {demo d = new demo();function test() returns(string) {return d.dahan();}
}

关于赋值和参数传递这件事情,和C语言都是一样的操作–值传递

在 4.0 版本中 constant 和 view 功能一样,但在 5.0 已被废弃

全局变量加上 constant 后就不能被修改

构造函数和合约同名(事实上这已经过时了),传参是在部署合约时的事情

pragma solidity ^0.4.0;contract demo {uint public a;uint public b;function demo(uint _a, uint _b) {a = _a;b = _b;}
}// constructor 是新潮的形式
contract gouzao {constructor() {}
}

modifier 使用尝鲜,它可是能传参的哦,而且还支持多个 modifier

pragma solidity ^0.4.0;contract demo {address public owner;constructor() {owner = msg.sender;}modifier OnlyOwner() {require(msg.sender == owner);// 动态添加_;}uint num = 0;// 仅合约所有者能调用// 先执行 require(msg.sender == owner); 判断调用者是否为合约拥有者,不是的话就回滚并报错function changeNum() OnlyOwner {num = 100;}modifier Judge(uint judge) {require(num > judge);_;}function testJudge() Judge(12) {}/*多重 modifier*/uint public a = 0;modifier mod1 {a = 1;// test() 的代码装载在这里_;a = 2;}modifier mod2 {a = 3;_;a = 4;}function test() mod1 {a = 100;}/*这是 mod1 的 _ 实际上装载的是 mod2,mod2 装载的才是函数内部的代码a = 1a = 3a = 100a = 4a = 2*/function test2() mod1 mod2 {a = 100;}
}

继承

pragma solidity ^0.4.0;contract demo {uint public money = 100;function dahan() public returns(string) {return "dahan";}
}contract son is demo {function getMoney() returns(uint) {return money;}function test() {dahan();}
}

sol 支持连续继承,public 对象同理支持在继承中使用

如果不加任何修饰符,默认为 public ,即可被继承

internal 能被继承

private 修饰符子合约不能访问

externa 不存在这个修饰符修饰变量

view 修饰:只读取,不改变

pure 修饰:不读取也不改变

public internal externall 修饰符可以被继承

private 修饰符只能被合约独立使用,不能被继承

internal:可以在内部被调用,不能在外部被调用,可以被继承(想想 new)

external:不能在内部被调用,只能在外部调用,可以被继承,如果强行调用,通过“地址”(想想new)

public 修饰变量默认生产 get 方法,这个方法默认是 external 权限的,不能在合约内部调用,实在要调用要通过“地址this”

pragma solidity ^0.4.0;contract demo {uint public money = 100;function dahan() public returns(string) {return "dahan";}
}contract son is demo {function getMoney() returns(uint) {return money;}function test() {dahan();}
}

疯狂 map

pragma solidity ^0.4.0;contract demo {mapping(uint => mapping(uint => mapping(uint => string))) public map;function test() {map[0][1][2] = "zhangsan";}
}
pragma solidity ^0.4.0;contract demo {uint money = 100;
}contract son is demo {uint money = 99999999;// 当子合约与父合约有相同属性时,子合约属性会覆盖掉父合约的属性// 函数同理// 返回 99999999function getMoney() returns(uint) {return money;}
}

sol 支持多重继承

多重继承里继承的合约有重复,那么按照写在最后的为准

pragma solidity ^0.4.0;contract demo {uint money = 100;
}contract demo2 {uint money = 200;
}contract son is demo, demo2 {// 200,因为 demo2 写在最后面// 调用函数时同理function getMoney() returns(uint) {return money;}
}

合约销毁

pragma solidity ^0.4.0;contract demo {function get() returns(string) {return "hello world";}// 调用后就不能与合约进行交互function kill() {selfdestruct(this);}
}

普通的类型是值传递,但可变数组和结构体这些可不是

pragma solidity ^0.4.0;contract demo {uint[] arrx;function test(uint[] arry) {// 将内存的 arry 拷贝给区块链上的 arrx 变量arrx = arry;// 当我们在函数体内部定义了一个可变长度的数组时,实际上,它默认的类型是 storage// 它指向了区块链上的 arrx// 所以当修改 arrz 时,实际操作了 arrxuint[] arrz = arrx;// 通过指针实际上修改了区块链上 arrx 的值arrz.length = 100;}
}

memory 不能强制赋给 storage 指针

结构体内部不能包含自己本身(类似与链表),但它可以包含自身类型的可变长度数组

mapping 是一个非常特殊的类型,如果结构体字段有这个类型,那么初始化时可以不包含它

pragma solidity ^0.4.0;contract demo {struct student {uint grade;string name;}function init() returns(uint, string) {student memory s = student(100, "hello world");return (s.grade, s.name);}function init2() returns(uint, string) {student memory s = student({grade: 100, name: "zhangsan"});return (s.grade, s.name);}/*mapping 是非常特殊的类型memory 类型是不能直接操作 mapping 类型,只能简介通过 storage 指针来操作(如下面的 meimei)*/struct student2 {uint grade;string name;mapping(uint => string) map;}// 默认为 storage 类型,只能通过这个类型操作 mappingstudent2 meimei;function init3() returns(uint, string) {student2 memory s = student2(100, "zhangsan");meimei = s;meimei.map[0] = "hello world";return (s.grade, s.name);}/*函数的参数是 storage 类型的话,必须保证函数是 internal 属性修饰事实上所有函数的形参默认都是 memory如果参数用 storage 修饰,即 stduent storage s 的话,传进去的就不是副本,而是引用*/function test(student storage s) internal {// 这样子操作的话只会是拷贝哦student memory meimei = s;}/*memory 类型之间的传递,由于 sol 的优化,是通过指针来传递的(这非常重要)*/
}

枚举

pragma solidity ^0.4.0;contract demo {/*girl: 0boy: 1*/enum people {girl,boy}// 0function getGirl() view returns(people) {return people.girl;}// 1function getBoy() view returns(people) {return people.boy;}function test() {people robot = people.girl;}
}

Solidity 教程相关推荐

  1. 智能合约语言 Solidity 教程系列9 - 错误处理

    这是Solidity教程系列文章第9篇介绍Solidity 错误处理. Solidity系列完整的文章列表请查看分类-Solidity. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文 ...

  2. 智能合约语言 Solidity 教程系列8 - Solidity API

    这是Solidity教程系列文章第8篇介绍Solidity API,它们主要表现为内置的特殊的变量及函数,存在于全局命名空间里. <!-- more --> 写在前面 Solidity 是 ...

  3. 智能合约语言 Solidity 教程系列9 - 错误处理 1

    什么是错误处理 错误处理是指在程序发生错误时的处理方式,Solidity处理错误和我们常见的语言不一样,Solidity是通过回退状态的方式来处理错误.发生异常时会撤消当前调用(及其所有子调用)所改变 ...

  4. Solidity API

    这是Solidity教程系列文章第8篇介绍Solidity API,它们主要表现为内置的特殊的变量及函数,存在于全局命名空间里. Solidity 系列完整的文章列表请查看分类-Solidity. 写 ...

  5. 基于chatgpt的社区教育网站开发教程

    文章目录 社区教育网站教程 网站架构 技术栈 实现步骤与自主学习资源 社区教育网站教程 社区教育网站是一个基于Web3.0和教育4.0理念的在线教育平台,它旨在为用户提供一个去中心化.开放.自主和协作 ...

  6. solidity开发讲解

    solidity 教程链接 1. 源文件结构 源文件中可以包含任意多个 合约定义 .导入源文件指令 . 版本标识 指令. 结构体 . 枚举 和 函数 定义. SPDX许可标识 SPDX:The Sof ...

  7. c语言中结构体数组的引用,【C语言入门教程】7.2 结构体数组的定义和引用

    7.2 结构体数组的定义和引用 当需要使用大量的结构体变量时,可使用结构体定义数组,该数组包含与结构体相同的数据结构所组成的连续存储空间.如下例所示: struct student stu_a[50] ...

  8. mysql的安装和启动_mysql安装和启动

    Sublime中Markdown的安装与使用 摘要:为什么用它,因为用markdown写出来的东西很好看,展示下:isujin.com(差不多就是这个样子啦,好看不?) 网页版Markdown编辑器有 ...

  9. 实现一个可管理、增发、兑换、冻结等高级功能的代币

    本文首发于深入浅出区块链社区 原文链接:实现一个可管理.增发.兑换.冻结等高级功能的代币 本文主要介绍代币高级功能的实现: 代币管理.代币增发.代币兑换.资产冻结.Gas自动补充. 写在前面 在上一篇 ...

  10. 使用以太坊发布属于你自己的虚拟代币

    使用以太坊发布属于你自己的虚拟代币 2018年04月22日 10:54:32 阅读数:98 本文从技术角度详细介绍如何基于以太坊ERC20创建代币的流程. 关于以太坊的编程语言Solidity的教学我 ...

最新文章

  1. Java基础Switch和循环控制
  2. lol服务器显示未知错误,运行英雄联盟出现未知错误的处理方法
  3. 工具dumpbin.exe
  4. IT旅途——程序员面试经验分享
  5. 逻辑短路 java_逻辑操作符中的短路现象
  6. 2015蓝桥杯省赛---java---C---3(无穷分数)
  7. oracle数据库连接数超了,oracle数据库当前和最大连接数
  8. js 判断 浏览器 是否为 微信 浏览器
  9. Java学习的5个阶段,助大家步步攀升
  10. sat2 计算机科目,2019-2020年SAT2考试时间及Top100大学要求
  11. 马斯克发推:8月特斯拉Autopilot实现完全自动驾驶
  12. 切换IP软件,切换电脑手机IP如此简单
  13. 计算机桌面ico图标,.ico格式图标制作转换教程及DIY桌面图标的方法
  14. Retina屏下的图片优化
  15. 计算机老师教师节祝福语,送给老师教师节祝福语
  16. 浮点数开方运算的快速计算
  17. java获取连续日期天数
  18. html+css设置背景图移动以及人物行走的动画效果
  19. softmax,softmax loss和交叉熵的关系
  20. 总结定时器设计方法_超实用!网站导航栏设计方法总结

热门文章

  1. 解决电信网络Echarts官网打不开的问题
  2. pe卸载win10更新补丁_Win10怎么卸载有问题更新补丁|Win10卸载更新补丁
  3. Spartan-6 FPGA 如何使用ISE下载程序
  4. 最新麻瓜编程实用主义学Python分享
  5. Windows8.1-KB2999226-x64安装提示此更新不适用你的计算机
  6. chrome浏览器js 导出excel
  7. ae去闪插件deflicker使用_Ae/Pr视频去闪烁插件REVisionFX DEFlicker v1.7.1 Win大众脸已注册...
  8. Linux版MySQL下载教程
  9. 电脑无损分区大小调整
  10. 联发科MT2503芯片资料MT2503原理图