ETH开发系列智能合约安全

通过MetaMask向智能合约转入ETH和转出ETH

2018-08-14  本文已影响32人  黄大叔_ddc6

一 MetaMask

1 安装MetaMask

通过Chrome浏览器安装MetaMask插件,插件地址https://www.metamask.io/,选择'GET CHROME EXTENSION'如下图红框。

插件

注:如果安装失败,退出登录再安装,这是我遇到的一种情况。如果仍然失败请留言。

2 生成MetaMask账号

MetaMask插件安装成功后,会出现一只狐狸?头像,如下图

安装成功

点击插件,设置密码,创建账号(也可以导入已有账号)如果是创建账号记得保存好助记词,这些操作不一一说明了,有问题请留言。

这里主要说下几个网络,一个是主网,另外还有三个测试网络,我是在Rinkeby Test Network下完成的,各位也可以试试另外两个测试网络,当然用主网做开发是不可能的-穷。

下面讲下如何申请Rinkeby Test Network的测试代币。

打开rinkeby网站·地址:https://www.rinkeby.io/#faucet

rinkeby

我是通过google++的方式,需要FQ,这个大家自己丰衣足食,别干蠢事就行。

分享地址

复制刚刚分享的信息地址,到rinkeby网站输入地址申请测试币。

复制信息地址

到这时MetaMask钱包已准备完成。

二 智能合约

1 编写并发布智能合约

为做测试写一个简单的智能合约,复杂的也憋不出来。

智能合约编辑器:http://remix.ethereum.org/#optimize=true&version=soljson-v0.4.24+commit.e67f0147.js

智能合约

点击Deploy,弹出MetaMask对话框,支付gas确认发布

确认发布

2 验证智能合约

合约发布成功后,会显示发布合约的交易查询地址。

发布合约交易地址

点击发布合约交易查询地址,显示如下

发布合约交易详情

点击合约地址,查询合约详细信息

合约详情

验证合约

验证

输入以上5个地方的信息,点击验证

验证成功

验证成功后,保存合约地址和ABI信息,后续要用到。

3 合约内容说明

合约代码(这只是一个测试合约,Solidity还不是很熟悉,如果合约有什么语法错误,欢迎指教)

pragma solidity ^0.4.24;

contract GameContract {

  address fromAddress;

  uint256 value;

  uint256 code;

  uint256 team;

  function buyKey(uint256 _code, uint256 _team)

    public

    payable

  {

      fromAddress = msg.sender;

      value = msg.value;

      code = _code;

      team = _team;

  }

  function getInfo()

    public

    constant

    returns (address, uint256, uint256, uint256)

  {

      return (fromAddress, value, code, team);

  } 

   function withdraw()

        public

    {

        address send_to_address = 0xfdd7a3f5375C6Fcc7852C0372bCE202b3080F451;

        uint256 _eth = 333000000000000000;

        send_to_address.transfer(_eth);

    }

}

buyKey方法是向合约地址转入eth,该方法有payable属性,说明可以转入eth。在方法中通过msg.sender和msg.value,可以获取eth的转出地址(from_address)和数量(单位是wei),eth的转入地址(to_address)就是合约地址。其它两个参数是合约逻辑需要的数据,可以有多个也可以没有。(from_address=msg.sender;to_address=contract_address;value=msg.value)

getInfo方法是获取buyKey方法转入的信息。

withdraw方法是从合约地址中转出eth,转出地址(from_address)是合约地址,转入地址(to_address)是send_to_address,数量是_eth(单位是wei)。

合约代码说明就这样,不了解的一起学习。

三 通过WEB3调用智能合约

先贴代码

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>

MetaMask Test

Set Info!Get Info!Send Out!

    window.addEventListener('load', function() {

    if (typeof web3 !== 'undefined') {

        initContract(web3);

        initAccount(web3);

    }

});

var address = '';

// 初始化MetaMask当前账户

function initAccount(web3) {

    // 获取metamask当前登录的account

    web3.eth.getAccounts(function(err, accounts) {

    console.log(accounts);

    if (accounts!=null && accounts.length>0)

    address = accounts[0].toString();

    });

}

// 初始化合约对象

function initContract(web3) {

var abi = [{"constant":false,"inputs":[],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getInfo","outputs":[{"name":"","type":"address"},{"name":"","type":"uint256"},{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_code","type":"uint256"},{"name":"_team","type":"uint256"}],"name":"buyKey","outputs":[],"payable":true,"stateMutability":"payable","type":"function"}];

var contract_address = '0xe5fe93d857900a84cb6be5429a06f825ca6d28fb'

    var eth = new Eth(web3.currentProvider)

    var contract = eth.contract(abi).at(contract_address);

    listenForClicks(contract, web3)

}

// 添加按钮click事件

function listenForClicks (contract, web3) {

    var button = document.querySelector('button.setInfo');

    var button1 = document.querySelector('button.getInfo');

    var button2 = document.querySelector('button.sendOut');

    // 调用buyKey方法(eth转入)

    button.addEventListener('click', function() {

var etherValue = web3.toWei(0.2, 'ether');

        contract.buyKey('1', '1', {from: address, value: etherValue}, function(error, result) {

            console.log('Send In')

if (!error)

            console.log(JSON.stringify(result));

        else

            console.error(error);

        });

    });

// 调用getInfo方法

    button1.addEventListener('click', function() {

        contract.getInfo(function(error, result) {

            console.log('Get Info')

if (!error) {

            console.log('fromAddress:' + result[0] + ', value:' + result[1]);

            console.log('code:' + result[2] + ', team:' + result[3]);

} else

            console.error(error);

        });

    });

// 调用withdraw方法(eth转出)

    button2.addEventListener('click', function() {

        contract.withdraw({from: address}, function(error, result) {

            console.log('Send Out')

if (!error)

            console.log(JSON.stringify(result));

        else

            console.error(error);

        });

    });

}

是tomcat跑的jsp页面,大家也可以用其它服务器

主要讲下智能合约eth的转入和转出两块的代码。

1 智能合约eth转入方法的调用

buyKey

智能合约中的buyKey只有两个参数,前面两个参数就对应了智能合约中的两个参数,红框中的参数是eth转出地址(from_account)和eht数量,单位是wei。

合约转入eth 查询合约eth

2 智能合约eth转出方法的调用

如果实现了上一步,那就先祝贺你,现在我们再看看智能合约eth的转出,上一步成功后看到合约的eth数量是0.2个,而转出方法中我们写的数量是0.333个,所以还需要向合约转入eth,再调用一次buyKey方法

0.4个eth

调用合约eth转出方法

withdraw

这个地方也有{from: address}参数,但是这个不是eth转出地址。因为这个方法内部有eth的交易,所以需要支付gas,这个参数只是指定了gas由谁支付。

Send Out

点击CONFIRM,等待块确认成功之后查看合约余额和转入地址的余额

合约eth

可以看到合约eth余额已减少0.333个

https://rinkeby.etherscan.io/tx/0x63feedf866bab8dc459cc522d5cb9a0ccdbb2a58f3d83b82670352d6080306b8

这是转入地址对应的交易信息有兴趣的可以去看看交易详情。

总结

这块东西在度娘没有找到很全的相关资料,谷哥还得FQ,英语也不好,花了不少时间才总结出这点东西,肯定会有很多问题,但也算是从头到尾流程跑通了,不足的地方希望大家指教一起学习一起进步。

转载请注明出处,谢谢合作。

上一篇下一篇

猜你喜欢

热点阅读