marser

marser 查看完整档案

长沙编辑  |  填写毕业院校  |  填写所在公司/组织 www.marser.cn 编辑
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

marser 收藏了文章 · 2019-03-05

收藏了8年的PHP优秀资源,都给你整理好了

最后更新于 2020.02.06

以下是我整理好的 PHP 资源,各位看官拿去用,不用再自己找了。

GitHub 上稳定更新,觉得不错请点个 Star ❤️

如转载分享,请保留出处,谢谢 😆

原文地址: https://shockerli.net/post/ph...

GitHub: https://github.com/shockerli/...

资源站点

项目框架

  • laravel-admin - 快速构建后台管理的开发工具
  • Voyager - Laravel 后台管理框架
  • FastAdmin - 基于 ThinkPHP5 + Bootstrap 的极速后台开发框架
  • YFCMF - 后台内容管理框架,基于 ThinkPHP5.1
  • ThinkCMF - 后台内容管理框架,基于 ThinkPHP5
  • RhaPHP - 微信开发、小程序开发、微信公众号管理系统
  • OneBase - 基于 ThinkPHP5 的后台开发框架

成品软件

未归类

CMS

  • Grav - 基于文件的 CMS
  • October - 基于 Laravel 开发的 CMS

社区

  • Flarum - 基于 PHP 和 Mithril.js 开发的轻社区
  • PHPDish - 基于 Symfony 框架开发的内容社区系统
  • Koel - 音乐社区🎵

文件管理

微信相关

项目管理

构建/部署

  • Phabricator - 用于敏捷开发的项目管理软件, 含代码托管、Code Review、任务管理、文档管理、问题跟踪、构建与持续集成、博客、内部聊天等

  • Walle - Web系统部署工具
  • Piplin - 持续集成系统
  • Phing - PHP项目构建工具
  • Deployer - PHP项目部署工具
  • PHPCI - 持续集成工具

基础框架

类库

未归类

路由

异步/协程

  • Amp - 非阻塞协程并发框架
  • Recoil - 异步协程框架
  • Promise - Promises/A implementation for PHP
  • Guzzle Promises - Promises/A+ library for PHP with synchronous support

前端相关

  • PHP-CSS-Parser - PHP 实现的 CSS 解析器
  • Minify - JS 和 CSS 压缩工具
  • Munee - 一个集图片尺寸调整、CSS-JS 合并/压缩、缓存等功能于一身的PHP库

聊天/短信

文本处理

算法

语法解析

代码检查/静态分析

CLI

错误/异常

调试工具

API

  • phprs - 一款轻量、类 jax-rs、实用的 PHP 框架
  • graphql-php - GraphQL 参考实现的 PHP 移植版本
  • Dingo API - A RESTful API package for the Laravel and Lumen frameworks

安全

加密/解密

时间/日期

  • Chinese calendar - 中国农历(阴历)与阳历(公历)转换与查询工具
  • Carbon - 时间日期处理类

微信

网页抓取/代理

URL/Domain

OAuth

Auth

  • jwt-auth - JSON Web Token Authentication for Laravel & Lumen

API文档

数据库

队列/任务

  • RoboTask - 面向对象的 PHP 任务运行器
  • PHP-Queue - 管理队列后端的应用
  • RoboTask - PHP 后台任务组件
  • Task - 一个灵感来源于 Grunt 和 Gulp 的纯 PHP 任务运行器
  • php-resque - PHP 版Resque
  • taskPHP - 基于原生态 PHP 开发的定时计划任务框架
  • SimpleFork - 精简的 PHP 多进程控制库

缓存

Markdown

邮件

Office

PDF/条形码

  • Barcode - Barcode 生成工具
  • Snappy - 根据 URL 或 HTML 页面生成图片或 PDF 格式的缩略图
  • TCPDF - 使用官方 PDF 类生成 PDF 文档和条形码生成工具
  • FPDF - 利用纯 PHP 代码生成 PDF 文件
  • PDFParser - PDF 文档解析库
  • Dompdf
  • Browsershot - 将 HTML 转换为图像、PDF 或字符串

