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


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

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

    
    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];
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

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

    pragma solidity >=0.4.16 <0.9.0;
    
    • 1

    这个表示下面的代码适用的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() 不能作为内部函数直接调用

    下面一行,

    address public owner
    
    • 1

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

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

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

     uint storedData;
     string value;
    
    • 1
    • 2

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

    emit LogDepositMade(msg.sender, msg.value); 
    
    • 1

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

    SimpleBank.LogDepositMade().watch({}, '', function(error, result) {
        if (!error) {
            console.log("deposit to : " + result.args.accountAddress +
                " amount " + result.args.amount);
            
        }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

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

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


    参考:

    • https://docs.soliditylang.org/en/latest/
  • 相关阅读:
    优先队列与堆排序的时间复杂度分析
    【毕业设计】基于javaEE+SSH+mysql+strust2的超市积分管理系统设计与实现(毕业论文+程序源码)——超市积分管理系统
    开发工程师必备————【Day25】Django补充(二)
    dubbo 用户指南
    音视频直播开发问题分析总结 -- 花屏&绿屏
    强化学习问题(一)--- 输入conda activate base无法激活虚拟环境
    spring常见面试题总结
    微信小程序中前端 授权登录获取用户的openid
    MySQL主从复制(基于binlog日志方式)
    无硬盘的版本 1099,14寸笔记本,而且无硬盘的,特别有有意思,可以自己购买个硬盘,安装linux系统或者windows。
  • 原文地址:https://blog.csdn.net/pony_maggie/article/details/126294677