起因是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. 区分大小写

数据类型

基本类型

  1. 布尔(bool)
  2. 整形(int / uint)
  3. 地址(address)
  4. 定长字节数组
  5. 定长浮点(fixed / ufixed)
  6. 枚举类型(enum)
  7. 函数类型(function)

引用类型

  1. 数组(array) {不定长字节数组, 字符串}
  2. 结构体(struct)
  3. 映射(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{ }
}

transfersend的区别:

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:只有外部可以调用,只有函数可以用



可以明显的看出 被privateinternal修饰的函数 外部不可以调用

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

封装性

  1. 函数合约

  2. 修饰符(访问修饰符)

    • public, private , internal, external

      • 状态变量:publicprivate, internal
      • 函数:publicprivate, 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传给第一个参数
}
}

合约销毁

合约生命周期

  1. 合约创建(new、sdk)
  2. 合约操作、使用(调用函数实现功能)
  3. 合约销毁(区块链上 关于合约的存储和代码都会被删除)
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); // 销毁合约
} }

映射

引用数据类型

关键字及特性

  1. mapping
  2. 存储一对数据,以key-value形式的
  3. key的数据类型是有要求的:动态数组,枚举,structmapping都不可以;value基本上都可以
  4. 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; }
}

结构体

引用数据类型

关键字及特性

  1. 关键字struct
  2. 大部分类型都可以,但是不可以包含自己本身
  3. 结构体作为函数的返回值类型使用时
    • 结构体中有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;
} }

枚举

  1. 作用:增强代码的可读性
  2. 基本数据类型
  3. 关键字:enum
  4. 书写时不能有;
  5. 不能有""
  6. 不能有中文
  7. 结果可以转为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);
}
}

事件与日志

  1. 合约中不能直接访问日志中的内容,可以通过sdk的方式进行交互 获取
  2. 日志通过事件来实现
  3. 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); // 触发事件
}
}

事件的主题

  1. 将事件索引化
  2. 一个没主题的事件,无法搜索到
  3. 一个事件,最多有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); // 触发事件
}
}

异常

  1. 程序编译或运行中发生的错误 即异常
  2. 发生运行时异常,会将之前修改的状态全部还原(0.6.0版本可以选择)
  3. solidity异常
    • 0.4.10之前,throw 条件不满足,中断运行,恢复修改的状态,耗光gas
    • 0.4.10之后,throw废弃,require() ,assert(), revert()代替原来的throw
    • 0.6.0版本,增加了try catch
  4. 功能介绍

    条件检查

    - 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的消耗】

分类

  • 内联汇编
  • 独立汇编

内联汇编的作用

  1. 可以直接嵌入到solidity的源码中使用
  2. 代码的可读性更高
  3. 直接访问栈
  4. 可以节省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的更多相关文章

  1. 安装solidity遇见的问题——unused variable 'returned'

    在编译安装solidity的过程中遇见了一个很奇怪的问题 webthree-umbrella/libethereum/libethereum/Executive.cpp: In member func ...

  2. Solidity教程系列1 - 类型介绍

    现在的Solidity中文文档,要么翻译的太烂,要么太旧,决定重新翻译下,再加上代码事例讲解. 写在前面 Solidity是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果 ...

  3. 智能合约语言Solidity教程系列2 - 地址类型介绍

    智能合约语言Solidity教程系列第二篇 - Solidity地址类型介绍. 写在前面 Solidity是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你 ...

  4. 智能合约语言 Solidity 教程系列3 - 函数类型

    Solidity 教程系列第三篇 - Solidity 函数类型介绍. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你先看以 ...

  5. 智能合约语言 Solidity 教程系列4 - 数据存储位置分析

    写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么 这部分的内容官方英文文档讲的不是很透,因此我在参考Soli ...

  6. 智能合约语言 Solidity 教程系列6 - 结构体与映射

    写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么 本系列文章一部分是参考Solidity官方文档(当前最新版 ...

  7. 智能合约语言 Solidity 教程系列5 - 数组介绍

    写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么 本文前半部分是参考Solidity官方文档(当前最新版本: ...

  8. Solidity 中文文档 —— 第一章:Introduction to Smart Contracts

    第一章:智能合约简介 粗略地翻译了 Ethereum 的智能合约开发语言的文档:Solidity.欢迎转载,注明出处. 有任何问题请联系我,本人微信:wx1076869692,更多详情见文末. 我是 ...

  9. Solidity by Example详解 - Voting

    Example地址:https://solidity.readthedocs.io/en/develop/solidity-by-example.html#voting Voting程序的功能: 这个 ...

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

    这是Solidity教程系列文章第8篇介绍Solidity API,它们主要表现为内置的特殊的变量及函数,存在于全局命名空间里. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应 ...

随机推荐

  1. 为什么要使用MongoDB?

    1.Mongo与Mysql简单对比 关系型数据库-MySQL 1.在不同的引擎上有不同的存储方式. 2.查询语句是使用传统的sql语句,拥有较为成熟的体系,成熟度很高. 3.开源数据库的份额在不断增加 ...

  2. 温故知新,基于Nexus3和Docker搭建私有Docker Mirrors镜像库

    前言 接着上一篇文章关于基于Nexus3和Docker搭建私有Nuget服务的探索,我们可以进一步利用Nexus3来创建一个私有的Docker镜像库满足内部需求. 仓库类型 hosted: 本地存储, ...

  3. 陋居寡闻,初探Github CLI For Windows,开启命令行撸铁时代

    简介 gh is GitHub on the command line. It brings pull requests, issues, and other GitHub concepts to t ...

  4. 7、resync实时备份

    sersync+rsync(增量,无差异备份),resync支持多线程,效果比inotify更好,配置思想和inotify很相似 7.1.在备份服务器上安装并配置rsync服务,实现nfs共享目录,可 ...

  5. 一、.Net Core 依赖注入详解及Autofac使用

    .NET中的依赖注入实际上帮助我们解耦了我们的代码,是控制反转和依赖反转原则的具体实现. .Net Core的依赖注入的好处: 1. application 更稳定,容易维护和演化: 2. 实现细节的 ...

  6. 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单口已被 ...

  7. Defense:SMB协议漏洞利用与控制CVE-2017-7494("永恒之蓝")攻防实验

    漏洞描述 1. 服务器打开了文件/打印机共享端口445,让其能够在公网上访问 2. 共享文件拥有写入权限 3. 恶意攻击者需猜解Samba服务端共享目录的物理路径 Samba是在Linux和UNIX系 ...

  8. 输出数组中出现次数最多且值最大的数字----python

    class Solution(): #求最多的数 def find_max(self,list): num = 0 for i in list: print(i) if list.count(i) & ...

  9. 使用oss来存取及优化图片资源

    目录 1. 开通阿里云OSS,并创建存储空间 2. 图片上传及处理 2.1 图片上传 2.2 图片处理 前言: 在日常开发中,不免会遇到需要实现图片上传与展示的需求.比如一个文章发布系统,我们通常会开 ...

  10. window下玩转maven私服全流程,融合创建仓库、上传项目资源、下载私服资源

    ​ 在互联网项目开发浪潮中,maven成为了项目管理依赖的重要工具,更多时候maven只作为拉取外部依赖的手段.但出于安全的考虑的,部门企业难免封装一些私有的工具类,或开源框架的二次开发封装,mave ...