HTTP/网络通信

表单校验

测试框架

模板引擎

图像处理

Composer

最好用的 PHP 包管理器,没有之一

PHP 扩展

  • pickle - PHP 扩展安装工具
  • PHPTrace - 跟踪和分析 PHP 脚本的工具
  • Zephir - 编写 PHP 扩展的编程语言
  • Yaconf - 高性能的配置管理扩展
  • php-beast - PHP 源码加密模块

PHP相关软件/工具


感谢您的阅读,觉得内容不错,点个赞吧 😆

原文地址: https://shockerli.net/post/ph...
查看原文

marser 关注了专栏 · 2019-02-25

阿里云栖号

汇集阿里技术精粹-yq.aliyun.com

关注 11805

marser 关注了专栏 · 2018-08-09

PHP Zendo

PHP开发者的学习苦旅

关注 635

marser 关注了专栏 · 2018-08-06

四魂之域

在学习和工作中成长。

关注 989

marser 发布了文章 · 2018-04-25

以太坊智能合约开发第七篇:智能合约与网页交互

原文发表于:以太坊智能合约开发第七篇:智能合约与网页交互

上一篇中,我们通过truffle开发框架快速编译部署了合约。本篇,我们将来介绍网页如何与智能合约进行交互。

编写网页

首先我们需要编写一个网页。打开 smartcontract/app/index.html 文件,修改 head 区代码如下:

<head>
  <title>Hello - Truffle</title>
  <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  <!-- 可选的 Bootstrap 主题文件(一般不用引入) -->
  <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
  <script data-original="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
  <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
  <script data-original="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
  <script data-original="./app.js"></script>
</head>

修改 body 区代码如下:

<body>
  <div class="alert alert-success" role="alert" style="display:none;" id="message-box"></div>
  <div class="form-group">
    <input type="text" class="form-control" id="username" aria-describedby="basic-addon1">
  </div>
  <button type="submit" id="submit" class="btn btn-success">调用合约</button>
  <button type="submit" id="cancel" class="btn btn-default">重置</button>
</body>

网页呈现效果如下图:
demo

修改启动脚本

smartcontract/app/javascripts/app.js 脚本文件是智能合约与网页交互的核心,修改代码如下:

//导入CSS
import "../stylesheets/app.css";
//导入web3和truffle-contract库
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'

//导入Hello合约的ABI文件
import Hello_artifacts from '../../build/contracts/Hello.json'
//获取Hello合约对象
var HelloContract = contract(Hello_artifacts);

window.App = {
  init: function() {
    //设置web3连接
    HelloContract.setProvider(web3.currentProvider);
  },

  //封装合约中的say()方法调用过程,供javascript调用
  say: function(name, callback){
    //instance为Hello合约部署实例
    HelloContract.deployed().then(function(instance){
      //调用Hello合约中的say()方法,并传入参数name
      instance.say.call(name).then(function(result){
        //将返回结果传入回调函数
        callback(null, result);
      });
    }).catch(function(e){
      console.log(e, null);
    });
  }
};

window.addEventListener('load', function() {
  //设置web3连接  http://127.0.0.1:7545 为Ganache提供的节点链接
  window.web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:7545"));
  App.init();
});

前面的篇幅中,我们提到过 web3模块是以太坊提供的工具包,主要用于与合约的通信。从上面的代码中,我们可以看到,通过Hello合约的ABI文件获取到合约对象之后,再配合web3工具,就可以与Hello合约进行通信了。其中 App.say() 是对Hello合约中say()方法的调用过程进行了封装,方便前端代码进行调用。

智能合约与网页交互

启动脚本修改完了之后,就需要与网页进行整合。我们再返过来继续修改 smartcontract/app/index.html 文件。在文件末尾添加如下交互代码:

