Solidity学习笔记

  • Post author:
  • Post category:solidity




学习视频来源:


基于以太坊的智能合约开发教程【Solidity】

读取数据不需要消耗燃料费Gas,修改数据需要消耗燃料费。

pragma solidity ^0.4.0;

contract Helloworld{
    string Myname = "lushuo";
    
    function getName() public view returns(string){
        return Myname;
    }
    function changeName(string newName) public{
        Myname = newName;
    }
    
}

给变量加上 public 之后,就会默认生成 get 方法。

在Solidity中constant、view、pure三个函数修饰词的作用是告诉编译器,函数不改变/不读取状态变量,这样函数执行就可以不消耗gas了(是完全不消耗!),因为不需要矿工来验证。所以用好这几个关键词很重要,不言而喻,省gas就是省钱!

视图函数是只读函数,使用View关键字声明。它们不修改区块链的状态。

这意味着使用view关键字声明的函数不能包含可能修改状态变量或存储在区块链上的数据的代码。

这三个关键词有什么区别和联系,简单来说,在Solidity v4.17之前,只有constant,后来有人嫌constant这个词本身代表变量中的常量,不适合用来修饰函数,所以将constant拆成了view和pure。view的作用和constant一模一样,可以读取状态变量但是不能改;pure则更为严格,pure修饰的函数不能改也不能读状态变量,否则编译通不过。


constant关键字

  • 函数内部的 constant 关键字,在4.0版本中因为他是和 view 这样的关键字是等价的,在5.0版本中将会废弃掉 constant 关键字。
  • 局部变量是没有 constant 这个属性的
  • 全局变量加上了 constant 属性,就不能修改。
  • 当前的版本支持 int,uint,string,bytes1–bytes32 能够使用 constant。


数据类型详解


数据类型详解和转换

	// 布尔类型
	bool 
	// 整形
	int【可正可负】 和 uint【非负】
	uint8【八位 最大能存十进制255,在以太坊中节约内存】
	// 位运算
	// 整数溢出以及异常处理
	// 整形字面量
	// 固定长度字节数组
	


地址类型(address)

以太坊中的地址的长度为20字节,一字节等于8位,一共160位,所以address其实亦可以用uint160来声明。

1个数字代表四位。两个数字就是一个字节。

address owner = 0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C;

在这里插入图片描述

加上 payable 关键字之后,可以给合约地址转账。

pragma solidity ^0.4.0;

contract BooleanTest{
    function pay() payable{

    }
    function getBalance() returns(uint){
        return this.balance;
    }
}

先部署,部署完成之后再设置转账的值,执行pay方法。


外部地址个外部地址之间的转账

	function transfer() payable{
        address account = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2;
        account.transfer(msg.value);
    }

设置val值

在这里插入图片描述

点击 transfer 转账就完成了。

在这里插入图片描述


总体代码

pragma solidity ^0.4.0;

contract BooleanTest{
    // 控制台输入value 后点击 pay 方法可以转账
    function pay() payable{

    }
    // 查看当前合约账户的余额
    function getBalance() returns(uint){
        return this.balance;
    }
    // 获取合约地址
    function getThis() view returns(address){
        return this;
    }
    // 获取当前账户的账户余额
    function getrandomBalance(address account) view returns(uint){
         
        return account.balance;
    }
    // 如何在外部地址和外部地址之间转账
    function transfer() payable{
        address account = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2;
        account.transfer(msg.value);
    }

}


以太坊的全局属性

在这里插入图片描述

pragma solidity ^0.4.0;

contract BooleanTest{
    function getglobal1() view returns(address){
        return msg.sender;
    }
    function getglobal2() view returns(uint){
        return block.difficulty;
    }
    function getglobal3() view returns(uint){
        return block.number;
    }
    function getglobal4() view returns(address){
        return block.coinbase;
    }
}

在这里插入图片描述


转账误操作

当把转账金额设置成固定金额的时候,val值超过固定值,多余的金额会转到合约账户里面。

account.transfer(5 ether);


构造函数

版本不同,语法不同。

pragma solidity ^0.8.0;

contract BooleanTest{
    uint public a;
    constructor() {
        a = 100000;
    }
}

一个文件可以写多个 contract ,在编译的时候进行选择即可。

在这里插入图片描述


构造函数的经典用法!!!

在部署合约的时候,将合约的部署者(拥有者)的账户地址赋值给owner。

	address owner
	constructor() public{
       OraclesSCowner = msg.sender;
    }


modifire函数

	constructor() public{
       owner = msg.sender;
       ReqID=0;
       currentID = 1;
    }
    
	//testing center
	modifier OnlyOwner(){
	    require(msg.sender == owner);
	    _;
	}

	//timer oracle
	modifier OnlyTimerOracle(){
	    require(msg.sender == 0xdD870fA1b7C4700F2BD7f44238821C26f7392148);
	    _;
	}
	
	//timer oracle
	modifier OnlyChosenOracle(){
	    require(msg.sender == chosenOracle);
	    _;
	}

