区块链-智能合约Solidity编程

news/2024/10/19 15:38:32/

文章目录

  • 一、ubuntu安装
  • 二、FISCO BCOS安装
  • 五、 WeBASE安装
    • 5.1 WeBASE简介
    • 5.2 节点前置服务搭建
    • 5.3 调用HelloWorld合约
  • 七、Solidity极简入门
    • 7.1. 值类型
    • 7.2. 变量数据存储和作用域
    • 7.3. 函数
    • 7.4 控制流
    • 7.5 数组&映射
    • 7.6 结构体
    • 7.7 修饰符
    • 7.8 事件
    • 7.9 面向对象
    • 7.10 抽象合约
    • 7.11接口合约
    • 7.12 库合约
  • 九、案例
    • 9.1 权限控制合约
    • 9.2 投票合约
    • 9.3 拍卖合约


一、ubuntu安装

# ubuntu系统下载
https://releases.ubuntu.com/18.04.6/
##虚拟机安装好后 root密码用普通用户登录
#sudo passwd初始化

在这里插入图片描述

# 替换镜像源
mv /etc/apt/sources.list /etc/apt/sources.list.backup
# 新建源 参考国内源文档
https://developer.aliyun.com/mirror/ubuntu/
# 操作如下
vim /etc/apt/aources.list
.........
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse 
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
.........
# 更新apt源表
apt update
apt upgrade

二、FISCO BCOS安装

FISCO BCOS 2.0 技术文档
https://fisco-bcos-documentation.readthedocs.io/zh-cn/latest/

环境安装:

# 不安装,则start.all会报错:Cannot open file:../crypto/rand/randfile
apt install -y openssl curl# 不安装 bash console/start.sh 会报错Failed to connect to all the nodes!
apt install -y default-jdk

安装包下载

#借梯子下载好相关的包
#build_chain.sh
https://github.com/FISCO-BCOS/FISCO-BCOS/releases/download/v2.11.0/build_chain.sh
# fisco-bcos build_chain.sh脚本中需要的二进制文件
https://github.com/FISCO-BCOS/FISCO-BCOS/releases/download/v2.11.0/fisco-bcos.tar.gz 
# console  download_console.sh 脚本中需要的文件
https://github.com/FISCO-BCOS/console/releases/download/v2.9.2/console.tar.gz

执行

