首页 > 其他分享 >Solidity基本概念学习2

Solidity基本概念学习2

时间:2023-12-06 15:15:08浏览次数:28  
标签:基本 function arr return Solidity gas uint 概念学习 public

文档: https://solidity-by-example.org/
视频教程: https://www.youtube.com/watch?v=xv9OmztShIw&list=PLO5VPQH6OWdVQwpQfw9rZ67O6Pjfo6q-p

说明

看视频没注意有文档, 前面写了一篇好多废话, 之后结合文档+视频去做笔记和写代码, 做记录...

常量(constant)

常量是不能修改的变量。它们的值是硬编码的,使用常量可以节省gas成本。

不可变变量(imutable)

不可变变量就像常量。不可变变量的值可以在构造函数内部设置,但之后不能修改。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract ConstantsAndImutable {
    // coding convention to uppercase constant variables
    address public constant MY_ADDRESS = 0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc;
    uint public constant MY_UINT = 123;

    // coding convention to uppercase constant variables
    address public immutable MY_ADDRESS2;
    uint public immutable MY_UINT2;

    constructor(uint _myUint) {
        MY_ADDRESS2 = msg.sender;
        MY_UINT2 = _myUint;
    }
}

注意这种带构造器的合约需要填入初始值才能部署, 不然会报错:
creation of Constants errored: Error encoding arguments: Error: invalid BigNumber string (argument="value", value="", code=INVALID_ARGUMENT, version=bignumber/5.7.0)
img
从显示来看的话没有太大区别:
img

对状态变量的读写

要编写或更新状态变量,需要发送一个交易(transaction)。
另一方面,可以免费读取状态变量,而无需支付任何交易费用。
实际上前面已经做过类似的操作了. 修改一下案例.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
contract StateVariable {
    uint public stateval = 123;
    function get() view external returns(uint)  {
        return stateval;
    }
    function set(uint myval) external {
        stateval = myval;
    }
}

如果是用的MetaMask的话会对这个支付费用比较敏感. 每次执行都需要用户去确认交易. 而Remix vm提供的测试号都是默认直接执行交易了.
执行前后
问题: 函数也可以用public修饰, 那么publicexternal是有什么区别?

货币单位ether和wei

交易(transaction)需要用ether支付。
类似于一美元等于100美分的方式,1个以太等于$10^{18}$ WEI。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract EtherUnits {
    uint public oneWei = 1 wei;
    // 1 wei is equal to 1
    bool public isOneWei = 1 wei == 1; // true

    uint public oneEther = 1 ether;
    // 1 ether is equal to 10^18 wei
    bool public isOneEther = 1 ether == 1e18; // true
}

gas fee (燃气费)

你需要支付多少以太币进行一笔交易?
你支付的以太币数量为 gas spent(已消耗的燃气)* gas price(每单位燃气愿意支付的以太币),其中:

  • gas 是计算的单位。
  • gas spent 是交易中使用的总燃气费用。
  • gas price 是你愿意为每单位燃气支付的以太币。
    具有更高gas price的交易在区块中具有更高的优先级。未使用的燃气将被退还。
    燃气限制
    对于你可以使用的燃气量有两个上限:
  • gas limit(你愿意在交易中使用的最大燃气量,由你设置)
  • block gas limit(区块中允许的最大燃气量,由网络设置)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// 用死循环去测试gas的返还
contract Gas {
    uint public i = 0;
    // Using up all of the gas that you send causes your transaction to fail.
    // State changes are undone.
    // Gas spent are not refunded.
    function forever() public {
        // Here we run a loop until all of the gas are spent
        // and the transaction fails
        while (true) {
            i += 1;
        }
    }
}

执行forever后

if/else, 三元运算符

跟Java和C一样的.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract IfElse {
    function foo(uint x) public pure returns (uint) {
        if (x < 10) {
            return 0;
        } else if (x < 20) {
            return 1;
        } else {
            return 2;
        }
    }

    function ternary(uint _x) public pure returns (uint) {
        // if (_x < 10) {
        //     return 1;
        // }
        // return 2;

        // shorthand way to write if / else statement
        // the "?" operator is called the ternary operator
        return _x < 10 ? 1 : 2;
    }
}

for, while, do-while