<script>
  $(document).ready(function(){
      $('#submit').on('click', function(){
          var username = $('#username').val();
          if(typeof username == 'undefined' || username == false){
              alert('不能为空');
          }else {
                //调用App的say()方法
              window.App.say(username, function (err, result) {
                  if(err){
                      alert(err);
                  }else {
                      $('#username').val(username);
                      $('#message-box').html(result);
                      $('#message-box').show();
                  }
              });
          }
      });
      $('#cancel').on('click', function(){
          $('#username').val('');
          $('#message-box').hide();
          $('#message-box').html('');
      });
  });
</script>

接下来,就是见证奇迹的时刻。
smartcontract 目录下执行 npm run dev
npm run dev

注意图中标识的部分。http://locahost:8083 为网页访问地址(每个人运行的端口号可能不一样)。我们也能看出,truffle开发框架集成了 webpack 工具,对网页中包含的静态资源文件进行了打包。

最后,我们通过浏览器打开 http://locahost:8083 来测试下效果:
Hello

至此,一个简单的Dapp应用示例就此完成了。我们也熟练掌握了通过truffle开发框架编写合约代码、快速编译部署、构建Dapp的整个过程。

我的专栏:智能合约
智能合约开发QQ群:753778670
智能合约开发QQ群

查看原文

赞 3 收藏 2 评论 0

marser 收藏了文章 · 2018-04-23

一行代码蒸发了¥6,447,277,680 人民币!

一行代码蒸发了¥6,447,277,680 人民币!

现在进入你还是先行者,最后观望者进场才是韭菜。

美图董事长蔡文胜曾在三点钟群,高调的说出了这句话,随即被大众疯传。

在他发表完言论没多久,2月美链(BEC)上交易所会暴涨4000%,后又暴跌。尽管他多次否认,聪明的网友早已扒出,他与BEC千丝万缕的关系。

庄家坐庄操控币价,美图的股价随之暴涨,蔡文胜顺利完成了他的韭菜收割大计。

但在币圈,割人者,人恒割之。

随着BEC智能合约的漏洞的爆出,被黑客利用,瞬间套现抛售大额BEC,6亿在瞬间归零。

而这一切,竟然是因为一个简单至极的程序Bug。

背景

今天有人在群里说,Beauty Chain 美蜜 代码里面有bug,已经有人利用该bug获得了 57,896,044,618,658,100,000,000,000,000,000,000,000,000,000,000,000,000,000,000.792003956564819968 个 BEC

那笔操作记录是 0xad89ff16fd1ebe3a0a7cf4ed282302c06626c1af33221ebe0d3a470aba4a660f

下面我来带大家看看,黑客是如何实现的!

我们可以看到执行的方法是 batchTransfer

那这个方法是干嘛的呢?(给指定的几个地址,发送相同数量的代币)

整体逻辑是

你传几个地址给我(_receivers),然后再传给我你要给每个人多少代币(_value)

然后你要发送的总金额 = 发送的人数* 发送的金额

然后 要求你当前的余额大于 发送的总金额

然后扣掉你发送的总金额

然后 给_receivers 里面的每个人发送 指定的金额(_value)

从逻辑上看,这边是没有任何问题的,你想给别人发送代币,那么你本身的余额一定要大于发送的总金额的!

但是这段代码却犯了一个很傻的错!

代码解释

这个方法会传入两个参数

  1. _receivers
  2. _value

_receivers 的值是个列表,里面有两个地址

0x0e823ffe018727585eaf5bc769fa80472f76c3d7

0xb4d30cac5124b46c2df0cf3e3e1be05f42119033

_value 的值是 8000000000000000000000000000000000000000000000000000000000000000

我们再查看代码(如下图)

我们一行一行的来解释

uint cnt = _receivers.length;

是获取 _receivers 里面有几个地址,我们从上面可以看到 参数里面只有两个地址,所以 cnt=2,也就是 给两个地址发送代币

uint256 amount = uint256(cnt) * _value;

