以太坊智能合约简介(Solidity)

简介: 本文略过了冗杂介绍,直接下沉到代码示例。本文中包含一个存储实例和生成极简单 subcurrency 的实例

本文会通过两个示例来简单介绍智能合约

示例一:存储(Storage)

下面这段代码实现了一个uint值的存储。

pragma solidity ^0.4.0;

contract SimpleStorage {
    uint storedData;

    function set(uint x) public {
        storedData = x;
    }

    function get() public constant returns (uint) {
        return storedData;
    }
}

在某种意义上,Solidity合约就是在以太坊区块链中特定地址内的一组代码(合约的函数)和数据(合约的state)的集合。

uint storedData;

这一行声明了一个uint(256bit的无符号整数)类型的state变量:storedData。你可以认为storedData是数据库中的一个存储单元,它可以被通过执行数据库管理代码的方式查询和修改。在以太坊中只有合约的所有者能这样做。示例代码中,setget函数可以被用于修改或检索变量的值

获取state对象,不需要像其他语言那样加this.前缀

由于此合约仅存储了一个完全公开的数字,所以它的发布是无法被阻止的。但任何人都可以通过以另一参数调用set来覆盖你刚刚保存的数字(但你写过的那个数字仍会被保存在区块链历史中)。稍后,你将看到如何设置限制以确保只有你自己可以修改这个变量的值

注意,所有标识符(如合约名,变量名,函数名等)只能使用ascii字符集。UTF-8编码的数据可以存储在字符串变量中

使用与其他字符相似的Unicode字符时需要保持小心

 

示例二:子货币Subcurrency

下面的合约将会实现一种最简单的加密货币。这里定义的货币可以凭空产生,但只有创建合约的人才有能力凭空生成货币(实现一个不同的发币计划是件微不足道的小事)。 此外,任何人都可以互相发送货币而不需要使用用户名和密码进行注册——进行所有的一切,只需要一个以太坊密钥对。

 
 
pragma solidity ^0.4.21;

contract Coin {
    // The keyword "public" makes those variables
    // readable from outside.
    address public minter;
    mapping (address => uint) public balances;

    // Events allow light clients to react on
    // changes efficiently.
    event Sent(address from, address to, uint amount);

    // This is the constructor whose code is
    // run only when the contract is created.
    function Coin() public {
        minter = msg.sender;
    }

    function mint(address receiver, uint amount) public {
        if (msg.sender != minter) return;
        balances[receiver] += amount;
    }

    function send(address receiver, uint amount) public {
        if (balances[msg.sender] < amount) return;
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        emit Sent(msg.sender, receiver, amount);
    }
}

这段合约带来了一些新的概念,以下将一一介绍

 

address public minter;声明了一个address类型的state变量,这个变量是所有人都可以读取的。address类型是一个不允许进行任何算术操作的160位值。它很适合被用来存储合约地址或属于外部个人的密钥对。关键字public会自动生成一个允许你从合约外部获取一个state变量当前值的函数。若没有这个关键字,其他合约将无法获取到这个变量。由编译器生成的代码和下面这行代码大致相同

function minter() returns (address) { return minter; }

(直接加上这句会导致编译器报错,因为此函数和state变量重名)

下一行:mapping (address => uint) public balances;

这句话创建了一个数据类型更加复杂的公共state变量——一个从地址到无符号整型的映射。此处的映射可以被看做一个虚拟初始化了的hash表,以便每个可能的密钥存在,并映射到一个字节表示全是0的值上(这个比喻不太合理,因为包含一个有映射的所有键的列表是不可能的,包含所有值也是不可能的)。因此要么保存添加到映射中的内容,要么在不需要这种内容的部分使用它(就像这句)。由public关键字创建的getter函数【注1】在这种情况下更加复杂一些。看起来大概是这样的:

function balances(address _account) public view returns (uint) {
    return balances[_account];
}

用这个函数可以轻松查询一个账户的余额

 

event Sent(address from, address to, uint amount);

这行声明了一个所谓的“event(事件)”,它被最后的send函数发出。包括服务端应用在内的用户接口可以以较低的成本监听这些被发送到区块链上的事件。一旦事件被发送,监听者就会获取到fromtoamount参数,以便监听者跟踪交易。为监听这一事件,我们会使用

 
 
Coin.Sent().watch({}, '', function(error, result) {
    if (!error) {
        console.log("Coin transfer: " + result.args.amount +
            " coins were sent from " + result.args.from +
            " to " + result.args.to + ".");
        console.log("Balances now:\n" +
            "Sender: " + Coin.balances.call(result.args.from) +
            "Receiver: " + Coin.balances.call(result.args.to));
    }
})

