solidity学习二(赋值数据位置、modify、Event、receive&fallback、数组)

25 篇文章 1 订阅
22 篇文章 0 订阅

一、赋值位置
类似js中,深拷贝,浅拷贝。
1.storage状态变量 = storage状态变量,没有修改指针,而是深拷贝。

pragma solidity ^ 0.5.0;
contract Locations {
    uint[] public stateVar = [1,2]; //storage
    uint[] public stateVar2;
    function doSomething() public returns(uint) {
        stateVar2 = stateVar;
        stateVar = [3,4];
        require(stateVar2[0]==3,'equal to 3');
        return stateVar2[0]; //returns 1
    }
}

2.memory 局部变量=storage 状态变量,没有修改指针,而是深拷贝。

pragma solidity ^ 0.5.0;
contract Locations {
    uint[] public stateVar = [1,2]; //storage
    function doSomething() public returns(uint) {
        uint[] memory localVar; //memory
        localVar = stateVar;
        stateVar = [3,4];
        require(localVar[0]==1,'equal to 3');
        return localVar[0]; //1
    }
}

3.storage局部变量 = storage 状态变量
引用

pragma solidity ^0.4.0;

contract TestLoc {
    uint[] x; //  x的存储位置是storage

    // memoryArray的存储位置是 memory
    function f(uint[] memoryArray) public returns (uint[]) {
        x = memoryArray;    // 从 memory 复制到 storage

        uint[] storage y = x;          // storage 引用传递局部变量y(y 是一个 storage 引用)
        y[1] = 2;               // x y 都会被修改

        // 错误, 不能将memory赋值给局部变量
        // y = memoryArray;

        g(x);               // 引用传递, g可以改变x的内容
        h(x);               // 拷贝到memory, h无法改变x的内容
        return x;
    }

    function g(uint[] storage storageArray) internal {
        storageArray[2] = 3;
    }

    function h(uint[] memory memoryArray) public pure {
        memoryArray[2] = 4;
    }
}

5.内存变量复制到内存变量
对于引用类型的局部变量,从一个内存变量复制到另一个内存变量不会创建副本。直接修改指针,浅拷贝
memory 局部变量 = memory 局部变量 (直接修改指针,浅拷贝)
对于引用类型的局部变量,从一个内存变量复制到另一个内存变量不会创建副本。
对于值类型的局部变量仍然创建一个新副本。

pragma solidity ^ 0.5.0;
contract Locations {
    
    function doSomething() public pure returns(uint) {
        uint[] memory stateVar = new uint[](3); //storage
        stateVar[0] = 1;
        stateVar[1] = 2;
        uint[] memory localVar = stateVar; //storage
        stateVar[0] = 3;
        require(localVar[0]==1,'equal to 3');
        return localVar[0]; //returns 3
    }
}

二、函数修饰符 modifier

pragma solidity ^0.5.0;

contract Mutex{
    bool locked;
    modifier noReentrancy(){
        require(!locked, "reetrant call.");
        locked = true;
        _; // 跳回function
        locked = false; 
    }

    function withdraw() public noReentrancy {
        (bool success,) = msg.sender.call("");
        require(success);
    }
}

Inherited

pragma solidity >=0.6.0<0.8.0;

contract Base1{
   modifer foo() virtual {_;};
}
contract Base2{
   modifer foo() virtual {_;};
}
contract Inherited1 is Base1{
   modifer foo() override {_;};
}
contract Inherited2 is Base1, Base2{
   modifer foo() override(Base1, Base2) {_;};
}

三、时间Event

1.声明一个事件,按照惯例,事件名称以大写字母开头,以区别于函数。
event Deposit(address indexed _from, bytes32 indexed _id, uint _value);
2.触发事件
emit Deposit(msg.sender, _id, msg.value);
第一个参数用于存储事件签名的哈希值,这样就只剩下三个参数用于索引参数。

pragma solidity ^0.5.0;
contract Counter {
    uint256 public count = 0;
    event Increment(address who);   // 声明事件
    function increment() public {
        emit Increment(msg.sender); // 触发事件
        count += 1;
    }
}

3.js中监听

counter = web3.eth.contract(abi).at(address);
counter.Increment(function (err, result) {
  if (err) {
    return error(err);
  }
  log("Count was incremented by address: " + result.args.who);
  getCount();
});
getCount();

四、特殊函数
0.6版本后出现的2个特殊函数:receive、fallback函数
参考:https://learnblockchain.cn/article/1817
Solidity中的函数为:
function function_name(<param_type> <param_name>) [returns(<return_type>)]{ … }

但是有一种特殊的函数----回退函数,它是合约里的特殊函数,没有名字,不能有参数,没有返回值。当调用的函数找不到时,就会调用默认的fallback函数

FallBack函数的实用场景
场景一:空投
利用FallBack函数,用户只需要使用钱包向空投合约发送0金额的转账(只消耗手续费),空投合约就可以向该地址进行空投。

场景二:锁仓
用户使用钱包将代币转账到锁仓合约中,锁仓合约利用FallBack函数接收到请求,就可以执行锁仓逻辑了。

五、数组
5.1数组声明

uint [3] arr1; // 3是数组长度
uint [] memory  arr= new uint[](3); // 3是数组长度,用这种方式,数组长度不能省略

uint [2] memory arr1 = [uint(2),3];

5.2多维数组声明

uint[][5] arr;

在这里插入图片描述
5.3数组长度

uint [10] tens;  // 不能修改长度
uint[] public b = new uint[](7);  // storage类型可以通过length修改长度


memory类型数组不能修改长度、不能push
uint[] memory a = new uint[](7);
    //   a.push(10);
    //   a.length = 10;

只有storage不固定长度数组,才可以用length

5.4字符串操作


//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8;

import "github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol"; // 引入这个包

contract StringTest {
    using strings for *;
    string public myStr;
	string niceName = unicode"陈小浩同学";  
    function foo(string memory strPart) public {
        myStr = myStr.toSlice().concat(strPart.toSlice());
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端段

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值