循环结构也跟Java, C类似

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Loop {
    function loop() public {
        // for loop
        for (uint i = 0; i < 10; i++) {
            if (i == 3) {
                // Skip to next iteration with continue
                continue;
            }
            if (i == 5) {
                // Exit loop with break
                break;
            }
        }

        // while loop
        uint j;
        while (j < 10) {
            j++;
        }
    }
}

Mapping

使用语法(keyType => valueType)创建映射。
keyType可以是任何内置值类型、字节、字符串或任何合约。valueType可以是任何类型,包括另一个MappingArrayMapping是不可迭代的。
Mapping貌似不能作为返回类型, 会报错:
TypeError: Data location must be "memory" or "calldata" for return parameter in function, but none was given.

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

contract Mapping {
    mapping (address => uint) public myMap; // 用于观察
    // Mapping 总会返回值.
    // If the value was never set, it will return the default value.
    function get(address key) public view returns(uint) {
        return myMap[key]; // 2885 gas
    }
    function set(address key, uint val) public {
        myMap[key] = val; // 22854 gas
    }
    function remove(address key) public {
        delete myMap[key]; // 5554 gas
    }
}
contract NestedMapping {
    mapping (address => mapping(uint => bool)) public nestedMap;
    function get(address addr, uint _i) public view returns(bool){
        return nestedMap[addr][_i]; // 3178 gas
    }
    function set(address addr, uint _i, bool _b) public {
        nestedMap[addr][_i] = _b;  // 25217 gas
    }
    function remove(address addr, uint _i) public {
        delete nestedMap[addr][_i]; // 25060 gas
    }
}

随便找个地址测着玩就行, 按照两个合约和上面提到的报错来看, 我们没法一次获取整个Mapping的值?
img