uint256

首先uint256(cnt) 是把cnt 转成了 uint256类型

那么,什么是uint256类型?或者说uint256类型的取值范围是多少...

uintx 类型的取值范围是 0 到 2的x次方 -1

也就是 假如是 uint8的话

则 uint8的取值范围是 0 到 2的8次方 -1

也就是 0 到255

那么uint256 的取值范围是

0 - 2的256次方-1 也就是 0 到115792089237316195423570985008687907853269984665640564039457584007913129639935

python 算 2的256次方是多少

那么假如说 设置的值超过了 取值范围怎么办?这种情况称为溢出

举个例子来说明

因为uint256的取值太大了,所以用uint8来 举例。。。

从上面我们已经知道了 uint8 最小是0,最大是255

那么当我 255 + 1 的时候,结果是啥呢?结果会变成0

那么当我 255 + 2 的时候,结果是啥呢?结果会变成1

那么当我 0 - 1 的时候,结果是啥呢?结果会变成255

那么当我 0 - 2 的时候,结果是啥呢?结果会变成255

那么 我们回到上面的代码中,

amount = uint256(cnt) * _value

则 amount = 2* _value

但是此时 _value 是16进制的,我们把他转成 10进制

(python 16进制转10进制)

可以看到 _value = 57896044618658097711785492504343953926634992332820282019728792003956564819968

那么amount = _value*2 = 115792089237316195423570985008687907853269984665640564039457584007913129639936

可以在查看上面看到 uint256取值范围最大为 115792089237316195423570985008687907853269984665640564039457584007913129639935

此时,amout已经超过了最大值,溢出 则amount = 0

下一行代码
require(cnt > 0 && cnt <= 20);
require 语句是表示该语句一定要是正确的,也就是 cnt 必须大于0 且 小于等于20

我们的cnt等于2,通过!

require(_value > 0 && balances[msg.sender] >= amount);

这句要求 _value 大于0,我们的_value是大于0 的
且,当前用户拥有的代币余额大于等于 amount,因为amount等于0,所以 就算你一个代币没有,也是满足的!

balances[msg.sender] = balances[msg.sender].sub(amount);

这句是当前用户的余额 - amount

当前amount 是0,所以当前用户代币的余额没有变动

for (uint i = 0; i < cnt; i++) {
    balances[_receivers[i]] = balances[_receivers[i]].add(_value);
    Transfer(msg.sender, _receivers[i], _value);
}

这句是遍历 _receivers中的地址,
对每个地址做以下操作

` balances[_receivers[i]] = balances[_receivers[i]].add(_value);
`
_receivers中的地址 的余额 = 原本余额+value

所以 _receivers 中地址的余额 则加了57896044618658097711785492504343953926634992332820282019728792003956564819968 个代币!!!

`Transfer(msg.sender, _receivers[i], _value);
}`
这句则只是把赠送代币的记录存下来!!!

总结

就一个简单的溢出漏洞,导致BEC代币的市值接近归0

那么,开发者有没有考虑到溢出问题呢?

其实他考虑了,

可以看如上截图

除了amount的计算外, 其他的给用户转钱 都用了safeMath 的方法(sub,add)

那么 为啥就偏偏这一句没有用safeMath的方法呢。。。

这就要用写代码的人了。。。

啥是safeMath

safeMath 是为了计算安全 而写的一个library

我们看看他干了啥?为啥能保证计算安全.

function mul(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}

如上面的乘法.
他在计算后,用assert 验证了下结果是否正确!

如果在上面计算 amount的时候,用了 mul的话,
c / a == b
也就是 验证 amount / cnt == _value

这句会执行报错的,因为 0 / cnt 不等于 _value

所以程序会报错!

也就不会发生溢出了...

那么 还有一个小问题,这里的assertrequire 好像是干的同一件事

都是为了验证 某条语句是否正确!

那么他俩有啥区别呢?

