Solidity极速入门「基础备忘」

Solidity是一门专为实现智能合约而创建的高级编程语言,在以太坊虚拟机Ethereum Virtual Machine (EVM)上运行。它与C++,Python以及JavaScript颇有渊源。

比较重要的特性:

一个简单的例子

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract BasicTest {

    uint myStoredData;
	
    function myGet() public view returns (uint) {
        return myStoredData;
    }

    function mySet(uint what) public {
        myStoredData = what;
    }

}

代码编译部署到区块链上之后,任何人只要知道了该合约的地址及函数签名,都可以修改myStoredData数据。比如,该合约地址为 0xaE036c65C649172b43ef7156b009c6221B596B8b 那么编写如下代码:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

interface BasicTest {
    function myGet() external view returns (uint);
    function mySet(uint w) external;
}

contract Super {
    BasicTest bt;
    function setAddr(BasicTest addr) public {
        bt = addr;
    }

    function test(uint w) public returns (uint) {
        bt.mySet(w);
        return bt.myGet();
    }
}

输入参数为合约地址,执行setAddr;然后输入欲改值1356,就可以修改了。

数据类型

布尔bool,整型int/uint,定长fixed/ufixed,地址address,定长字节数组,变长字节数组,枚举

需要说明的是:

函数

function () {internal|external} [pure|constant|view|payable] [returns ()]

函数的可见性

可指定为external, public, internal, 或者private

对于public和private,相信学过其他高级语言的人都能明白:

函数的状态可变性

如果你试图在一个用view或者pure修饰的函数体内修改变量,或者在一个未使用payable修饰的函数体内发送ether,那么编译的时候,就会给出错误。

内部函数调用

仅仅发生在一个合约内部。可以理解为“方法调用”。

外部函数调用

外部函数调用使用消息机制实现。外部调用事件消息包括了发送者,接收者,内容,ether数量,以及gas。

一个合约调用其它合约的函数,只有通过外部函数调用的方式,没有其它方式。

调用一个public函数,分别使用内部调用和外部调用,对比一下:

内部调用

function g1(uint a) public returns(uint ret) {
    return 44;
}

function y2() public returns(uint ret) {
    uint a = g1(100);
    for(uint i=0; i < 30; i++) {
        g1(100);
    }
    return a;
}

外部调用

function g1(uint a) public returns(uint ret) {
    return 44;
}


function y1() public returns(uint ret) {
    uint a = this.g1(100);
    for(uint i=0; i < 30; i++) {
        this.g1(100);
    }
    
    return a;
}

可以看出,所消耗的gas差别很大。

进一步试验

contract FunctionTest{
    uint public v1;
    uint public v2;
    function internalFunc() internal{
        v1 = 10;
    }
    function externalFunc() external returns (uint res){
        v2 = 20;
        return v2;
    }
    function resetV2() public {
        v2 = 0;
    }
    function callFunc() public {
        //直接使用内部的方式调用
        internalFunc();  //<--- 合约内部直接调用,正确
        //不能在内部调用一个外部函数,会报编译错误。
        //Error: Undeclared identifier.
        //externalFunc(); //<--- 外部合约不可以调用
        //不能通过`external`的方式调用一个`internal`
        //Member "internalFunc" not found or not visible after argument-dependent lookup in contract FuntionTest
        //this.internalFunc();  //<--- this.相当于外部调用
        //使用`this`以`external`的方式调用一个外部函数
        this.externalFunc();
    }
}
// 合约的继承
contract Son is FunctionTest {
    function callInternalFunc()  public{
        internalFunc();  // 可以继承父合约的内部方法
        this.externalFunc();
    }
}
contract FunctionTest1{
    uint public v3;
    function externalCall(FunctionTest ft) public {
        //调用另一个合约的外部函数
        v3 = ft.externalFunc();
        //不能调用另一个合约的内部函数
        //Error: Member "internalFunc" not found or not visible after argument-dependent lookup in contract FuntionTest
        //ft.internalFunc();
    }
    function resetV3() public {
        v3 = 0;
    }
}

最后,再看一个发送ether的例子。可以指定gas。具体如何估算,留个悬念,请见下回分解吧。

function g(uint a) public payable returns(uint ret) {
    return 44;
}

function y() public payable returns(uint ret) {
    uint a = this.g{value:11,gas:5800}(100);
    return a;
}

constructor() payable{} //必不可少

注意: payable关键字

展开阅读全文

页面更新:2024-03-10

标签:以太   定长   区块   不允许   数组   合约   变量   函数   入门   状态   方式   基础

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top