注意,自动生成的函数balance是怎样从用户接口调用的

 

Coin这个特殊的函数时在创建合约时调用的构造器,他不能在合约构造完成后再被调用。它永久存储了合约创建者的地址:msg(和txblock一起)。msg是一个神奇的全局变量,包含一些允许连接到区块链的属性。msg.sender永远是当前的(外部)函数调用所来自的地址。

 

这个合约中的函数可以被用户和其他合约调用,如mintsendmint只能被合约创建者进行有效的调用。而send可以被任何已经持有一些这种币的人调用来向他人进行转账。注意如果你用这个合约发送币到其他地址,你在区块链浏览器上浏览目标地址时并不会看到任何效果产生,因为你发送了币并改变余额的事实只存储于这个特定的货币合约的数据存储中。因为有了事件的使用,创建一个用于跟踪你自己的货币的交易和余额的“区块链浏览器”变得比较简单。

 

 

【注1】:getter函数时编译器为所有public的state变量自动创建的,它会返回一个uint类型的名为“data”的state变量值。状态变量的初始化可以在声明时完成。

 


相关文章
|
网络协议 Linux Android开发
解决GitHub无法访问的问题:手动修改hosts文件与使用SwitchHosts工具
解决GitHub无法访问的问题:手动修改hosts文件与使用SwitchHosts工具
1340 1
javaWeb服务详解(含源代码,测试通过,注释) ——Dept的Dao层
javaWeb服务详解(含源代码,测试通过,注释) ——Dept的Dao层
|
9月前
|
存储 关系型数据库 MySQL
【YashanDB知识库】共享从 MySQL异常处理CONTINUE HANDLER的改写方法
本文介绍了MySQL中`CONTINUE HANDLER FOR NOT FOUND`的用法及其在YashanDB中的改写方法。通过一个示例存储过程,展示了如何使用游标和异常处理机制来应对“未找到数据”的情况。在MySQL中,`CONTINUE HANDLER`用于捕获此类异常;而在YashanDB中,则需改用游标的`%NOTFOUND`属性和`NO_DATA_FOUND`异常处理。文章对比了两者的执行效果,帮助用户顺利完成从MySQL到YashanDB的业务迁移。
|
JSON 小程序 JavaScript
|
数据采集 自然语言处理 搜索推荐
python【包含数据预处理】基于词频生成词云图
背景目的 有一篇中文文章,或者一本小说。想要根据词频来生成词云图。
|
负载均衡 Java 开发者
如何在Spring Boot项目中实现微服务架构?
如何在Spring Boot项目中实现微服务架构?
1038 1
|
缓存 运维 监控
Ubuntu查看内存使用情况
Ubuntu查看内存使用情况
3317 0
|
Web App开发 前端开发 安全
前端研发链路之测试
本文由前端徐徐撰写,介绍了前端测试的重要性及其主要类型,包括单元测试、E2E测试、覆盖率测试、安全扫描和自动化测试。文章详细讲解了每种测试的工具和应用场景,并提供了选择合适测试策略的建议,帮助开发者提高代码质量和用户体验。
313 3
前端研发链路之测试
|
机器学习/深度学习 人工智能 自动驾驶
实战案例分析:AI在特定行业的深度应用
【7月更文第20天】随着人工智能技术的飞速发展,其在各行各业的应用日益广泛且深入,不仅推动了产业创新,也极大地提升了服务效率与质量。本文将聚焦于金融、教育、和交通三大领域,通过具体案例与技术解析,展现AI如何在这三个行业中发挥着革命性的作用。
2185 0
|
人工智能 搜索推荐 数据安全/隐私保护
别错过!2024年苹果iPhone AI革命:揭秘技术突破与未来蓝图
本文首发于公众号“AntDream”。2024年,苹果iPhone在技术创新方面展现了一系列亮点,包括Apple Intelligence集成、Siri的进化、系统范围的写作工具、图像生成能力、跨应用任务处理、隐私保护加强等。iOS 18带来了多项改进,如屏幕图标重新设计、新增卫星短信等功能。后续规划包括Apple Intelligence的推广、与其他AI模型合作、硬件发展、软件生态扩展、全球多语言支持等。苹果将继续优化用户体验和强化隐私保护,探索AI技术在健康监测、增强现实等领域的应用,持续引领智能手机领域的创新潮流。
827 1