用了assert的话,则程序的gas limit 会消耗完毕

而require的话,则只是消耗掉当前执行的gas

总结

那么 我们如何避免这种问题呢?

我个人看法是

  1. 只要涉及到计算,一定要用safeMath
  2. 代码一定要测试!
  3. 代码一定要review!
  4. 必要时,要请专门做代码审计的公司来 测试代码

这件事后需要如何处理呢?

目前,该方法已经暂停了(还好可以暂停)所以看过文章的朋友 不要去测试了...

不过已经发生了的事情咋办呢?

我的想法是,快照在漏洞之前,所有用户的余额情况

然后发行新的token,给之前的用户 发送等额的代币...

查看原文

marser 收藏了文章 · 2018-04-14

以太坊智能合约开发:实现转账退费

在以太坊智能合约开发时,可能会有以下需求:

仅接受用户转入指定价值的eth,如果用户转入eth较少,则直接返回异常,当用户转入eth较多,则将用户多转入的eth退回。

在这里我们可以借助 fallback function,也就是后备函数进行转入金额的限定,示例如下:

代码示例
contract Refund {
    
    address owner = 0x0;
  
    uint256 ticket = 1 ether;    // 一个eth
      
    // 合约构造函数
    // 第一次部署合约时,会调用该方法。
    // 之后执行合约不会调用。
    function Refund() public payable {
        // 将部署合约的地址作为合约拥有者
        owner = msg.sender;
    }
  
    // 后备函数
    function () public payable {
          require(msg.value >= ticket);
          if (msg.value > ticket) {
               var refundFee = msg.value - ticket;
            msg.sender.transfer(refundFee);
        }
    }
}
代码解释

public : 函数可见性

payable :可支付的函数修饰符,没有该修饰符无法接受转账操作。

msg.value :执行合约时,转账的eth数量,以wei为单位。

msg.sender : 执行合约的地址

<address>.transfer(uint256):给指定地址<address>进行转账

sendtransfer 的区别

<address>.transfer(uint256 amount)

发送给定数量的wei给指定地址,错误时抛出异常

<address>.send(uint256 amount) returns (bool)

发送给定数量的wei给指定地址,错误时返回false

查看原文

marser 发布了文章 · 2018-04-13

以太坊智能合约开发第六篇:truffle开发框架

原文发表于:以太坊智能合约开发第六篇:truffle开发框架

在前面几篇教程中,我们实现了一个简单的 Hello 合约,并通过 solc 编译器将合约代码编译后,部署在私有链Ganache上。本篇将介绍通过truffle框架来构建自动编译、部署合约代码。

truffle框架

Truffle是基于Solidity语言的一套开发框架,它简化了去中心化应用(Dapp)的构建和管理流程。本身是采用Javascript编写,支持智能合约的编译、部署和测试。
truffle开发框架提供了很多功能,简化了我们的开发、编译、部署与调试过程:

  • 内置了智能合约编译、链接、部署和二进制文件的管理
  • 方便快速开发的合约自动化测试
  • 方便扩展的、脚本化的部署与发布框架
  • 方便的网络管理功能。不论是公有网络还是私有网络
  • 基于ERC190标准,使用EthPM & NPM进行依赖包管理
  • 内置控制台功能。项目构建后,可以直接在命令行调用输出结果,方便了开发调试
  • 可配的构建流程,支持持续集成。
  • 支持外部脚本的执行

接下来,我们将通过truffle框架来构建 Hello 合约的编译、部署过程。

truffle安装

npm install -g truffle

安装好后,查看一下版本信息:

truffle version

本篇示例基于如下版本:

Truffle v4.0.1 (core: 4.0.1)
Solidity v0.4.18 (solc-js)

初始化项目

truffle提供了很多项目模板,可以快速搭建一个去中心化应用的代码骨架。我们使用 webpack 项目模板来构建 Hello 合约。在 smartcontract 目录下,执行如下命令:

truffle unbox webpack