代码解释:

  • owner 是在构造函数中获得的合约的拥有者的地址。
  • require 进行判断,如果不成立,就不执行下面的语句。
  • OnlyOwner、OnlyTimerOracle、OnlyChosenOracle 都是函数的修饰符。
  • 使用了上面函数修饰符的函数,会首先进行调用上面的函数进行判断。
contract LocationTrackingSC {

    address owner = 0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C;
    
	modifier OnlyOwner(){
	    require(msg.sender == owner);
	    _;
	}

	//events
    event ProofOfLocation(address EA, int lat, int long, uint256 time);
   
   //Triggers proof of location events
    function TriggerLocationAlert(address EA, int lat, int long, uint256 time) OnlyOwner public {
        emit ProofOfLocation(EA,lat,long,time);
    }
}


mapping

pragma solidity ^0.4.0;
contract mapingTest{
    
    mapping(address => uint) idmaping;
    mapping(uint => string) namemaping;

    uint public sum = 0;

    function register(string name){
        // 获取当前合约的调用这
        address account = msg.sender;
        sum++;

        // 将合约的调用者的地址与注册总量id联系到一起
        idmaping[account] = sum;

        // 当前用户的id与用户注册的名字绑定到了一起
        namemaping[sum] = name;
    }

    // 通过关键字地址获取到和他绑定在一起的id值
    function getIdByAddress(address are) view returns(uint){
        return idmaping[are];
    }
    function getNameById(uint id) view returns(string){
        return namemaping[id];
    }


}


合约的继承使用 is 关键字


智能合约的访问权限共有 4 种类型

: private(不能被继承)、internal、public 和 external

  • private 函数和状态变量仅在当前合约中可以访问,在继承的合约内不可访问。
  • internal 函数和状态变量可以在当前合约或继承合约里调用。需要注意的是不能加前缀 this,前缀 this 是表示通过外部方式访问。
  • public 函数是合约接口的一部分,可以通过内部或者消息来进行调用。对于 public 类型的状态变量,会自动创建一个访问器。
  • 外部函数是合约接口的一部分,所以我们可以从其它合约或通过交易来发起调用。一个外部函数 f,不能通过内部的方式来发起调用,如f()不可以调用,但可以通过this.f()。
  • external 修饰的函数不能够在内部调用。也不能够在继承合约内部调用。间接的方式可以通过this.f()。子合约也是需要this.f()。


结构体struct

	struct Video {
	    address vid_owner;//Ethereum address of the video owner
	    string info;//informtation about the video
	    bytes32 IPFS_Hash;//IPFS hash of the uploaded video on the IPFS server
	    address SC_address;//address of Smart contract
	    string metadata;
	    uint256 timestamp;
    }

	struct Artist{
        artistState state;
        address EA;
        bytes32 hash;
        bool result;//by default false unless granted permission
    }

    bool parent;//if true it means it has a parent and it is a child
    Video public parent_video;//parent video if any

    mapping (bytes32 =>Video) public Granted_Permission_ChildVideos;//for history tracking, mapping all children videos with their SC address
    mapping (bytes32 => Artist) public Granted_Permissions;// EA of artists with granted permissions, maps between the EA and the IPFS hash of the video
    mapping (bytes32 => Artist) public Denied_Permissions;//list of artists with denied permissions,maps between the EA and the IPFS hash of the video
    mapping (bytes32=>Artist) public Requests;//all requets , EA and IPFS hash
  • 如果结构体中有mapping类型的时候,初始化结构体的时候,要忽略掉这样的mapping类型。
  • memory的对象不能够直接的操作struct结构体中的mapping。
pragma solidity ^0.4.0;
contract memoryTest{
    struct student{
        uint grade;
        string name;
        mapping(uint=>string) map;
    }
    student meimei;
    function init() view returns(uint,string,string){
        student memory s = student(100,"lushuo");
        // s.map[0] = "hello"; [报错]
        // 将内存当中的s对象赋值给meimei这样的storage对象
        meimei = s;
        // 我们只能通过storage对象来操作我们的结构体中mapping属性
        meimei.map[0] = "helloworld";
        return(s.grade,s.name,meimei.map[0]);
    }
}


枚举体

一般用于状态的转移

enum artistState {SentRequest,  GrantedPermission, DeniedPermission, SentAttestationRequest, GrantedAttestation, DeniedAttestation } 

在这里插入图片描述

pragma solidity ^0.4.0;
contract memoryTest{
    enum girl{fengjie,binbin,yuanyuan} // 0 1 2

    girl dateGirl = girl.fengjie;

    function getEnum() view returns(girl){
        return girl.yuanyuan; // 2
    }
    function oneNightDate() returns(string){
        require(dateGirl == girl.fengjie);
        dateGirl = girl.binbin;
        return 'date with fengjie';
    }
    function secondNightDate() returns(string){
        require(dateGirl == girl.binbin);
        return 'date with binbin';
    }
}



版权声明:本文为qq_39537400原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。