solidity高级特性

solidity高级特性,第1张

1 function
view:承诺不修改状态。
pure:纯函数,承诺不会读取或修改状态。
payable:为了接收ether,(fallback)回退函数必须标记为payable。最少需2300gas。

2 log
通过函数来访问低层接口的记录机制log0,log1,log2,log3和log4。 logi获取类型的参数,其中第一个参数将用于日志的数据部分,其他参数用作主题。上面的事件调用可以以与以下相同的方式执行i + 1bytes32。

pragma solidity ^0.4.10;

contract C {
    function f() public payable {
        uint256 _id = 0x420042;
        log3(
            bytes32(msg.value),
            bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20),
            bytes32(uint256(msg.sender)),
            bytes32(_id)
        );
    }
}

3 event
event允许EMV写日志功能的方便使用,进而在dapp的用户接口中用JavaScript顺序调用,从而监听这些事件。
event是合约中可继承的成员。当他们调用时,会导致一些参数在交易日志上存储–在blockchain上的一种特殊的数据结构。
//只需声明事件,不需实现,就能用。
//像函数一样可被继承

外部获取智能合约的状态变化
每次触发事件,都会生成以太坊日志,可以索引
在remix中console面板的log里面生成一条日志

如何使用
event EventName(uint param); //声明事件,通常事件大写开头,函数小写
emit EventName(10); //触发事件

外部DApp监听使用
var ev = contractInstance.EventName();
ev.watch(function(err,result){
result.args.name;
})

wiki.learnblockchain.cn/course/dapp.html

// SPDX-License-Identifier:MIT
// 参考: https://www.bilibili.com/video/BV1BQ4y1k7Gz?spm_id_from=333.337.search-card.all.click
pragma solidity ^0.8;

contract Event{
    
    // event Log1(address sender, uint256 value);
    event Log1(address indexed sender, uint256 value); // indexed 索引
    string log;

    function test() external{
        emit Log1(msg.sender, 100); //这种方式消耗gas少,比下面存储少
        log = 'dfkg';
    }
}

event -> emit -> watch

pragma solidity ^0.4.24;

contract testEvent {

    constructor() public payable {
    }

    event Deposit(address _from, uint _value);


    function deposit() public payable {
        emit Deposit(msg.sender, msg.value);
    }
    function depositNone() public payable {
    }
}

contract testEvent2 is testEvent {

    function deposit2() public payable {
        emit Deposit(msg.sender, msg.value);
    }
}

4 library
库和合约类似,但是它们的目的主要是在给定地址上部署,以及用EVM的CALLCODE特性来重用代码。这些代码是在调用合约的上下文里执行的,例如调用合约的指针和调用合约的存储能够被访问。由于library是一片独立的代码,如果它们显式地提供的话,就仅仅能访问到调用合约的状态变量。

using A for B指令,可用于将库A的函数附加到给定类型B。这些函数将把调用者类型作为第一个参数(使用 self标识)。
// SPDX-License-Identifier: MIT

pragma solidity ^0.7;
// 0.8版本会自动检查溢出,所以用0.7
library SafeMath{
    function add(uint256 x, uint256 y) internal pure returns (uint256){
        uint256 z = x + y;
        require(z >= x, "overflow");
        return z;
    }
}
library ArrayExtener{ 
    // 为数组添加扩展
    function remove(uint256[] storage arr, uint256 index) public{
        arr[index] = arr[arr.length - 1];
        arr.pop(); //删除最后一个数
    }
}
contract TestArray {
    using SafeMath for uint;
    using ArrayExtener for uint[]; // 为数组添加一个library

    uint public Max = 2**256-1;
    uint [] public arr = [1,2,3,4];
    function testAdd(uint x, uint y) public pure returns (uint){
        return x.add(y);
        // SafeMath.add(x,y);  //或者这样写
    }

    function testArr() public{
        // for (uint i = 0; i < 4; i++){
        //     arr.push(i);
        // }
        arr.remove(1);

    }
}

5 interface
interface类似于抽象合约,但它们不能实现任何功能。还有其他限制:

无法继承其他合约或接口。
所有声明的函数必须是external的。
无法定义构造函数。
无法定义变量。
无法定义结构。
interface基本上限于合约ABI可以表示的内容,并且ABI和interface之间的转换应该是可能的,而不会丢失任何信息。
如果是接口类型,尽量加I开头

pragma solidity ^0.5.0;

// 调取外部的dog_cat合约

interface IanimalEat{
      function eat() external returns(string memory);
}

contract animal is IanimalEat{
    //可以调取外部的合约方法
    function test(address _addr) public returns(string memory){
        IanimalEat   generalEat =  IanimalEat(_addr);
        return generalEat.eat();
    }

    //可以改写
    function eat() external returns(string memory){
        return "eat eat eat";
    }
}

6 抽象合约

抽象合约前面加A(abstract)
6.1合约存在没有函数体(实现)的函数。
6.2合约不能通过编译,只能被继承。
6.3如果派生合约没有实现抽象函数,则该派生合约也将被标记为抽象合约。

pragma solidity ^0.5.0;
contract ACalculator {
   function getResult() public view returns(uint);
}
contract Test is ACalculator {
   function getResult() public view returns(uint) {
      uint a = 1;
      uint b = 2;
      uint result = a + b;
      return result;
   }
}

7 assembly
Inline Assembly是一种以较低级别访问以太坊虚拟机的方法。

address _addr = msg.sender;
uint256 _codeLength;

// 检索code的size        
assembly {_codeLength := extcodesize(_addr)}

8 delete
if() throw;
assert、require、revert

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/943207.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-18
下一篇 2022-05-18

发表评论

登录后才能评论

评论列表(0条)

保存