初始化项目的时候,它会创建运行一个完整Dapp所需的文件和目录。我们将 strings.solHello.sol 两个合约文件移动到 contracts 目录下,并删除 contracts 目录下原有的 ConvertLib.solMetaCoin.sol 文件(Migrations.sol 合约用来管理应用合约的部署,因此请勿删除)。目录结构如下:

smartcontract
  ├── app
  ├── contracts
          ├── Hello.sol
          ├── Migrations.sol
          └── strings.sol
  ├── migrations
          ├── 1_initial_migration.js
        └── 2_deploy_contracts.js
  ├── node_modules
  ├── package.json
  ├── test
  ├── truffle.js
  └── webpack.config.js

修改部署脚本

目录migrations (迁移的意思) 非常重要。truffle使用该目录下的脚本来管理合约的部署。在前面几篇教程中,我们是通过自己编写编译部署脚本 deploy.js ,并在node控制台中运行来将 Hello 合约部署到区块链上的。有了truffle,以后再也不用这么做了。

第一个脚本 1_initial_migration.js 的作用是向区块链部署 Migrations 合约。 这个合约的作用是存储并跟踪已经部署的最新合约。每次运行脚本时,truffle就会向区块链查询获取已部署好的合约,然后部署新的合约。部署完成后,这个脚本会更新 Migrations 合约中的last_completed_migration 字段指向最新部署的合约。

我们可以简单地把 Migrations 合约当成是一个数据库表,字段last_completed_migration 总是保持最新状态。

我们来修改第二个脚本 2_deploy_contracts.js

//artifacts对象为truffle框架提供
//artifacts.require()方法与Node中的require()方法类似
//编译合约代码。自动调用solc编译器来编译合约代码并返回编译结果对象
var stringsContract = artifacts.require("./strings.sol");
var HelloContract = artifacts.require("./Hello.sol");

//部署器对象deployer为truffle框架提供
module.exports = function(deployer) {
  //部署string.sol合约
  deployer.deploy(stringsContract);
  //将已部署的strings合约类库连接到Hello合约
  deployer.link(stringsContract, HelloContract);
  //部署Hello.sol合约
  deployer.deploy(HelloContract);
};

代码不难,加上了注释很容易理解。

修改truffle配置

部署脚本修改完后,我们还需要在配置文件中声明要连接的以太坊节点地址,这里使用Ganache的地址 http://localhost:7545

require('babel-register')
module.exports = {
  networks: {
    development: {
      host: 'localhost',
      port: 7545,
      network_id: '*'
    }
  }
}

注意 development 关键字。truffle支持将合约部署到多个区块链网络,例如开发网络、私有网络、测试网或公网。 在上面的配置中,我们只定义了一个用于开发的网络。

编译合约

smartcontract 目录下执行 truffle compile 命令,终端输出如下:

Compiling ./contracts/Hello.sol...
Compiling ./contracts/Migrations.sol...
Compiling ./contracts/strings.sol...
Writing artifacts to ./build/contracts

可以看到,contracts 目录下的三个合约文件都编译了,并且在当前目录下生成了 build/contracts 目录,同时也产生了三个文件:

smartcontract/build/contracts
    ├── Hello.json
    ├── Migrations.json
    └── strings.json

这三个都是 abi 文件(abi概念的解释,可以翻看以太坊智能合约开发第二篇:理解以太坊相关概念)。

部署合约

合约编译成功后,就可以部署了。在 smartcontract 目录下执行部署命令 truffle migrate ,可以看到终端上输出了部署日志:
部署日志

关键信息可以标注出来。我们也可以在 Ganache 中的 LOGS 面板中查看 transaction id 和 合约地址:
Ganache日志

合约调用

合约部署成功后,我们可以通过 truffle console 命令进入控制台。在控制台里调用刚才部署的合约:

$ truffle console
truffle(development)> Hello.deployed().then(function(contractInstance){contractInstance.say.call('Guys').then(function(result){console.log(result)})})
truffle(development)> Hello Guys

