用一个示例入门solidity编程语言

2023-02-24 10:37:07 浏览数 (1)

我们拿上一篇文章的示例程序作为切入点,来了解一下solidity的主要语法。需要说明的是这篇文章不是solidity的手册,不会把语言所有的语法点都覆盖,需要查看手册可以看文章最后的参考链接。

上一篇文章我们的实例程序如下,这是一个简单的模拟银行的智能合约。

代码语言:javascript复制
pragma solidity 0.6.6;

contract SimpleBank { 

    mapping (address => uint) private balances;

    address public owner;

    event LogDepositMade(address accountAddress, uint amount);

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


    function deposit() public payable returns (uint) {
        require((balances[msg.sender]   msg.value) >= balances[msg.sender]);

        balances[msg.sender]  = msg.value;

        emit LogDepositMade(msg.sender, msg.value); // fire event

        return balances[msg.sender];
    }


    function withdraw(uint withdrawAmount) public returns (uint remainingBal) {
        require(withdrawAmount <= balances[msg.sender]);


        balances[msg.sender] -= withdrawAmount;

        msg.sender.transfer(withdrawAmount);

        return balances[msg.sender];
    }

    function balance() view public returns (uint) {
        return balances[msg.sender];
    }
}

第一行,pragma solidity 0.6.6指明了我们的代码使用的是solidity的0.6.6版本,也可以写成下面的形式:

代码语言:javascript复制
pragma solidity >=0.4.16 <0.9.0;

这个表示下面的代码适用的solidity版本是大于等于0.4.16,但是要小于0.9.0。

这一行其实是给编译器看的,让编译器使用正确的版本编译我们的代码。

接下来的contract那一行,有点像我们在其他编程语言用的class关键字,声明我们接下来的代码是个contract。contract可以认为是一个代码(code)和数据(data)的集合。

接下来是mapping (address => uint) private balances,这是一个key-value类型,key是address类型(下面讲),value是uint类型。这里声明了一个mapping类型的变量balance表示余额。private表示这个变量只能在合约内部访问,在合约外部或者派生合约都不能访问。除了private,还有public,external和internal这几个类型。

  • public 内部外部都可以调用,会自动生成getter函数
  • internal 和private类似,区别在于派生合约
  • external 定义的外部函数可以被其它合约调用。用 external 修饰的外部函数 function() 不能作为内部函数直接调用

下面一行,

代码语言:javascript复制
address public owner

address是一种比较特殊的类型,它有20个字节长度,一般用来表示地址或者账户的公钥信息。需要注意的是,虽然看起来它是一个数字的类型,但是它不支持任何的算术运算操作。比如 和-。

这个owner用来表示合约持有者的地址。

也可以是下面这样的基本类型,

代码语言:javascript复制
 uint storedData;
 string value;

接下来一行event LogDepositMade(address accountAddress, uint amount);,然后在下面有一个调用,

代码语言:javascript复制
emit LogDepositMade(msg.sender, msg.value); 

这里首先是声明了一个事件,然后通过emit触发事件的执行。有事件一般就有对用的监听者(listeners),比如我们可以使用web3.js(这个后面会讲)来监听,示例如下:

代码语言:javascript复制
SimpleBank.LogDepositMade().watch({}, '', function(error, result) {
    if (!error) {
        console.log("deposit to : "   result.args.accountAddress  
            " amount "   result.args.amount);

    }
})

constructor是构造方法,这个比较好理解,其他编程语言一般也有这个。构造方法只会在程序启动的时候调用一次,这里是把owner变量赋值为msg.sender,后者是一个约定的内部变量,表示的是方法的调用者。在这里当然就是指合约的创建人。

deposit是一个方法,表示存钱。这里首先需要我们关注的是payable这个关键字。被这个关键字修饰的方法可以在调用的时候接收ETH。这个方法的首先检查发送的ETH值要必须大于0,然后更新余额,出发日志事件,最后返回余额。

withdraw方法的逻辑是取钱。逻辑也很简单,不多说。balance方法就是返回余额,有一个关键字view,表示这是一个只读的方法,调用这种方法不消耗GAS。


参考:

  • https://docs.soliditylang.org/en/latest/

0 人点赞