# 安装
bash build_chain.sh -l 127.0.0.1:3 -e ./fisco-bcos
bash nodes/127.0.0.1/start_all.sh
# 查看
tail -f nodes/127.0.0.1/node0/log/log_2024092819.29.log |grep +++
tail -f nodes/127.0.0.1/node0/log/log_2024092819.29.log |grep connect# 控制台安装
tar -xf console.tar.gz
cp -r nodes/127.0.0.1/sdk/* console/conf/
cp -n console/conf/config-example.toml console/conf/config.toml
bash console/start.sh

五、 WeBASE安装

5.1 WeBASE简介

WeBASE(WeBank Blockchain Application Software Extension)是在区块链应用和FISCO-BCOS节点之间搭建的一套通用组件。围绕交易、合约、密钥管理,数据,可视化管理来设计各个模块,开发者可以根据业务所需,选择子系统进行部署。WeBASE屏蔽了区块链底层的复杂度,降低开发者的门槛,大幅提高区块链应用的开发效率,包含节点前置、节点管理、交易链路,数据导出,Web管理平台等子系统

5.2 节点前置服务搭建

vim ~/.bashrc
# 增加 JAVA_HOME 提示报错:java_home不存在
readlink -f $(which java)
.........
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
.........
source ~/.bashrc
echo $JAVA_HOME## webase-front.zip
https://osp-1257653870.cos.ap-guangzhou.myqcloud.com/WeBASE/releases/download/v1.5.5/webase-front.zip
unzip webase-front.zip
cd webase-front
cp ../nodes/127.0.0.1/sdk/* ./conf/
bash start.sh
bash status.sh
tail -f log/WeBASE-Front.log |grep success

http://localhost:5002/WeBASE-Front
在这里插入图片描述

也可以使用在线开发环境:
https://remix.ethereum.org/
在这里插入图片描述

5.3 调用HelloWorld合约

HelloWorld合约已经内置于控制台中,位于控制台目录contracts/solidity/HelloWorld.sol

pragma solidity>=0.4.24 <0.6.11;contract HelloWorld {string name;constructor() public {name = "Hello, World!";}function get() public view returns (string memory) {return name;}function set(string memory n) public {name = n;}
}
# 在控制台输入以下指令 部署成功则返回合约地址
[group:1]> deploy HelloWorld
# 调用get接口获取name变量 此处的合约地址是deploy指令返回的地址
[group:1]>call HelloWorld 0xa2bf59b4ca0952464b393947990eaa2e25870587 get
# 调用set设置name
[group:1]>call HelloWorld 0xa2bf59b4ca0952464b393947990eaa2e25870587 set "Hello, FISCO BCOS"

七、Solidity极简入门

Solidity是一门为实现智能合约而创建的面向对象的高级编程语言。 智能合约是管理以太坊中账户行为的程序。

Solidity 是一种面向以太坊虚拟机 (EVM) 的 带花括号的语言。 它受 C++,Python 和 JavaScript 的影响。您可以在 语言的影响因素 部分中找到更多有关 Solidity 受哪些语言启发的细节

7.1. 值类型

pragma solidity 0.6.10;contract ValueType {string  _string = "Hello Web3!";//布尔型bool  _bool = true;bool  _bool1 = !_bool;   // 取非bool  _bool2 = _bool && _bool1; //与bool  _bool3 = _bool || _bool1; //或bool  _bool4 = _bool == _bool1; //相等 bool  _bool5 = _bool != _bool1; //不相等//整数int _int = -1; // 整数uint  _uint = 1; // 正整数 uint=uint256uint  _num = 17;uint  _num1 = _num +2; // 加uint  _num2 = _num/3;  //除取整uint  _num3 = _num%5;  //取余uint  _num4 = _num*3;  //乘uint  _num5 = _num**2; //指数//地址address public _address = 0xfBbe31cb73D23Ae79771157c2Bb7C45Cce7C1E18;// 固定长度 Arrayuint[8] _array1;address[100] _array3;//定长字节数组//长度为1的字节类型bytes1 A = 0x01;//byte是bytes1的别名byte B =0x01;//长度为2的字节类型bytes2 C= 0xaabb;bytes1[32] _array2;bytes32 _bytes32 = "hellowold";bytes1  _bytes1 = _bytes32[0];// 可变长度 Arrayuint[] array4;address[] array6;//bytes比较特殊,是数组,不用加[]//可以使用bytes或bytes1[]。bytes 比 bytes1[] 省gasbytes1[] array5;bytes array7;  // 初始值 //如果你在变量声明后添加了public关键字,//那么这个变量将自动生成一个与变量名相同的函数,//该函数用于获取这个变量的值bool public _bool_c; // falsestring public _string_c; // ""int public _int_c; // 0uint public _uint_c; // 0address public _address_c; // 0x0000000000000000000000000000000000000000 (或 address(0))//枚举 类比boolenum ActionSet { Buy, Hold, Sell}ActionSet public _enum_c; // 默认值第1个内容Buy的索引0function fi() internal{} // internal空白函数function fe() external{} // external空白函数  
}

常量

pragma solidity 0.6.10;
contract ConstantTest {// constant变量必须在声明的时候初始化,之后不能改变uint256 constant CONSTANT_NUM = 10;string constant CONSTANT_STRING = "0xAA";bytes constant CONSTANT_BYTES = "WTF";address constant CONSTANT_ADDRESS = 0x0000000000000000000000000000000000000000;// immutable变量可以在constructor里初始化,之后不能改变uint256 public immutable IMMUTABLE_NUM = 9999999999;address public immutable IMMUTABLE_ADDRESS;uint256 public immutable IMMUTABLE_TEST;// 利用constructor初始化immutable变量,因此可以利用constructor() public {IMMUTABLE_ADDRESS = address(this);IMMUTABLE_TEST = test();}//利用了test()函数给IMMUTABLE_TEST初始化为9function test() public pure returns(uint256){uint256 what = 9;return(what);}   
}

枚举和结构体

//可以理解bool的扩展。
pragma solidity 0.6.10;contract Enum {enum Status{None,running,stopping,spendding}    struct Order{address buyer;Status status;}Status status = Status.running;//枚举可以显式地和 uint 相互转换function get() external returns(Status) {return status;//1}function set(Status _status) external{status = _status;}
}

7.2. 变量数据存储和作用域

引用类型(Reference Type):包括数组(array)和结构体(struct),由于这类变量比较复杂,占用存储空间大,我们在使用时必须要声明数据存储的位置。

Solidity数据存储位置有三类:storage,memory和calldata。不同存储位置的gas成本不同。storage类型的数据存在链上,类似计算机的硬盘,消耗gas多;memory和calldata类型的临时存在内存里,消耗gas少。大致用法:

storage:合约里的状态变量默认都是storage,存储在链上。

memory:函数里的参数和临时变量一般用memory,存储在内存中,不上链。尤其是如果返回数据类型是变长的情况下,必须加memory修饰,例如:string,
bytes, array和自定义结构。

calldata:和memory类似,存储在内存中,不上链。与memory的不同点在于calldata变量不能修改(immutable),一般用于函数的参数。

pragma solidity 0.6.10;contract StorageScope{uint[] x = [1,2,3]; // 状态变量:数组 xfunction fStorage() public{//声明一个storage的变量 xStorage,指向x。修改xStorage也会影响x//storage存储uint[] storage xStorage = x;xStorage[0] = 100;}function get() public returns (uint){return x[0];}// memory存储function g(uint[3] memory _data) public pure {// ...}
}

Solidity中变量按作用域划分有三种,分别是状态变量(state variable),局部变量(local variable)和全局变量(global variable)
状态变量是数据存储在链上的变量,所有合约内函数都可以访问,gas消耗高。状态变量在合约内、函数外声明
局部变量是仅在函数执行过程中有效的变量,函数退出后,变量无效。局部变量的数据存.储在内存里,不上链,gas低.
全局变量是全局范围工作的变量,都是solidity预留关键字。他们可以在函数内不声明直接使用:

pragma solidity 0.6.10;contract StorageScope{uint public m = 1;uint public y;string public z;function foo() external{// 可以在函数里更改状态变量的值m = 5;y = 2;z = "0xAA";}    //局部变量是仅在函数执行过程中有效的变量,函数退出后,变量无效。//局部变量的数据存储在内存里,不上链,gas低。    function bar() external  returns(uint){uint xx = 1;uint yy = 3;uint zz = xx + yy;return(zz);}//全局变量是全局范围工作的变量,都是solidity预留关键字。他们可以在函数内不声明直接使用:function global() external view returns(address, uint, bytes memory){address sender = msg.sender;uint blockNum = block.number;bytes memory data = msg.data;return(sender, blockNum, data);}
}

7.3. 函数

注意 1:合约中定义的函数需要明确指定可见性,它们没有默认值。

注意 2:public|private|internal也可用于修饰状态变量。public变量会自动生成同名的getter函数,用于查询数值。未标明可见性类型的状态变量,默认为internal

 function  //关键字开头//函数名 输入到函数的变量类型和名称
<function name> ( <parameter types>)
//public:内部和外部均可见。
//private:只能从本合约内部访问,继承的合约也不能使用。
//external:只能从合约外部访问(但内部可以通过 this.f() 来调用,f是函数名)。
//internal: 只能从合约内部访问,继承的合约可以用
{internal|external|public|private} 
//pure,中文意思是“纯”,这里可以理解为”纯打酱油的”。pure 函数既不能读取也不能写入链上的状态变量。
//view,“看”,这里可以理解为“看客”。view函数能读取但也不能写入状态变量。
//非 pure 或 view 的函数既可以读取也可以写入状态变量。
[pure|view|payable]
[returns(<return types>)]

在这里插入图片描述

函数返回值

returns:跟在函数名后面,用于声明返回的变量类型及变量名。 return:用于函数主体中,返回指定的变量。

pragma solidity 0.6.10 ;contract FunctionTypes {int num = 99;//function <function name>(<parameter types>) {internal|external|public|private} //[pure|view|payable] [returns (<return types>)] 方括号中的是可写可不写的关键字// pure: 纯纯牛马function addPure(uint256 _number) external pure returns(uint256 new_number){new_number = _number + 1;}function addView()  external view returns (int) {int newnum = num +1;return newnum;}function add()  external  returns (int) {int num = num +1;return num;}//需要读num值 viewfunction viewFunc() external view returns(int){return num;}// 不需要读写numfunction pureFunc()  external pure returns (int){return 3+7;}// internal: 内部函数function minus() internal {num = num - 1;}// 合约内的函数可以调用内部函数function minusCall() external returns(int) {minus();return num;}// 返回多个变量function returnMultiple() public  returns(uint256, bool, uint256[3] memory,address,address){return(1, true, [uint256(1),2,5],address(this),address(0));}// 命名式返回function returnNamed() public  returns(uint256 _number, bool _bool, uint256[3] memory _array){_number = 2;_bool = false;_array = [uint256(3),2,1];}// 命名式返回,依然支持returnfunction returnNamed2() public pure returns(uint256 _number, bool _bool, uint256[3] memory _array){return(1, true, [uint256(1),2,5]);}
}

例:计算合约

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.10;contract Counter {int num ;function inc() external returns (int){num = num +1;return num;//return num +1;//num+1 是另一局部变量,会不自增。} //如下 只加1 不更新的.function in+1() external returns (int x){x = num +1;}function dec() external returns (int){num = num -1;return num;}
}

例:地址变量使用

//声明solidity版本为0.6.10
pragma solidity 0.6.10;
//定义合约
contract AddrTest {
//定义address类型全局变量address addr;
//部署合约时设置addr值constructor() public{addr =0x018020B71d0cACB421483efa5104fD2a8DAe9728;}function getValue() public returns(address){return addr;}//合约地址 和 0function getAddress() public returns(address,address){return (address(this),address(0));       }   
}

7.4 控制流

条件选择

pragma solidity 0.6.10;
contract fenzhi{function test(bool condition)public returns(string memory){
//单个条件判断if(condition){return "condition true";}return "condition false";}function test2(bool condition) public returns(string memory){//当条件不满足时,执行else语句if(condition){return "condition true";} else {return "condition false";}}function test3(bool condition, bool condition2) public returns (string memory){//else语句可以结合if连续判断if(condition){return "condition true";}else if(condition2){return"condition2 true";} else {return "all false";}}function test5(bool condition)public returns(string memory){//条件?条件为true时的返回:条件为false时的返回string memory x=condition ?"condition ture":"condition false";return x;}function test6(bool condition, bool condition2) public returns (string memory){//先判断condtion,condition为true执行大括号语句,否则执行elseif(condition){//再判断condition2if(condition2){return "condition2 true";} else{return "condition2 false";} } else {return "condition false";}        }
}

循环

pragma solidity 0.6.10;contract  ForAndWhere {function forexam() external returns (int) {int sum;for (int condition =1; condition<=10;condition++){  //写在执行语句前面,跳过后面的语句if (condition ==5){continue;}//写在执行语句前面,跳出循环if (condition ==9){break;}sum+=condition;}return sum;//31=1+2+3+4+6+7+8}function where() external returns (int){int _n=1;where (_n <10){//code_n++;}}
}

7.5 数组&映射

数组

pragma solidity 0.6.10;contract ArrayTest{//动态数组int[] public nums = [1,2,3];//定长数组int[3] public numsFix =[4,5,6];function example() external returns (uint[] memory,uint){nums.push(4);//[1,2,3,4]nums[2] = 66; // [1,2,66,4]delete nums[1];//[1,0,66,4] //位置没有删nums.pop();// [1,0,66]uint len = nums.length;//对于memory修饰的动态数组,可以用new操作符来创建,//但是必须声明长度,并且声明后长度不能改变uint[] memory a = new uint[](5);//如果创建的是动态数组,你需要一个一个元素的赋值。a[0] =1;return (a,len); }// 查看数组function returnArray() external view returns( int[] memory){return nums;}// 删除元素function remove(uint _index) public {for (uint i = _index; i< nums.length-1;i++){nums[i] = nums[i+1];}nums.pop();}    
}

异常

require(_owners[tokenId] == msg.sender, "Transfer Not Owner");
assert(_owners[tokenId] == msg.sender);

数组方法

pragma solidity 0.6.10;
//定义Test6合约
contract Array_ {//个ages变量,类型为uint类型阳,并在声明时初始化值uint[] public ages =[10,11,12];
//在数组未尾添加空元素function pushEmpty() public {ages.push();      }
//在数组未尾添加指定元素function pushAge(uint age)public {ages.push(age);    }
//删除数组未尾元素function popAge() public {ages.pop();   }
//将指定索引的元素设置为0值function deleteAge(uint index) public {delete ages[index];  }function getAges() public returns(uint[] memory){return ages;       }function getLength() public returns(uint){return ages.length;        }// 查看数组function returnArray() external view returns(uint[] memory){return ages;}// 删除元素:1. 前面不变 后面往前移,删最后一个。function remove1(uint _index) public {require (_index < ages.length,"index out of band");for (uint i = _index; i< ages.length-1;i++){ages[i] = ages[i+1];}ages.pop();}// 删除元素:2.最后一个数替换后删。不考虑顺序。function remove2 (uint _index) external {require (_index<ages.length,"index out of band");ages[_index] = ages[ages.length-1];ages.pop();}//测试,当检查条件不成立的时候,就会抛出异常function test() external view {assert (ages.length==3);assert (ages[0]==1);}
}

字节数组

pragma solidity 0.6.10;
contract arry_char{//初始化A,类型为字节数组bytes public A;//初始化B,类型为字节数组bytes public B= "hellw";//初始化C,字符串string public c= "world";
//bytes类型使用push删除元素function pushA(byte b)public {A.push(b);}
//bvtes类型使用pop删除元素function popA()public {A.pop();}
//bytes类型修改指定索引元素function changeB()public {B[4]= "o";}
//string类型不能获取长度或修改指定索引元素function errFunc()public {//C.length;// C[0] = "a"}
}

映射

pragma solidity 0.6.10;
contract Test_mapping {
//声明全局变量users,类型为mapping键为uint类型,值为string类型mapping(uint=>string)public users;
// 设置用户名function setuser(uint userID, string memory name) public {users[userID]= name;}
// 获取用户名function getuser(uint userID)public returns(string memory){return users[userID];}
// 删除用户function deleteuser(uint userID)public {delete users[userID];}
}

数组和映射组合快速判断。

pragma solidity 0.6.10;contract IterableMapping{mapping (address=>uint) balances;mapping (address=>bool) inserted;address[] keys;function set(address _key, uint _val) external {balances[_key]= _val;if (!inserted[_key]){inserted[_key] = true;//可以快速判断存在keys.push(_key);}}//数组长度function getSize() external view returns (uint){return keys.length;}// 第一个值function getFirst() external view returns (uint){return balances[keys[0]];}
}

7.6 结构体

pragma solidity 0.6.10;contract Structs{struct Car{string model;uint  year;address owner;}Car c;Car[] cs;mapping (address=>Car[]) carbyown;function example() external  {//初始化Car memory benchi = Car("benchi",1984,msg.sender);Car memory baoma = Car({year:1999,model:"baoma",owner:msg.sender});Car memory aodi;aodi.model ="aodi";aodi.year = 2000;aodi.owner=msg.sender;cs.push(benchi);cs.push(baoma);cs.push(aodi);//使用storage指向cs修改Car storage c=cs[0];c.year = 1985;delete c.model;}// 返回第值function returnstruct(uint _i) external view returns(uint,string memory,address){return (cs[_i].year,cs[_i].model,cs[_i].owner);}
}
//声明soliditv版本为0.6.10
pragma solidity 0.6.10;
contract Test_struct{//定义枚举类型enum gender {male, female}
//定义结构体类型struct user {uint ID;// 用户IDstring name; //用户名gender _gender;//用户性别}
//声明全局变量user,变量类型为user public _user;//创建用户function createUser(uint userID, string memory name, bool isFemale) public{_user =user(userID,name,gender.male);if(isFemale){_user._gender =gender.female;          }}
//更新用户名function updateUserName(string memory name) public {_user.name = name;}//获取用户性别function getUserGender() public returns(string memory){if(_user._gender == gender.male){return"男";}        return"女";}
}

7.7 修饰符

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

pragma solidity 0.6.10;contract ModifyTest {address public owner;// 创建合约时初始化owner变量uint x;constructor() public {owner = msg.sender;}modifier onlyOwner() {require (owner==msg.sender,"只允许合约创建者操作");_;}modifier compare(uint x,uint y) {// if(x>y){//     _;// }require (x>y,"小于Y");_;}// function test() public onlyOwner  returns(uint){//     return x+1;// }function test(uint x) public onlyOwner compare(x,9) returns(uint){return x+1;}
}

使用lihui部署并调用合约test()函数,输入9,提示错误。
在这里插入图片描述
使用lihui部署并调用合约test()函数,输入10,返回11。
在这里插入图片描述
使用lihui创建合约,使用test用户调用test(),提示“只允许“
在这里插入图片描述

7.8 事件

在这里插入图片描述

pragma solidity 0.6.10;contract EventTest{event testLog(uint x,string y);function test(uint a, string memory b) public {emit testLog(a,b);}event message (address _from, address _to, string _message);function sendMessage(address _to, string memory _message) external {emit message(msg.sender,  _to,  _message);}
}

通过合约管理-在线工具-Event查看

在这里插入图片描述

7.9 面向对象

pragma solidity 0.6.10;contract Object {string name;uint age;//构造函数,初始化constructor (string memory _name,uint _age) public {name = _name;age = _age;}function get() external view returns(string memory,uint){return (name,age);}
}

部署时就需要初始化
在这里插入图片描述
继承

pragma solidity 0.6.10;
contract Animal {string name;uint age;// 构造函数constructor (string memory _name,uint _age) public {name = _name;age = _age;}function get_name() public view returns(string memory){return name;}function get_age() public view returns (uint){return age;}
}
pragma solidity 0.6.10;
import "./Animal.sol";
contract Dog is Animal{constructor(string memory _name, uint _age) Animal(_name, _age) public{}//使用super话用父合约中的petName座function dogName() public view returns(string memory){return super.get_name();}//通过指定合约名调用父合约中的getAge函数function dogAge() public  view returns(uint){return Animal.get_age();}
}

直接使用父类方法和自写方法一样。
在这里插入图片描述
多继承

pragma solidity 0.6.10;
contract Pet {
// 和人玩耍function play()public view returns(string memory){return "play with people";}
//陪伴人function accompany()public returns(string memory){return "accompany with people";}
}
pragma solidity 0.6.10;
import "./Animal.sol";
import "./Pet.sol";
// is Pet 则继承Pet方法
contract CatPet is Animal,Pet{
//构造函数继承的两种方式
//contract CatPet is Animal("cat",22),Pet{    constructor(string memory _name, uint _age) Animal(_name, _age) public{}//使用super话用父合约中的petName座function dogName() public view returns(string memory){return super.get_name();}//通过指定合约名调用父合约中的getAge函数function dogAge() public  view returns(uint){return Animal.get_age();}
}

在这里插入图片描述

new 创建合约

//在NewPet中引用Pet, 并使用new 关键字创建
pragma solidity 0.6.10;
import "./Pet.sol";
contract NewPet {address petaddr;function deploy() public  returns(address){Pet pt = new Pet();petaddr=address(pt);return petaddr;}function get() public view returns (string memory){return  Pet(petaddr).play();}
}

方法覆盖
在这里插入图片描述

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.10;
contract A {    function foo() external view virtual returns(string memory){return "A";}function bar() external view returns(string memory){return "ab";}
}
pragma solidity 0.6.10;
import "./A.sol";contract B is A {function foo() external view virtual override returns(string memory){return "Ba";}
}
pragma solidity 0.6.10;
import "./B.sol";contract C is B {function foo() external view override returns(string memory){return "Cb";}
}

在这里插入图片描述

7.10 抽象合约

在这里插入图片描述

pragma solidity 0.6.10;
abstract contract A {function foo() external view virtual returns(string memory){return "A";}    function bar() external view returns(string memory){return "ab";}    function virt(uint x,uint y) public virtual returns (uint);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.10;
import "./A.sol";
contract B is A {function foo() external view virtual override returns(string memory){return "Ba";}    function virt(uint _x,uint _y) public override returns (uint){return _x+_y;}
}

7.11接口合约

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

7.12 库合约

在这里插入图片描述

pragma solidity 0.6.10;library Librar {function max(int x,int y) internal pure returns (int){return x>y?x:y;//取最大值}function find(int[] storage arr,int t) internal view returns(uint){for (uint i =0;i<arr.length;i++){if (arr[i] ==t) return i;}//查找值revert ("no find");}
}contract Library {function test(int x,int y) external view returns (int){return Librar.max(x,y);//调用库函数}using Librar for *;//简化库函数调用function test2(int x,int y) external view returns(int){return x.max(y);}int[]  arr = [1,2,3,6];function testfind() external view returns(uint){return arr.find(2);}
}

在这里插入图片描述

在这里插入图片描述

九、案例

在这里插入图片描述

9.1 权限控制合约

pragma solidity 0.6.10;contract AcessContract {event GrantRole(bytes32 indexed _role, address indexed _account);      //role=>account=>boolmapping (bytes32=>mapping(address=>bool)) public roles;bytes32 private constant ADMIN = keccak256(abi.encodePacked("ADMIN"));bytes32 private constant USER = keccak256(abi.encodePacked("USER"));//升级权限function grantRole(bytes32 _role,address _account) internal {roles[_role][_account] = true;emit GrantRole(_role,_account);}//取消权限function evokeRole(bytes32 _role,address _account) internal {roles[_role][_account] = false ;emit GrantRole(_role,_account);}modifier onlyRole(bytes32 _role){require (roles[_role][msg.sender],"not auth");_;}constructor() public {grantRole(ADMIN,msg.sender);}// ADMIN才能修改function grantRoleW(bytes32 _role,address _account) external onlyRole(ADMIN) {grantRole(_role,_account);}
}

9.2 投票合约

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;contract ballot{// 选民struct Voter{uint weight; //权重bool voted; //是否已投票string proposalName;//address delegate;// 被委托人}//提案struct Proposal{string name;//提案名uint voteCout;//投票数}//主持人address public chairPerson;    //存储所有选民mapping(address=>Voter) public voters;//存储所有提案Proposal[] public proposals;//是否在投票中bool voting = true;//修饰符,只有主持人可以操作modifier onlychairPerson() {require(chairPerson == msg.sender,"只有主持人可以操作");_;}// 修饰符,只有投票正在中可以操作modifier onlyproposals(){require(voting,"投票已结束");_;}   //创建合约 传入提案名constructor(string[] memory proposalNames) public{//合约创建者为主持人chairPerson = msg.sender;// 给主持人赋权voters[msg.sender].weight =1;// 添加提案到数组for (uint i =0;i<proposalNames.length;i++){proposals.push(//Proposal(proposalNames[i],0));Proposal({name:proposalNames[i],voteCout:0}));}}//内部使用工具 根据提案名获取索引function getProposalIndexByName(string memory _name) private view returns(uint){for (uint i = 0; i<proposals.length;i++){if (keccak256(abi.encodePacked(_name)) == keccak256(abi.encodePacked(proposals[i].name))){return i;}}revert("未找到");}//授权某个选民进行投票function approveToVote(address voteradd) public  onlychairPerson onlyproposals {require (voters[voteradd].voted == false,"已投票");require (voters[voteradd].weight ==0,"已赋权");voters[voteradd].weight =1;}// 投票给某提案function vote(string memory _proposalName) public onlyproposals{Voter storage sender = voters[msg.sender];require (sender.voted == false,"已投票");sender.voted=true;sender.proposalName= _proposalName;uint i= getProposalIndexByName(_proposalName);proposals[i].voteCout += sender.weight;}// 停止投票function stoped()   public  onlychairPerson {voting=false;}// 将投票权委托给指定用户,并跟随指定用户的投票function delegate(address delegateAddr) public onlyproposals {//获取操作用户Voter storage sender = voters[msg.sender];require (sender.voted == false,"已投票");require(delegateAddr!=msg.sender,"自己不能自己委托" );//委托是可以传递的,可能形成闭环让合约卡住while (voters[delegateAddr].delegate!=address(0)){delegateAddr =voters[delegateAddr].delegate;require(delegateAddr!= msg.sender,"不能循环委托");}//设置为已投票sender.voted=true; sender.delegate = delegateAddr;//获取被委托人Voter storage d = voters[delegateAddr];if (d.voted){//若被委托人投过票,则直接增加票数uint i = getProposalIndexByName(d.proposalName);proposals[i].voteCout+=sender.weight;} else {// 若被委托人没投过票,增加被委托人票数d.weight += sender.weight;}    }//获取投票最多的提案function getMax() public view returns (string memory winName){uint maxVote=0;for (uint i = 0; i<proposals.length;i++){if(proposals[i].voteCout >maxVote){maxVote = proposals[i].voteCout;winName = proposals[i].name;}}return winName;} 
}

在这里插入图片描述
在这里插入图片描述
通过代码了解联邦选举流程

pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;contract ballot2{struct Area{string name; //选取名称uint weight; // 选区计票权重mapping(string=>uint) Proposal;// 该区投票情况}    //投票人struct Voter{uint weight; //权重bool voted; //是否已投票string proposalName;//string areaName;// 选区名}//提案struct Proposal{string name;//提案名uint voteCout;//投票数}//主持人address public chairPerson;//存储所有选民mapping(address=>Voter) public voters;//存储所有提案Proposal[] public proposals;//存储所有的选区Area[] areas;//是否在投票中bool voting = true;//修饰符,只有主持人可以操作modifier onlychairPerson() {require(chairPerson == msg.sender,"只有主持人可以操作");_;}// 修饰符,只有投票正在中可以操作modifier onlyproposals(){require(voting,"投票已结束");_;} //创建合约 传入提案名和主持人所在地区constructor(string[] memory proposalNames,string memory chairPersonArea) public{//合约创建者为主持人chairPerson = msg.sender;// 给主持人赋权voters[msg.sender].weight =1;// 设置主持人所在区域voters[chairPerson].areaName = chairPersonArea;// 添加提案到数组for (uint i =0;i<proposalNames.length;i++){proposals.push(//Proposal(proposalNames[i],0));Proposal({name:proposalNames[i],voteCout:0}));}}//内部使用工具 根据提案名获取索引function getProposalIndexByName(string memory _name) public view returns(uint){for (uint i = 0; i<proposals.length;i++){if (keccak256(abi.encodePacked(_name)) == keccak256(abi.encodePacked(proposals[i].name))){return i;}}revert("未找到");}//内部使用工具 根据提小区获取索引function getAreaIndexByName(string memory _name) public view returns(uint){for (uint i = 0; i<areas.length;i++){if (keccak256(abi.encodePacked(_name)) == keccak256(abi.encodePacked(areas[i].name))){return i;}}revert("未找到");}// 添加小区function addArea(string memory _name,uint _weight) public onlychairPerson onlyproposals{areas.push(Area({name:_name,weight:_weight}));}//授权某个选民进行投票,并设置选民所在地区function approveToVote(address voteradd,string memory _areaname) public  onlychairPerson onlyproposals {require (voters[voteradd].voted == false,"已投票");require (voters[voteradd].weight ==0,"已赋权");voters[voteradd].weight =1;voters[voteradd].areaName = _areaname;}// 投票给某提案function vote(string memory _proposalName) public onlyproposals{Voter storage sender = voters[msg.sender];require (sender.voted == false,"已投票");sender.voted=true;sender.proposalName= _proposalName;uint areai= getAreaIndexByName(sender.areaName);//获取选民选区,增加对应投票areas[areai].Proposal[_proposalName] += sender.weight;}// 停止投票function stoped()   public  onlychairPerson {voting=false;}//获取区域最大投票和权重function getAreaMax(string memory _areaname) public view returns (string memory winName,uint){uint maxVote=0;// 获取指定区域uint areai= getAreaIndexByName(_areaname);Area storage a = areas[areai];for (uint i = 0; i<proposals.length;i++){uint  ProposalCount = a.Proposal[proposals[i].name];if(ProposalCount>maxVote){maxVote = ProposalCount;winName = proposals[i].name;}}return (winName,a.weight);}    //将每个区的票相加function areaTotel() public onlyproposals {string memory winName;uint winWeight;for (uint i =0;i<areas.length;i++){(winName,winWeight) = getAreaMax(areas[i].name);uint indexi = getProposalIndexByName(winName);proposals[i].voteCout += winWeight;}}   //获取投票最多的提案function getMax() public view returns (string memory winName){uint maxVote=0;for (uint i = 0; i<proposals.length;i++){if(proposals[i].voteCout >maxVote){maxVote = proposals[i].voteCout;winName = proposals[i].name;}}return winName;} 
}

9.3 拍卖合约

在这里插入图片描述
在这里插入图片描述

pragma solidity 0.6.10;contract Auction{//拍卖收益人address public beneficiary;//拍卖结束的时间戳(毫秒)uint public auctionEnd;//当前出价最高者和最高金额address public highestBidder;uint public highestBid;//参与拍卖用户余额mapping (address=>uint) public balance;//最高出价变更EVENTevent HighestBidIncreased(address bidder,uint amount);//初始化拍卖,传入拍卖时间(秒)和收益人地址constructor (address _beneficiary, uint _biddingtime) public{beneficiary = _beneficiary;auctionEnd = now+_biddingtime*1000;}//存入余额function deposit(uint _value) public{balance[msg.sender] += _value;}//取出余额function withdraw() public returns(uint) {uint valueNow =balance[msg.sender];balance[msg.sender]=0;return valueNow;}// 竞拍出价function bid (uint _value) public {require(now<=auctionEnd,"拍卖时间结束");require(balance[msg.sender]>=highestBid,"余额不足");require(_value > highestBid,"当前价低于最高价");// 将余额返还给之前最高者balance[highestBidder]+=highestBid;// 当前最高者减余额balance[msg.sender]-= _value;//更新最高者,发送eventhighestBidder = msg.sender;highestBid = _value;emit  HighestBidIncreased(msg.sender,_value);}    function stopAuction() public {require(now>auctionEnd,"拍卖时间未到");balance[beneficiary]+=highestBid;}
}

在这里插入图片描述
在这里插入图片描述

// 声明 solidity 版本为 0.6.10
pragma solidity 0.6.10;
// 定义 Auction 合约
contract Auction2{//拍卖结构体,存储盲拍的散列和保证金struct Bid{bytes32 blindedBid;uint margin;}//拍卖受益人address public beneficiary;// 拍卖结束的时间戳uint public biddingEnd;// 出价披露结束的时间戳uint public revealEnd;// 参数拍卖的用户mapping(address =>Bid) public bids;//当前出价最高者和最高金额address public highestBidder;uint public highestBid;// 参与拍卖用户的余额mapping(address=>uint) balance;// 修饰符,限制操作时间必须小于 timemodifier onlyBefore(uint time){require(now<time);_;}// 修饰符,限制操作时间必须大于 timemodifier onlyAfter(uint time){require(now>time);_;}// 初始化拍卖,传入拍卖持续时间(秒),出价披露持续时间(秒),受益人地址constructor(uint biddingTime,uint revealTime,address beneficiary)public{beneficiary=beneficiary;biddingEnd =now+biddingTime*1000;revealEnd =biddingEnd +revealTime*1000;}// 存入余额function deposit(uint value)public {balance[msg.sender]+=value;}//取出余额function withdraw()public returns(uint){uint value =balance[msg.sender];balance[msg.sender]=0;return value;}// 工具函数,供用户计算哈希(该函数不会在区块链上留下日志)function bidTool(uint value, string memory secret)public view returns(bytes32){return keccak256(abi.encodePacked(value,secret));}//盲拍,传入盲拍哈希值和保证金function blindedBid(bytes32 blindedBid, uint value) public onlyBefore(biddingEnd){require(balance[msg.sender]>= value,"余额不足");balance[msg.sender]-= value;Bid storage bid= bids[msg.sender];require(bid.margin ==0,"只能出价一次");bids[msg.sender]= Bid({blindedBid:blindedBid,margin:value});}// 判断 value 是否为最高出价,更新当前最高价和出价用户function placeBid(address bidder, uint value)internal returns (bool success){if(value<= highestBid){return false;}if(highestBid !=0 ){balance[highestBidder]+=highestBid;}highestBid =value;highestBidder=bidder;return true;}//披露价格,验证哈希值,正确则执行出价流程function reveal(uint value, string memory secret) public onlyAfter(biddingEnd) onlyBefore(revealEnd){Bid storage bid= bids[msg.sender];uint refund = bid.margin;if(bid.blindedBid != keccak256(abi.encodePacked(value, secret))){return;}//只能披露一次价格if(bid.blindedBid ==bytes32(0)){return;}bool isHighest=placeBid(msg.sender,value);if(isHighest){refund -= value;}//将盲拍哈希设置为空bid.blindedBid=bytes32(0);balance[msg.sender]+= refund;}//结束拍卖,将拍卖所得转给受益人function stopAuction()public{require(now>= biddingEnd,"拍卖还未到结束时间");balance[beneficiary]+= highestBid;}    
}

http://www.ppmy.cn/news/1538883.html

相关文章

太速科技-607-基于FMC的12收和12发的光纤子卡

基于FMC的12收和12发的光纤子卡 一、板卡概述 本卡是一个FPGA夹层卡&#xff08;FMC&#xff09;模块&#xff0c;可提供高达2个CXP模块接口&#xff0c;提供12路收&#xff0c;12路发的光纤通道。每个通道支持10Gbps,通过Aurora协议&#xff0c;可以组成X4&#xff0…

【Java】I/O 操作详解

&#x1f4c3;个人主页&#xff1a;island1314 ⛺️ 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f442;&#x1f3fd;留言 &#x1f60d;收藏 &#x1f49e; &#x1f49e; &#x1f49e; 目录 1. 引言 &#x1f680; 2. File 类 &#x1f4d5; 2.1 创建 File 对象 …

leetcode二叉树(二)-二叉树的递归遍历

题目 . - 力扣&#xff08;LeetCode&#xff09; . - 力扣&#xff08;LeetCode&#xff09; . - 力扣&#xff08;LeetCode&#xff09; 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出…

SpringBoot 整合 RabbitMQ 的使用

一、RabbitTemplate 的使用 1.【导入依赖】 <!-- rabbitMQ --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId><version>2.6.1</version> </dependency>…

html 之 relative 和 absolute

当子元素或伪元素使用绝对定位&#xff08;position: absolute&#xff09;时&#xff0c;它会相对于最近的相对定位&#xff08;relative&#xff09;的父元素进行定位 relative 当你给父元素添加 relative 时 相对定位本身并不会影响元素的布局&#xff0c;它仍然会按照正常…

【C++贪心 DFS】2673. 使二叉树所有路径值相等的最小代价|1917

本文涉及知识点 C贪心 反证法 决策包容性 CDFS LeetCode2673. 使二叉树所有路径值相等的最小代价 给你一个整数 n 表示一棵 满二叉树 里面节点的数目&#xff0c;节点编号从 1 到 n 。根节点编号为 1 &#xff0c;树中每个非叶子节点 i 都有两个孩子&#xff0c;分别是左孩子…

深入探讨Python网络爬虫的实现与应用

引言 在信息爆炸的时代,数据成为推动决策和创新的关键因素。随着互联网的迅猛发展,各种在线信息源层出不穷,如何高效地获取和处理这些数据成为了许多行业的重要任务。网络爬虫(Web Crawler)作为一种自动化获取网页信息的技术,在数据收集和分析中发挥了重要作用。Python凭…

npm 配置淘宝镜像

为了加速 npm 包的下载速度&#xff0c;尤其是在中国地区&#xff0c;配置淘宝的 npm 镜像&#xff08;也称为 cnpm 镜像&#xff09;是一个常见的方法。以下是如何配置淘宝 npm 镜像的步骤&#xff1a; 1. 使用 npm 命令配置镜像 你可以直接使用 npm 命令来设置淘宝的 npm 镜…