需要注意的是,truffle 的所有调用都会返回 promise (node语法),所以每个响应都被包裹在 then() 函数里。

至此,通过truffle框架进行合约的编译、部署与调用就介绍完了。和之前手动编写编译部署脚本,及调用脚本的方式相比,是不是更方便快捷?而且代码量还更少更精炼。 通过truffle框架,编译和部署都用一条命令即可搞定。

抛砖引玉

本篇中合约的调用是在truffle控制台中,如何通过网页调用合约呢?

我的专栏:智能合约
智能合约开发QQ群:753778670
智能合约开发QQ群


目前有几套区块链实践的视频课程(视频+源码),需要的可加我微信(kuangwenjie)私信我(付费):

  • 『区块链』从零构建以太坊(Ethereum)智能合约到项目实战
  • 基于Ethereum & IPFS的去中心化Ebay区块链项目开发实战
  • HyperLedger(超级账本)Fabric

查看原文

赞 4 收藏 7 评论 1

marser 发布了文章 · 2018-04-12

以太坊智能合约开发第五篇:字符串拼接—Solidity

原文发表于:以太坊智能合约开发第五篇:字符串拼接—Solidity

上一篇,我们实现了一个简单的智能合约。用户输入什么字符串,合约就原样返回什么。在文章最后抛出了一个问题:如果我们事先在合约里定义好 Hello 字符串,如何与 name 变量进行字符串拼接?

在智能合约里进行字符串的拼接可不是一件简单的事情。本篇就来介绍智能合约里的字符串拼接。

尝试

我们先用绝大部分语言都通用的连接符 +. 来尝试着修改代码:

//pragma关键字:版本申明。
//用来指示编译器将代码编译成特定版本,以免引起兼容性问题
//此处不支持0.4.0之前的编译器,也不支持0.5.0之后的编译器(条件为 ^)
pragma solidity ^0.4.0;

//contract关键字:合约申明
//和Java、PHP中的class类似
//此处是申明一个名为Hello的合约
contract Hello {

    string str="Hello ";

    //public: 函数访问属性(后续文章为详细阐述)
    //returns (string): 定义返回值类型为string
    function say(string name) public returns (string) {
        return str + name;
    }
}

<!--more-->

运行 node deploy.js 部署脚本后,抛出了一个异常:

TypeError: Operator + not compatible with types string storage ref and string memory
return str + name;

我们将其修改为 . 并尝试部署后,也抛出一个异常:

TypeError: Member "name" not found or not visible after argument-dependent lookup in string storage ref return str . name;

说明在智能合约里,+. 都不是连接符。
通过查阅 Solidity 官方文档,我们发现 Solidity 语言并不提供字符串连接符的语法:
Solidity文档
那有没有其他方式,可以实现字符串的拼接功能呢?

以下部分为付费用户专享福利,请点击链接跳转至我的专栏付费购买。通过阅读以下部分,你将学习到:

第三方字符串工具合约:字符串的扩展处理(查找、分割、比较、拼接等功能)
智能合约里第三方合约的引入
字符串的拼接实现

我的专栏:智能合约
智能合约开发QQ群:753778670
智能合约开发QQ群


目前有几套区块链实践的视频课程(视频+源码),需要的可加我微信(kuangwenjie)私信我(付费):

  • 『区块链』从零构建以太坊(Ethereum)智能合约到项目实战
  • 基于Ethereum & IPFS的去中心化Ebay区块链项目开发实战
  • HyperLedger(超级账本)Fabric

查看原文

赞 0 收藏 1 评论 0

认证与成就

  • SegmentFault 讲师
  • 获得 38 次点赞
  • 获得 16 枚徽章 获得 0 枚金徽章, 获得 3 枚银徽章, 获得 13 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

  • PhalconCMS

    基于Phalcon框架的开源博客系统

注册于 2015-11-12
个人主页被 1.5k 人浏览