Solidity
起因是Xenc师傅给我截了张图,我日 居然看不懂 ,一搜才知道,之前学的版本有些老了.. 这次学下新一点的记录下
HelloWorld
pragma solidity ^0.6.0; // version
contract One{
// 状态变量
string name;
function setName() public{ // 必须要加权限修饰符了
name = "Muxue";
}
// view修饰的函数 表示访问状态变量, 但是不会修改, 不会消耗任何资源
function getName() public view returns(string memory){ // 返回字符串类型也需要加memory了
return name;
}
// pure修饰的函数 不不修饰也不读取状态变量 不会消耗任何资源
function pureTest() public pure returns(string memory){
return "test";
}
}
变量 常量 标识符 关键字
变量
type name = value;
标识符
需要命名的地方都是标识符
标识符命名规则
1. 字符, 数字, _, $组成
2. 不能以数字开头
3. 区分大小写
数据类型
基本类型
- 布尔(bool)
- 整形(int / uint)
- 地址(address)
- 定长字节数组
- 定长浮点(fixed / ufixed)
- 枚举类型(enum)
- 函数类型(function)
引用类型
- 数组(array) {不定长字节数组, 字符串}
- 结构体(struct)
- 映射(mapping)
区别
值类型一般都是值拷贝传递,但引用类型 有些是地址传递
数组
全局数组
全局的是storage
Array
几种声明 初始化方式
pragma solidity ^0.6.0;
contract ArrayTest{
uint[4] arr1; // 固定数组的声明
uint[] arr2; // 动态长度数组的声明
// 声明并初始化
uint[2] arr3 = [1,2];
uint[] arr4 = [1,4,12,4,2];
// 使用new
uint[] public arr5 = new uint[](3);
}
length和push pop的讲解
length: 长度 修改length 可改变动态长度数组的长度,但是0.6.0以上的版本都不能使用length修改数组长度
push:固定数组不能用 动态数组storage可以用 memory不能用
pop: 把push进来的数据 再顶出去
pragma solidity ^0.6.0;
contract ArrayTest{
uint[] arr4 = [1,4,12,4,2];
// 使用new
uint[] public arr5 = new uint[](3);
function push() public{
arr5.push(1);
}
// 尝试使用修改length
function changeLength() public{
// arr4.length = 12; // browser/Array/1.sol:19:9: TypeError: Member "length" is read-only and cannot be used to resize arrays. arr4.length = 12; // ^---------^
}
function Get() view public returns(uint[] memory){
return arr5;
}
function pop() public{
arr5.pop(); // 把push进来的再推出去
}
}
局部数组
局部的是memory
注意的一点是 新版本的 局部的都要加memory
,包括返回数组 返回值那里
pragma solidity ^0.6.0;
contract ArrayTest{
function test() public returns(uint[] memory){
uint[] memory arr8 = new uint[](3); // 使用new方法创建局部数组
arr8[0] = 1;
return arr8;
}
}
数据存储位置
storage
:是存在区块链 上的,全局变量
哪些数组类型可以使用storage
- 数组
- 结构体
- 映射
memory
:是存在内存上的,函数内的 局部的变量
栈
:值类型的局部变量存储在这里
calldata
:当函数为外部函数(external
),如果此函数的参数(非返回参数),则参数要求必须用calldata
,(教程里是这样说的,但是我用memory
也没报错)
对于存储型的数组(storage
), 可以放任意的元素类型
对于内存性的数组(memory
), 元素不可以是映射类型mapping
storage和memory的相互转换
pragma solidity ^0.6.0;
contract testFunc{
uint[] public a1Storage = [1,2,3];
function Geta1() public view returns(uint[] memory){
return a1Storage;
}
// sotrage -> memory 值传递 不会修改storage的值
function storageTomemory() public view{
uint[] memory b = a1Storage; // storage 赋值给 memory
b[0] = 100;
}
// memory -> storage 值传递
function memoryTostorage() public{
uint8[4] memory c = [2,4,1,5];
a1Storage = c;
c[0] = 255;
}
// sotrage -> storage 引用传递 修改一个 原数据也会修改数据
function storageTostorage() public{
uint[] storage m = a1Storage;
m[1] = 123;
}
// memory -> memory 引用传递
function memoryTomemory() public view returns(uint8[3] memory){
uint8[3] memory a = [1,2,3];
uint8[3] memory b = a;
b[1] = 12;
return a;
}
}
简单来说两个相同的都是引用传递,不同的都是值传递
字节数组
也分为
- 变长字节数组
- 定长字节数组
bytes
: 变成字节数组
bytes+num
:后面跟数字的是定长字节数组
pragma solidity ^0.6.0;
contract Test{
bytes b1; // 变长字节数组 bytes里是以16进制存储值的
bytes b2 = "abc\x22\x25"; // \x后面就代表是十六进制的值
bytes b3 = "ce\u8bd5";
function Get() public view returns( bytes memory){
return b3;
}
bytes4 bt = 0x74657374; // 定长字节数组
}
定长字节数组转变长字节数组
pragma solidity ^0.6.0;
contract Test{
bytes4 bt = 0x74657374; // 定长字节数组
// 把定长字节数组转换成变长字节数组
function To() public view returns(bytes memory){
bytes memory temp = new bytes(bt.length);
for(uint i=0;i<bt.length;i++){
temp[i] = bt[i];
}
return temp;
}
}
string
string没啥好说了吧 我擦..
字节转字符串
pragma solidity ^0.6.0;
contract Test{
bytes public name = "慕雪";
function EchoName() public view returns(string memory){
return string(name);
}
}
Solidity交易和内置对象
提到交易不得不提Gas
了哈,也就是燃料也叫手续费
Gas
又分为两个:
gas price
每个gas
的价格gas limit
限制gas
的最大值
需要给矿工预付的
gas
=gas price
*gas limit
消息:不修改合约状态,如带有pure
,view
等关键字的
账户和地址
分为外部账户
和合约账户
, 外部账户地址
, 外部合约地址
也就是外部账户和外部合约都各有地址
外部账户:我们钱包的一个用户 给你一个地址 就是一个外部账户
合约账户:我们部署一个合约 都会给我们一个地址
地址
address
- 20个字节,160位
- 值类型
address payable
0.5.0以后出的
只能使用它来进行转账
属性
balance
函数
专门用来做交易的
transfer
send
不会提示错误
demo code
pragma solidity ^0.6.0;
contract Test{
function echoAddress() public view returns(uint){
address _address = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
return uint(_address);
}
function getBalance(address _account) public view returns(uint){
return _account.balance;
// return address(this).balance; 返回当前合约账户余额
// this是指当前合约账户
}
function getThis() public view returns(address){
return address(this);
}
function testTransfer() public payable{
address(this).transfer(msg.value); // 前面是要给哪个地址转账的地址
}
function testTransfer2() public payable{
address payable _address = address(this); // 转账必须加payable
_address.transfer(1 ether); // 虽然这里写1了 但是我们还是需要在value那里设置1 ether
}
function testSend() public payable{
address payable _address = address(this);
_address.send(1 ether);
}
fallback() payable external{ // 回退函数
}
receive() payable external{
}
}
transfer
和send
的区别:
transfer假如value和设置的值不同 会报错。而send不会,但会返回一个false,但是错误了 还是会扣钱
Solidity单位和全局变量
具体可以看
https://solidity-cn.readthedocs.io/zh/develop/units-and-global-variables.html?highlight=全局#id3
区块链和交易属性
pragma solidity ^0.6.0;
contract One{
/*
block.blockhash(uint blockNumber) returns (bytes32):指定区块的区块哈希——仅可用于最新的 256 个区块且不包括当前区块;而 blocks 从 0.4.22 版本开始已经不推荐使用,
由 blockhash(uint blockNumber) 代替
block.number (uint): 当前区块号
msg.data (bytes): 完整的 calldata
msg.gas (uint): 剩余 gas - 自 0.4.21 版本开始已经不推荐使用,由 gesleft() 代替
msg.sig (bytes4): calldata 的前 4 字节(也就是函数标识符)
msg.value (uint): 随消息发送的 wei 的数量
tx.gasprice (uint): 交易的 gas 价格
tx.origin (address): 交易发起者(完全的调用链)
*/
function getBlockHash() public view returns(bytes32){
return blockhash(block.number-1); // block.number 当前区块号,得-1 要不然获取不到hash
}
// block.coinbase (address): 挖出当前区块的矿工地址
function getBlockCoinbase() public view returns(address){
return block.coinbase;
}
// block.difficulty (uint): 当前区块难度
function getBlockDifficulty() public view returns(uint){
return block.difficulty;
}
// block.gaslimit (uint): 当前区块 gas 限额
function getBlockLimit() public view returns(uint){
return block.gaslimit;
}
// block.timestamp (uint): 自 unix epoch 起始当前区块以秒计的时间戳
function getBlockTimestamp() public view returns(uint){
return block.timestamp;
}
// gasleft() returns (uint256):剩余的 gas
function getGasleft() public view returns(uint){
return gasleft();
}
// now (uint): 目前区块时间戳(block.timestamp)
function getTime() public view returns(uint){
return now;
}
// msg.sender (address): 消息发送者(当前调用)
function GetMsgsender() public view returns(address){
return msg.sender;
}
}
错误处理
最常用的应该就是require
了吧
pragma solidity ^0.6.0;
contract Two{
uint public money;
address master;
constructor() public{ // 构造函数
master = msg.sender;
}
function changeMoney() public {
require(msg.sender == master); // 如果不是 就直接报错了 不会往下面走
money += 5000;
}
}
函数
也就是function
,已经非常熟悉了
可见性
public
:内部 外部都可调用,状态变量和函数都可以用private
:私有的 只有内部可以调用,状态变量和函数都可以用internal
:只有内部可以调用,状态变量和函数都可以用external
:只有外部可以调用,只有函数可以用
可以明显的看出 被
private
和internal
修饰的函数 外部不可以调用
被external
修饰的内部不可以调用
如要调用可以加一个this.
function test3() public view returns(uint) {
return this.testExternal();
}
调用方式
external
:外部的 也就是外部点击函数名称那种方式internal
:内部的 就是一个合约方法调用另一个方法呗
可变性 可修改性
pure
:不用状态变量的时候view
:需要用到状态变量payable
:需要付款的时候constant
:和view一样的,0.5.0以后舍弃了
返回值
pragma solidity ^0.6.0;
contract Two{
// 返回多个参数
function test1() public pure returns(uint a,uint b){
return (2,4);
}
// 写参数名字
function test2() public pure returns(uint sum){
sum = 1+2; // 不需要加类型 因为上面我们定义了
// 不用reutrn 要是return,以return的值为结果
}
}
get
被public
修饰的变量,系统默认写了一个同名的函数,用来获取值,0.5.0以上的版本 不支持重写了
修改器 modifier
作用:可以修改函数的行为,控制函数的逻辑,代码重用
pragma solidity ^0.6.0;
contract TestModifier{
uint public a;
// create modifier
modifier myModifier(){
a=1;
_; // 函数会到这
a=10;
}
// call modifier
function callModifier() public myModifier{
a=9; // 最终结果为10
}
}
带参数的modifier
来个demo
看看modifier
的强大之处
pragma solidity ^0.6.0;
contract Two{
uint public level;
string public name;
string public sex;
modifier levelRequire(uint _level) {
require(level>=_level);
_;
}
function setLevel(uint _num) public{
level = _num;
}
function setName() public levelRequire(5){ // 相当于level需要大于或者等于五级才可以调用此方法
name = "Muxue"; // 如果modifier的_;后面还有 会在当前代码后面执行
}
function setSex() public levelRequire(7){
sex = "male";
}
}
多重modifier的执行顺序
这个是有点东西的
contract Three{
uint public a = 1;
modifier Test1{
a = 2; // 执行顺序1
_; // 把Test2带进来
a = 3; // 执行顺序5 也就是最后一个
}
modifier Test2{
a = 4; // 执行顺序2
_; // 把test函数带进来
a = 5; // 执行顺序4
}
function test() public Test1 Test2{
a = 6; // 执行顺序3
// a的结果为3
}
}
如果不信的 可以debug一步步的调着看
合约
构造函数
- 合约创建时自动调用,且只调用一次。每个合约只能有一个构造函数
- 构造函数一般是为状态变量初始化
constructor
关键字- 分为有参和无参
pragma solidity ^0.6.0;
contract TestNewContract{
uint age;
constructor(uint _age) public{
age = _age;
}
}
封装性
函数合约
修饰符(访问修饰符)
public
,private
,internal
,external
- 状态变量:
public
,private
,internal
- 函数:
public
,private
,internal
,external
- 状态变量:
继承
is
关键字
pragma solidity ^0.6.0;
contract Father{
address owner;
string name;
uint money = 100000000000000000000000;
constructor() public{
owner = msg.sender;
name = "Muxue";
}
function changeName(string memory _name ) public{
require(msg.sender == owner);
name = _name;
}
}
contract Son is Father{
function getMoney() public view returns(uint){
return money; // 继承的父亲的
}
}
父合约构造函数的传参
pragma solidity ^0.6.0;
contract Father{
uint private age;
constructor(uint _age) public{
age = _age;
}
}
contract Son is Father(46){ // 继承式
}
// 这两种方法不能同时使用
contract Son2 is Father{
constructor() Father(46) public{ // 修改风格式
}
}
多态
重写父类方法和状态变量
得在父类方法上加上virtual
关键字,子类重写的方法加上override
方法
pragma solidity ^0.6.0;
contract A{
function F() public pure virtual returns(string memory){ // 仅当函数被标记为 virtual 或在接口中定义 时,才可以覆盖
return "A";
}
}
contract B is A{
// 函数重写
function F() public pure override returns(string memory){ // override 代表可重写
return "B";
}
// 函数重载
function F(string memory _test) public pure returns(string memory){
return _test;
}
}
父类:
virtual
,子类:override
重写要保证,函数名,参数,返回值相同
重写状态变量
0.6.0
后 不可再重写状态变量
super
pragma solidity ^0.6.0;
contract A{
function F() public pure virtual returns(string memory){ // 仅当函数被标记为 virtual 或在接口中定义 时,才可以覆盖
return "A";
}
function eat() public pure virtual returns(string memory){
return "rou";
}
}
contract B is A{
// 函数重写
function F() public pure override returns(string memory){ // override 代表可重写
return "B";
}
// 函数重载
function F(string memory _test) public pure returns(string memory){
return _test;
}
function eat() public pure override returns(string memory){
return "yu";
}
function test() public view returns(string memory){
// return eat(); // 调用的是自己重写的那个方法
return super.eat(); // 调用父类eat方法
}
}
想要调用父类的,也可以用
父类名.方法名
super是内部调用
多重继承 重写父类方法
pragma solidity ^0.6.0;
contract Father{
function getMoney() public pure virtual returns(uint ){
return 10000;
}
}
contract Mother{
function getMoney() public pure virtual returns(uint ){
return 8000;
}
}
contract Son is Father,Mother{
function getMoney() public pure override(Father,Mother) returns(uint){ // 处理重名函数
return 18000;
}
}
这个在我编译时,一直在报错,但是我还不知道哪错了,我用
0.8.4
编译一次之后,没问题。最后再换回0.6的版本,照样可以编译成功
抽象合约
抽象合约
- 关键字:
abstract
- 抽象合约中,可以有抽象函数,非抽象函数
- 抽象函数 不需要实现函数体
- 抽象合约不能实例化
作用:起到约束,约束继承的抽象合约的子合约,必须重写抽象函数
pragma solidity ^0.6.0;
abstract contract Father{ // 抽象合约 关键字 abstract
function eat() public pure virtual; // 抽象函数
}
contract Son is Father{
// 必须重写函数
function eat() public pure override{
}
}
接口
- 关键字
interface
- 接口中所有的函数都是抽象函数,所有可以省略
virtual
关键字 - 接口函数的修饰符必须使用
external
- 其余限制:不能继承其他合约或接口,不能定义构造函数,不能定义状态变量,不能定义结构体
interface Father{ // 接口
function eat() external pure; // 没有{}
}
contract Son is Father{
function eat() public pure override{ // 重写eat方法
}
}
库
作用
- 代码重要性
- 将多个合约重复的代码提取到一个库中
- 不需要继承 节省gas
关键字及特性
libray
- 库中的函数不能修改状态变量
- 库不可以被销毁
- 不能定义状态变量
- 不可以继承其他元素,也不能被继承
- 库不能接受以太币
使用
有两种方式
库名.方法名
pragma solidity ^0.6.0;
library Search{ // 库定义
function indexOf(uint[] storage _data,uint _value) public view returns(uint){
for(uint i=0;i<_data.length;i++){
if(_data[i] == _value){
return i;
}
}
return uint(-1);
}
}
contract TestLibray{ // 第一种
uint[] data;
constructor() public{
data.push(1);
data.push(2);
data.push(3);
data.push(4);
}
// 调用库函数
function indexof(uint _value) public view returns(uint){
return Search.indexOf(data,_value);
}
}
using 库名 for 状态变量
pragma solidity ^0.6.0;
library Search{ // 库定义
function indexOf(uint[] storage self,uint _value) public view returns(uint){ // self也就是传过来的那个类型
for(uint i=0;i<self.length;i++){
if(self[i] == _value){
return i;
}
}
return uint(-1);
}
}
contract TestUsingFor{
using Search for uint[]; // 把search这个库绑定为uint[]类型
uint[] data;
constructor() public{
data.push(1);
data.push(2);
data.push(3);
data.push(4);
}
// 调用库函数
function indexof(uint _value) public view returns(uint){
return data.indexOf(_value); // 会自动把data传给第一个参数
}
}
合约销毁
合约生命周期
- 合约创建(new、sdk)
- 合约操作、使用(调用函数实现功能)
- 合约销毁(区块链上 关于合约的存储和代码都会被删除)
pragma solidity ^0.6.0;
library Search{ // 库定义
function indexOf(uint[] storage self,uint _value) public view returns(uint){ // self也就是传过来的那个类型
for(uint i=0;i<self.length;i++){
if(self[i] == _value){
return i;
}
}
return uint(-1);
}
}
contract TestUsingFor{
using Search for uint[]; // 把search这个库绑定为uint[]类型
uint[] data;
address owner;
constructor() public{
owner = msg.sender;
data.push(1);
data.push(2);
data.push(3);
data.push(4);
}
modifier onlyOwner() {
require(owner == msg.sender);
_;
}
// 调用库函数
function indexof(uint _value) public view returns(uint){
return data.indexOf(_value); // 会自动把data传给第一个参数
}
function kill() public onlyOwner{
selfdestruct(msg.sender); // 销毁合约
}
}
映射
引用数据类型
关键字及特性
mapping
- 存储一对数据,以
key-value
形式的 - key的数据类型是有要求的:动态数组,枚举,
struct
,mapping
都不可以;value基本上都可以 mapping
不能作为参数使用
pragma solidity ^0.6.0;
contract TestMapping{
mapping(uint=>string) public uintMapping; // key:uint value:string
mapping(address=>uint) public addressMapping;
mapping(string=>mapping(uint=>address)) public stringMapping;
constructor() public{
uintMapping[1] = "test";
addressMapping[0x5B38Da6a701c568545dCfcB03FcB875f56beddC4] = 1;
addressMapping[0x17F6AD8Ef982297579C203069C1DbfFE4348c372] = 2;
stringMapping["Muxue"][1] = 0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB; // 复杂的是[key][key] = value;
}
}
结构体
引用数据类型
关键字及特性
- 关键字
struct
- 大部分类型都可以,但是不可以包含自己本身
- 结构体作为函数的返回值类型使用时
- 结构体中有
mapping
类型,函数只能使用internal
,private
- 结构体中没有
mapping
类型,需要添加pragma experimental ABIEncoderV2;
- 结构体中有
contract TestStruct{
struct People{
uint id;
string name;
mapping(string=>uint) grade;
// People test;
}
People public pp;
constructor() public{
// People memory ppt = People(1,"Muxue"); // mapping类型不能直接赋值,因为是storage的
People memory ppt = People({name:"Muxue",id:1});
pp = ppt;
pp.grade["level"] = 1;
}
}
枚举
- 作用:增强代码的可读性
- 基本数据类型
- 关键字:
enum
- 书写时不能有
;
- 不能有
""
- 不能有中文
- 结果可以转为
uint
contract TestEnum{
enum Sex{Man,Woman}
function useEnum() public pure returns(Sex){
return Sex.Man;
}
function useenum() public pure returns(uint){
return uint(Sex.Woman);
}
}
事件与日志
- 合约中不能直接访问日志中的内容,可以通过sdk的方式进行交互 获取
- 日志通过事件来实现
- Solidity中,事件是操作触发行为,日志是触发事件后将数据记录在区块链中
事件
事件可以用来做操作记录,存储为日志。主要就是用来记录日志的
关键字:
event
:创建事件emit
:触发事件
pragma solidity ^0.6.0;
contract TestEvent{
event LogEvent(string _name,uint _age); // 创建一个事件
function emitEvent() public{ // 不能加 pure or view
emit LogEvent("Muxue",17); // 触发事件
}
}
事件的主题
- 将事件索引化
- 一个没主题的事件,无法搜索到
- 一个事件,最多有4个主题
- 事件签名
- 参数签名
经过Keccak-256
算法加密
简单来说:主题就是为了讲事件索引化,可查询到这个事件
pragma solidity ^0.6.0;
contract TestEvent{
event LogEvent(string indexed _name,uint indexed _age); // 创建一个事件
function emitEvent() public{ // 不能加 pure or view
emit LogEvent("Muxue",17); // 触发事件
}
}
异常
- 程序编译或运行中发生的错误 即异常
- 发生运行时异常,会将之前修改的状态全部还原(0.6.0版本可以选择)
- solidity异常
- 0.4.10之前,throw 条件不满足,中断运行,恢复修改的状态,耗光gas
- 0.4.10之后,throw废弃,
require()
,assert()
,revert()
代替原来的throw - 0.6.0版本,增加了
try catch
- 功能介绍
① 条件检查
-require()
:还原状态 返回gas
-assert()
:还原状态 耗光gas
② 引发异常
-throw
:已经废弃
-revert()
:与thorw的区别,允许返回错误原因,可以退回gas
③ 捕获/处理异常
-try..catch
:只适合于外部调用,
pragma solidity ^0.6.0;
contract TestException{
uint public data = 100;
function testThrow(uint _i) public pure{
//if(_u<10) throw;
}
function testRequire(uint _i) public{
data = 200; // 假如下面引发异常了,会把修改的状态还原回去
require(_i>10,"_i < 10");
}
function testAssert(uint _i) public{
data = 200; // 假如下面引发异常了,会把修改的状态还原回去
assert(_i>10);
}
function testRevert(uint _i) public returns(uint){
data = 200; // 假如下面引发异常了,会把修改的状态还原回去
if(_i<10){
revert("_i < 10");
}
return 12;
}
event successEvent();
event failEvent();
function testTry(uint _i) external returns(uint){
try this.testRevert( _i ) returns(uint _value){ // 某个函数可能会出现异常, 必须外部调用所以加this. 返回值需要定义一个变量
// 如果没有异常走这个代码块
emit successEvent();
return _value;
}catch{
// 如果有异常走这个代码块
emit failEvent();
}
}
}
Solidity汇编
https://learnblockchain.cn/article/675
概念
solidity汇编语言,采用自己独特的语言风格,使编写的代码可读性更高,且能够直接与EVM交互,而且可以减少gas的消耗】
分类
- 内联汇编
- 独立汇编
内联汇编的作用
- 可以直接嵌入到solidity的源码中使用
- 代码的可读性更高
- 直接访问栈
- 可以节省gas
字面量
- 字符常量:10进制 16进制
- 字符串:"",字符串字面量最多可以包含32个字符
作用域
{}
离开大括号就不能用了
特点
函数式操作码
pragma solidity ^0.6.0;
contract Test{
function TestSum(uint _n) public pure returns(uint _sum){
for(uint i=0;i<_n;i++){
_sum += i;
}
}
function TestAssembly(uint _n) public pure returns(uint){
assembly{
let sum := 0 // let定义变量 := 赋值
for{let i:=0} lt(i,_n) {i := add(i,1)}
{
sum := add(sum,i)
}
mstore(0x0,sum)
return(0x0,32)
}
}
}
汇编局部变量
访问外部变量
pragma solidity ^0.6.0;
contract Test2{
uint outerV;
function outerValue() public pure{
uint innerV;
assembly{
let y := innerV // 只能访问局部变量
let x := outerV // 不能访问状态变量
}
}
}
标签
标签已经废弃掉了
流程控制
solidity没有switch,但汇编中有
- 判断:
①. if 没有else
②. switch,做多选择 - 循环
只有for
pragma solidity ^0.6.0;
contract Test3{
function testIf(uint _v) public pure returns(bool flag){
assembly{
flag := true
if lt(_v,5){
flag := false
}
}
}
function testSwitch(uint _n) public pure returns(uint _num){
assembly{
let z:=_n
switch z
case 1{
_num := 1
}
case 2{
_num := 2
}
case 3{
_num := 3
}
default{
_num := 100
}
}
}
}
函数
pragma solidity ^0.6.0;
contract Test4{
function test() public pure{
assembly{
function sum(a,b) -> res{
}
// 调用
let xx := sum(1,4)
}
}
}
Solidity的更多相关文章
- 安装solidity遇见的问题——unused variable 'returned'
在编译安装solidity的过程中遇见了一个很奇怪的问题 webthree-umbrella/libethereum/libethereum/Executive.cpp: In member func ...
- Solidity教程系列1 - 类型介绍
现在的Solidity中文文档,要么翻译的太烂,要么太旧,决定重新翻译下,再加上代码事例讲解. 写在前面 Solidity是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果 ...
- 智能合约语言Solidity教程系列2 - 地址类型介绍
智能合约语言Solidity教程系列第二篇 - Solidity地址类型介绍. 写在前面 Solidity是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你 ...
- 智能合约语言 Solidity 教程系列3 - 函数类型
Solidity 教程系列第三篇 - Solidity 函数类型介绍. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你先看以 ...
- 智能合约语言 Solidity 教程系列4 - 数据存储位置分析
写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么 这部分的内容官方英文文档讲的不是很透,因此我在参考Soli ...
- 智能合约语言 Solidity 教程系列6 - 结构体与映射
写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么 本系列文章一部分是参考Solidity官方文档(当前最新版 ...
- 智能合约语言 Solidity 教程系列5 - 数组介绍
写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么 本文前半部分是参考Solidity官方文档(当前最新版本: ...
- Solidity 中文文档 —— 第一章:Introduction to Smart Contracts
第一章:智能合约简介 粗略地翻译了 Ethereum 的智能合约开发语言的文档:Solidity.欢迎转载,注明出处. 有任何问题请联系我,本人微信:wx1076869692,更多详情见文末. 我是 ...
- Solidity by Example详解 - Voting
Example地址:https://solidity.readthedocs.io/en/develop/solidity-by-example.html#voting Voting程序的功能: 这个 ...
- 智能合约语言 Solidity 教程系列8 - Solidity API
这是Solidity教程系列文章第8篇介绍Solidity API,它们主要表现为内置的特殊的变量及函数,存在于全局命名空间里. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应 ...
随机推荐
- 为什么要使用MongoDB?
1.Mongo与Mysql简单对比 关系型数据库-MySQL 1.在不同的引擎上有不同的存储方式. 2.查询语句是使用传统的sql语句,拥有较为成熟的体系,成熟度很高. 3.开源数据库的份额在不断增加 ...
- 温故知新,基于Nexus3和Docker搭建私有Docker Mirrors镜像库
前言 接着上一篇文章关于基于Nexus3和Docker搭建私有Nuget服务的探索,我们可以进一步利用Nexus3来创建一个私有的Docker镜像库满足内部需求. 仓库类型 hosted: 本地存储, ...
- 陋居寡闻,初探Github CLI For Windows,开启命令行撸铁时代
简介 gh is GitHub on the command line. It brings pull requests, issues, and other GitHub concepts to t ...
- 7、resync实时备份
sersync+rsync(增量,无差异备份),resync支持多线程,效果比inotify更好,配置思想和inotify很相似 7.1.在备份服务器上安装并配置rsync服务,实现nfs共享目录,可 ...
- 一、.Net Core 依赖注入详解及Autofac使用
.NET中的依赖注入实际上帮助我们解耦了我们的代码,是控制反转和依赖反转原则的具体实现. .Net Core的依赖注入的好处: 1. application 更稳定,容易维护和演化: 2. 实现细节的 ...
- idea debug无法启动 Error running 'Tomcat8': Unable to open debugger port (127.0.0.1:50168): java.net.SocketException "socket closed
在日志里显示在 event log 里的 Error running 'server_web': Address localhost:1099 is already in use 显示1099单口已被 ...
- Defense:SMB协议漏洞利用与控制CVE-2017-7494("永恒之蓝")攻防实验
漏洞描述 1. 服务器打开了文件/打印机共享端口445,让其能够在公网上访问 2. 共享文件拥有写入权限 3. 恶意攻击者需猜解Samba服务端共享目录的物理路径 Samba是在Linux和UNIX系 ...
- 输出数组中出现次数最多且值最大的数字----python
class Solution(): #求最多的数 def find_max(self,list): num = 0 for i in list: print(i) if list.count(i) & ...
- 使用oss来存取及优化图片资源
目录 1. 开通阿里云OSS,并创建存储空间 2. 图片上传及处理 2.1 图片上传 2.2 图片处理 前言: 在日常开发中,不免会遇到需要实现图片上传与展示的需求.比如一个文章发布系统,我们通常会开 ...
- window下玩转maven私服全流程,融合创建仓库、上传项目资源、下载私服资源
在互联网项目开发浪潮中,maven成为了项目管理依赖的重要工具,更多时候maven只作为拉取外部依赖的手段.但出于安全的考虑的,部门企业难免封装一些私有的工具类,或开源框架的二次开发封装,mave ...