版权声明:忠于祖国,忠于人民 https://blog.csdn.net/boss2967/article/details/83278359
01.remix的使用
- vm:单机版,用于测试,迅速返回,默认有5个账户,每个默认100ETH
- injected web3: 这个实力负责真正连接以太坊环境
- web3 provider:有开发者自己定义的:Ganch或者geth自己搭建的私有网络
02.以太坊交互的特点
- 发送交易(send)
- 花钱
- 需要15秒左右进行确认后才能返回(真实网络)
- 获取数据(call)
- 免费
- 迅速返回
03.智能合约
- 合约
pragma solidity ^0.4.24;
contract Inbox{
string public message;
// var message string //go
//func Inbox(sr1 string, num uint128) {} //go
function Inbox()payable {
//构造函数完成对类,合约的初始化工作
message = "HELLO WORLD!";
}
function setMessage(string newMessage) public{
message = newMessage;
}
//func getMessage() string {} //go
function getMessage() public constant returns(string, string){
//return message;
return (message, "hello"); //元组
}
}
- 合约地址+bytecode+abi就可以唯一控制一个合约,通过web3就可以调用了
04.数据类型
01.值类型(memory,默认就是memory)
- 值类型是指变量在传递过程中是将数值完整的拷贝一份,在赋值给新的变量,这种方式需要开辟的内存空间,效率较低,两个变量完全独立,修改一个不会影响另外一个。
值类型包含:- 布尔(Booleans)
- 整型(Integer)
- 地址(Address)
- 定长字节数组(fixed byte arrags)
- 有理数和整型(Rational and Integer Literals,String literals)
- 枚举类型(Enums)
- 函数(Function Types)
02.引用类型(storage, memory)
- solidity没有指针,对于复杂的结构进行高效传递方式是使用关键字
storage
进行修饰。 - 复杂类型,占用空间较大的。在拷贝时占用空间较大。所以考虑通过引用传递。
- 常见的引用类型有:
- 字符串(string
- 不定长字节数组(bytes)
- 数组(Array)
- 结构体(Structs)
05.基础语法
01.view,constant,pure讲解
- 如果一个函数里面,访问了状态变量,但是没有修改,我们使用view或者constant修饰
- 如果访问了,而且修改了,那么就不能constant和view,否则会报错
- 如果没有使用过状态变量,我们要修饰为pure(函数内引用的状态变量没有改变)
- 如果你修饰为constant,但是你在函数中修改了,效果是:不会报错,正常执行,但是值不会改变
pragma solidity ^0.4.24;
contract test1 {
int8 public i8 = 100; //成员变量就是状态变量
int i256 = 256;
//表示不会修改函数内的状态变量
//为了明确语义,一般要加上constant(view两者完全相同)
function add() private constant returns(int) {
return i8 + i256;
}
//public 表示所有的人都可以看到的,而且可以调用
//private表示所有人都可以看到,但是无法调用
function mins() constant returns(uint256) {
return uint256(i256 - i8);
}
function isEqual(int a, int b) public pure returns(bool) {
return a == b;
}
function setValue(int8 num) {
i8 = num;
}
function setValue1(int8 num) constant {
i8 = num;
}
}
02.地址
- 余额
pragma solidity ^0.4.24;
contract test1 {
function getBalance(address _addr) public view returns (uint256) {
//使用balance成员获取当前地址的余额
return _addr.balance;
}
//地址是160位数字,可以使用uint160来转换
address add1 = 0x00ca35b7d915458ef540ade6068dfe2f44e8fa733c;
uint160 u160 = uint160(add1);
function add() public view returns(uint160) {
return u160 + 1;
}
}
- 转账(transger,send)
pragma solidity ^0.4.24;
contract test1 {
constructor() public payable {//表示可以去转账
}
// 1ehter = 10^18 wei //以太坊
// 1btc = 10^8 sat //比特币
// 我们合约中都是wei单位
// this是合约的地址
function getContractBalance() public view returns (uint256) {
return address(this).balance;
}
function transferTo1(address receiver) public {
//转账的单位是wei
//给谁转,就用谁调用transfe
// 如果转账失败,抛异常
receiver.transfer(1);
}
function transferTo2(address receiver) public {
receiver.transfer(address(this).balance);
}
//Send在转账失败时,不会抛出异常而是返回false,需要程序员自己校验
//一般不使用send
function sendTo(address receiver) public returns(bool) {
//转账的单位是wei
//给谁转,就用谁调用transfe
// 如果转账失败,抛异常
bool res = receiver.send(1);
return res;
}
}
03.固定长度数组bytes1
pragma solidity ^0.4.24;
contract test1 {
// - 长度可以读取 length
// - 长度不可以修改
// - 可以通过下标访问
// - 内容不可修改
bytes1 public b1 = "h";
bytes2 public b2 = "he";
bytes10 public b10 = "helloworld";
function getLen() public view returns(uint128){
//b1.lenght = 10;
//b1[0] = "H";
return b1.length;
}
function getByIndex(uint i) public view returns(byte) {
return b10[i];
}
}
4.匿名函数
pragma solidity ^0.4.24;
contract test1 {
uint128 public num;
constructor() public {//如果构造函数中为指定payable关键字,那么创建合约时不允许转账
}
//任何函数,只要指定了payable关键字,这个合约就可以接受转账,调用时,也可以转0
function giveMoney() public payable {
}
//一般用于给合约转账
function ()payable {
}
function setValue(uint128 _num) public {
num = _num;
}
function getBalance() public view returns(uint) {
return address(this).balance;
}
}
05.bytes
pragma solidity ^0.4.24;
// - 动态字节数组
// - 引用类型(说明可以使用storage来修饰,进行引用传递,指针的效果)
// - 支持下标索引
// - 支持length、push方法(push会帮助分配空间的)
// - 可以修改
// - 以十六进制格式赋值
//格外注意:对于bytes,如果不使用下标访问,那么可以不用先申请空间,
//直接赋值即可,或者push
contract test1 {
bytes public name1 = new bytes(1);
bytes public name2;
function getName1Length() public view returns(uint256) {
return name1.length;
}
function setName1Len(uint len) public {
name1.length = len;
}
function setName2Len(uint len) public {
name2.length = len;
}
function getName2ByIndex(uint i) public view returns(byte){
return name2[i];
}
function pushValueToName2(byte src) public {
name2.push(src);
}
function setValueToName2(string src) public {
name2 = bytes(src);
}
}
06.string
pragma solidity ^0.4.24;
// - 动态尺寸的UTF-8编码字符串,是特殊的可变字节数组
// - 引用类型
// - 不支持下标索引
// - 不支持length、push方法
// - 可以修改(需通过bytes转换)
contract test1 {
string public name = "banzhang";
function setValue() public {
//name[0] ="B";
bytes(name)[0] ="B";
}
function getLen() public view returns(uint256){
//return name.length;
return bytes(name).length;
}
function setLen() public returns(uint256) {
bytes(name).length = 20;
}
}
07.storageVSmemory
pragma solidity ^0.4.24;
contract test1 {
string public name = "banzhang";
uint public num = 10;
function call1() public {
setValue1(name);
}
function setValue1(string memory _name) public {
//name[0] ="B";
bytes(_name)[0] ="B";
num = 1000;
}
function call2() public {
setValue2(name);
}
function setValue2(string storage _name) private {
//name[0] ="B";
bytes(_name)[0] ="B";
num = 1000;
}
function localTest() public {
//String作为局部变量时,默认是storageleixing,但是可以指定为memory
// string tmp = name;
string memory tmp = name;
bytes(tmp)[0] = "B";
}
}
08.bytesStringBytes1相互转化
pragma solidity ^0.4.20;
contract Test {
bytes10 public b10 = 0x68656c6c6f776f726c64; //helloworld
//bytes bs10 = b10; //无法直接转换
bytes public bs10 = new bytes(b10.length);
//1. 固定字节数组转动态字节数组
function fixedBytesToBytes() public{
for (uint i = 0; i< b10.length; i++){
bs10[i] = b10[i];
}
}
//2.string转动态字节数组
string greeting = "helloworld";
bytes public b1;
function StringToBytes() public {
b1 = bytes(greeting);
}
//3. 动态字节数组转string
string public str3;
function BytesToString() public {
fixedBytesToBytes();
str3 = string(bs10);
}
//4. fixed bytes to String,error
function FiexBytesToString(){
//string tmp = string(b10);
}
}
09.自定义数组-定长数组
pragma solidity ^0.4.20;
// - 类型T,长度K的数组定义为T[K],例如:uint [5] numbers, byte [10] names;
// - 内容可变
// - 长度不可变,不支持push
// - 支持length方法
contract Test {
uint [10]nums = [1,2,3,4,5,6,7,8,9,10];
uint public sum;
function getSum() public returns(uint) {
for (uint i = 0; i< nums.length; i++) {
sum += nums[i];
}
return sum;
}
//==================
bytes10 helloworldFixed = 0x68656c6c6f776f726c64;
byte [10] byteArray = [byte(0x68), 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64];
function setValue() public {
byteArray[0] = 0x69;
}
bytes public res;
function appendArray() public returns (string) {
for (uint i = 0; i< byteArray.length; i++) {
res.push(byteArray[i]);
}
return string(res);
}
}
10.自定义数组-不定长数组
pragma solidity ^0.4.0;
contract C {
//创建方式一:字面量形式
uint [] public c = [uint(1), 2, 3];
function h() public {
c.push(4);
}
//创建方式二:new 关键字
//a. storage类型数组,状态变量,最初为空,下标访问时越界
uint[] public b;
//复杂类型在局部是引用
function g(){
b = new uint[](7);
//可以修改数组的长度
b.length = 10;
b[9] = 100;
b.push(101);
}
//b. memory类型数组
function f() public returns (uint[]){
uint[] memory a = new uint[](7);
//不能修改长度
//Error: Expression has to be an lvalue.
//a.length = 100;
//a.push(10);
for (uint i = 0; i< a.length; i++){
a[i] = i;
}
return a;
}
}
11.结构体
pragma solidity ^0.4.5;
contract Test {
//定义结构之后无分号,与枚举一致
struct Student {
string name;
uint age;
uint score;
string sex;
}
//两种赋值方式
Student public stu1 = Student("lily", 18, 90, "girl");
Student public stu2 = Student({name:"Jim", age:20, score:80, sex:"boy"});
Student[] public Students;
function assign() public {
stu1.name = "Lily";
Students.push(stu1);
Students.push(stu2);
}
}
12.mapping映射
pragma solidity ^0.4.20;
contract test {
//id -> name
mapping(uint => string) public id_names;
constructor() public{
id_names[0x01] = "lily";
id_names[0x02] = "Jim";
id_names[0x02] = "Lily";
}
function getNameById(uint id) public returns (string){
//加上storage如何赋值?
string memory name = id_names[id];
return name;
}
function setNameById(uint id) public returns (string){
// mapping(uint => string) memory id_name = id_names;
// var ids = id_names;
id_names[id] = "Hello";
}
// function getMapLength() public returns (uint){
// return id_names.length;
// }
}