以太坊智能合约简介(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变量值。状态变量的初始化可以在声明时完成。

 


相关文章
|
10月前
|
JSON 监控 API
小红书API接口的应用场景介绍
小红书API基于RESTful架构,支持HTTP协议与JSON格式,采用OAuth 2.0认证,实现内容数据获取、自动化发布、用户认证集成及实时舆情监控。开发者可借助API进行热度分析、KOL识别、跨平台登录与品牌告警,提升运营效率与决策能力。(238字)
1814 1
|
10月前
|
机器学习/深度学习 自然语言处理 算法
基于NLP与深度学习的智能面试训练系统深度解析:技术架构与核心算法
本文深入解析AI驱动的智能面试系统,涵盖基于NLP与深度学习的架构设计、核心算法及工程优化。从简历解析、多模态情感分析到行为预测,揭示技术落地细节,助力开发者构建高效、精准的招聘面试解决方案。
|
10月前
|
存储 前端开发 数据处理
《开发者必看的应用商店突围实战手册》
本文聚焦编程工具上架应用商店的全流程实战,拆解工具从审核通关到冷启动增长的核心逻辑。文章指出,多数编程工具上架遇阻或曝光低迷,根源在于忽视平台生态规则与用户决策逻辑,而非技术硬伤。核心围绕生态适配、合规打磨、体验优化、上架材料构建、审核应对、冷启动推广六大关键环节,详解如何精准匹配不同应用商店属性、把控数据隐私与权限合规细节、优化核心功能触达与使用体验、打造高转化上架材料、高效应对审核问题,以及通过平台资源对接、技术社区推广、生态联动实现用户增长。强调上架不是终点,而是技术价值落地的起点,唯有兼顾平台规则、用户需求与持续迭代,才能让优质编程工具突破隐性门槛,在海量应用中脱颖而出。
278 5
|
9月前
|
人工智能 编解码 测试技术
2025年主流云真机平台多机型兼容性稳定性及回归测试能力对比
文章聚焦2025年主流云真机平台,对比其多机型兼容性、长时间稳定性及回归测试能力。指出不同平台在这些方面存在显著差异,企业选型要结合自身需求。还解析了各核心能力要点,给出主流平台能力对比表格,介绍技术趋势,解答常见选型等问题。
|
9月前
|
Shell Linux 开发工具
Linux Shell别名配置(轻松提升你的终端操作效率)
本文介绍了Linux Shell别名(alias)的使用方法,帮助用户通过设置快捷命令提升终端操作效率。内容涵盖临时与永久别名配置、常用命令示例、查看删除方式及命名建议,适用于Bash和Zsh环境,是提高工作效率的实用技巧。(238字)
|
安全 关系型数据库 MySQL
MySQL数据库安全配置的基础规范
以上提供了针对于常见搜索引擎索引标准符合度高且实践价值显著易实施方案集锦; 这些步骤若得当执行将大幅度增进您所管理MYSQL 数据库环境稳固度与抗风险能力。
271 10
|
人工智能 测试技术 开发者
北大李戈团队提出大模型单测生成新方法,显著提升代码测试覆盖率
【9月更文挑战第27天】北京大学李戈团队在人工智能领域取得重要突破,提出HITS新方法,通过将待测方法分解为多个切片并利用大型语言模型逐个生成测试用例,显著提升代码测试覆盖率,尤其在处理复杂方法时效果显著,为软件开发和测试领域带来新希望。尽管存在一定局限性,HITS仍展示了巨大潜力,未来有望克服限制,推动软件测试领域的创新发展。论文详情见【https://www.arxiv.org/pdf/2408.11324】。
886 6
|
机器学习/深度学习 编解码 监控
《深度解析转置卷积:原理与多元应用场景》
转置卷积(反卷积)是深度学习中用于上采样的重要操作,通过在输入间插入零填充以放大特征图。它广泛应用于图像生成、语义分割、超分辨率重建和CNN可视化等领域,能够学习更优的上采样方式。尽管计算成本较高且可能引入伪像,但其在多个任务中发挥着关键作用,并随着技术发展不断优化。
725 5
|
IDE JavaScript 编译器
《Solidity 简易速速上手小册》第2章:搭建 Solidity 开发环境(2024 最新版)
《Solidity 简易速速上手小册》第2章:搭建 Solidity 开发环境(2024 最新版)
3976 0
|
数据挖掘 Linux iOS开发
Pandas
【7月更文挑战第4天】Pandas
1289 59