Array

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Array {
    // Several ways to initialize an array
    uint[] public arr;
    uint[] public arr2 = [1, 2, 3];
    // Fixed sized array, all elements initialize to 0
    uint[10] public myFixedSizeArr;

    function get(uint i) public view returns (uint) {
        return arr[i];
    }

    // Solidity can return the entire array.
    // But this function should be avoided for
    // arrays that can grow indefinitely in length.
    function getArr() public view returns (uint[] memory) {
        return arr;
    }

    function push(uint i) public {
        // Append to array
        // This will increase the array length by 1.
        arr.push(i);
    }

    function pop() public {
        // Remove last element from array
        // This will decrease the array length by 1
        arr.pop();
    }

    function getLength() public view returns (uint) {
        return arr.length;
    }

    function remove(uint index) public {
        // Delete does not change the array length.
        // It resets the value at index to it's default value,
        // in this case 0
        delete arr[index];
    }

    function examples() external pure  {
        // create array in memory, only fixed size can be created
        uint[] memory a = new uint[](5);
    }
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract ArrayRemoveByShifting {
    // [1, 2, 3] -- remove(1) --> [1, 3, 3] --> [1, 3]
    // [1, 2, 3, 4, 5, 6] -- remove(2) --> [1, 2, 4, 5, 6, 6] --> [1, 2, 4, 5, 6]
    // [1, 2, 3, 4, 5, 6] -- remove(0) --> [2, 3, 4, 5, 6, 6] --> [2, 3, 4, 5, 6]
    // [1] -- remove(0) --> [1] --> []

    uint[] public arr;

    function remove(uint _index) public {
        require(_index < arr.length, "index out of bound");

        for (uint i = _index; i < arr.length - 1; i++) {
            arr[i] = arr[i + 1];
        }
        arr.pop();
    }

    function test() external {
        arr = [1, 2, 3, 4, 5];
        remove(2);
        // [1, 2, 4, 5]
        assert(arr[0] == 1);
        assert(arr[1] == 2);
        assert(arr[2] == 4);
        assert(arr[3] == 5);
        assert(arr.length == 4);

        arr = [1];
        remove(0);
        // []
        assert(arr.length == 0);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract ArrayReplaceFromEnd {
    uint[] public arr;

    // Deleting an element creates a gap in the array.
    // One trick to keep the array compact is to
    // move the last element into the place to delete.
    function remove(uint index) public {
        // Move the last element into the place to delete
        arr[index] = arr[arr.length - 1];
        // Remove the last element
        arr.pop();
    }

    function test() public {
        arr = [1, 2, 3, 4];

        remove(1);
        // [1, 4, 3]
        assert(arr.length == 3);
        assert(arr[0] == 1);
        assert(arr[1] == 4);
        assert(arr[2] == 3);

        remove(2);
        // [1, 4]
        assert(arr.length == 2);
        assert(arr[0] == 1);
        assert(arr[1] == 4);
    }
}

示例代码自己部署自己玩.

标签:基本,function,arr,return,Solidity,gas,uint,概念学习,public
From: https://www.cnblogs.com/joey-redfield/p/17879571.html

相关文章

  • Python基础之Python基本构成
    【一】注释语法【1】什么是注释注释就是就是对代码的解释说明,注释的内容不会被当作代码运行【2】为什么要注释增强代码的可读性【3】如何使用注释代码注释分单行和多行注释1、单行注释用#号,可以跟在代码的正上方或者正后方#这是一段通过“#+注释内容”创造的注......
  • 基本黑客技术
    一、SQL注入1.1看看是否有sql注入漏洞加个引号可以看出来1.2判断是数字注入还是字符注入字符:admin'and1=1#数字:adminand1=11.3获得数据库的信息:数据库名、表名、字段名、对应信息1.3.1首先获得这个表的字段数量admin'and1=1orderby[num]#这个字段自己试......
  • 实验6熟悉的hive的基本操作
    今天完成了大数据实验六的hive的基本操作参照实验6熟悉Hive的基本操作_hive环境搭建实验报告-CSDN博客、这位博主的代码,但是前期的启动hive并没有按照博主的来,启动hive大家参照我之前的一篇博客来就行我是从黑马教程跟着下载的hiveHIVe的启动以及datagrip配置-王庆园-博客......
  • 指针(2)指针基本了解及其应用
    <1>指针(1)指针基本概念1)引入:提出问题:如果能够将取得的变量的地址传递给一个函数,能否通过这个地址在那个函数内访问这个变量2)回顾scanf函数功能格式:scanf("%d",&i)深入探讨:scanf()的原型应该是怎样的?我们需要一个参数能保存别的变量的地址,如何表达能够保存地址的变量?......
  • Solidity初学
    https://www.youtube.com/watch?v=xv9OmztShIw&list=PLO5VPQH6OWdVQwpQfw9rZ67O6Pjfo6q-phelloworld//SPDX-License-Identifier:MIT//如果没有上面的license就会出现黄色warning,挺难看的..pragmasolidity^0.8;//指定solidity编译版本,带了^号说明要在该版本(0.8)......
  • Border 基本使用
    Border基本使用1单线效果  代码:<BorderGrid.Row="0"BorderThickness="0,0,0,1"BorderBrush="Red"/>说明:BorderThickness="0,0,0,1"可以分别设置四条边,顺序是:左上右下2虚线效果  代码:<BorderGrid.Row="0"BorderThick......
  • C语言中的基本数据类型及其格式化输出
    C语言中的基本数据类型及其格式化输出基本数据类型从下图可以看出,C语言中的基本数据类型包括了整型(int)、字符型(char)、浮点型(float)和双精度浮点型(double)。在声明变量时,不同数据类型都会分配不同的存储空间,而且还跟操作系统有关。char//有符号字符型,1个字节u......
  • HTML学习笔记一:html简介和基本结构
    HTML学习笔记一一、什么是HTML?众所众知,我们打开的网页是一个一个的HTML,网页静态的结构是由html完成,而各式各样的表现样式是由css完成,至于网页与服务器之间的交互行为则都交给了javascript完成。HTML和CSS本质都是结构化、标准化的语言,用于定义页面结构,样式渲染。不得不提的就是......
  • Form表单的基本使用
    原文链接:https://blog.csdn.net/weixin_52851967/article/details/1285231741、什么是表单        表单在网页中主要负责数据采集功能。HTML中的<form>标签,就是用于采集用户输入的信息,并通过<form>标签的提交操作,把采集到的信息提交到服务器端进行处理。2、表单的组成部......
  • 文件的基本操作
    文件的基本操作1.操作文件打开的两种方式#1.文件的操作方式一:#讲文件以指定编码格式打开,讲文件句柄赋值给变量fpfp=open('01.txt','w',encoding='utf-8')#把hello写入文件fp.write("hello")#关闭文件fp.close()2.文件的操作方式二:#Python解释器内置了一个文......