合约实战,代币合约,DAPP开发

1. ERC20标准

https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md

pragma solidity ^0.4.4;

//定义接口
contract ERC20Interface{
  string public name;
  string public symbol;
  uint8 public decimals;
  uint256 public totalSupply;

  /* function balanceOf(address _owner) view returns (uint256 balance); */
  function transfer(address _to, uint256 _value) returns (bool success);
  function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
  function approve(address _spender, uint256 _value) returns (bool success);
  function allowance(address _owner, address _spender) view returns (uint256 remaining);

  event Transfer(address indexed _from, address indexed _to, uint256 _value);
  event Approval(address indexed _owner, address indexed _spender, uint256 _value);

}

contract ERC20 is ERC20Interface{
  mapping(address => uint256) public balanceOf;
  //委托,允许他人操作的金额数
  mapping(address => mapping(address => uint256)) allowed;

  //构造方法
  constructor() public {
    name = "MyToken";
    symbol = "weixuexi";
    decimals = 0;
    totalSupply = 10000;
    balanceOf[msg.sender] = totalSupply;
  }

  /* function balanceOf(address _owner) view returns (uint256 balance){
    return balanceOf[_owner];
  } */
  function transfer(address _to, uint256 _value) returns (bool success){
    require(_to != address(0));
    require(balanceOf[msg.sender] >= _value);
    require(balanceOf[_to] + _value > balanceOf[_to]);

    balanceOf[msg.sender] -= _value;
    balanceOf[_to] += _value;
    emit Transfer(msg.sender, _to, _value);
  }
  function transferFrom(address _from, address _to, uint256 _value) returns (bool success){

    require(_from != address(0));
    require(_to != address(0));
    require(balanceOf[_from] >= _value);
    require(allowed[msg.sender][_from] >= _value);  //当前合约能操作_from的钱数要大于_value
    require(balanceOf[_to] + _value > balanceOf[_to]);

    balanceOf[_from] -= _value;
    balanceOf[_to] += _value;
    emit Transfer(_from, _to, _value);

    success = true;
  }
  function approve(address _spender, uint256 _value) returns (bool success){
    //当前账户允许—_spender操作的金额数
    allowed[msg.sender][_spender] = _value;
    emit Approval(msg.sender, _spender, _value);
    success = true;
  }
  function allowance(address _owner, address _spender) view returns (uint256 remaining){
    return allowed[_owner][_spender];
  }
}
View Code

 2.DAPP去中心化应用开发【web项目】

  web3.js

  solidity

  truffle  https://truffleframework.com/docs/truffle/getting-started/installation

  ganache

开发流程:

  • 新建项目【初始化】
  • 编写合约
  • 合约编译、部署、测试
  • 与合约交互

安装truffle:

npm install -g truffle
查看版本:truffle.cmd version

创建项目:

  下载基本文件:

      cd pet-shop

    truffle init  【安装项目】

  下载pet-shop包文件:

    cd pet-shop

    truffle unbox pet-shop

 编写智能合约:Adoption.sol

pragma solidity ^0.4.23;


contract Adoption {
    address[16] public adoptors; //领养这地址

    function adopt(uint petId) public returns(uint) {
        adoptors[petId] = msg.sender;
        return petId;
    }

    function getAdoptors() public view returns (address[16]) {
        return adoptors;
    }
}

编译: truffle.cmd compile【方式一,结合使用ganache】

  truffle develop 【方式二,truffle集成了testrpc】; compile;

部署合约:migrate

  部署合约脚本: 1_migration.js   改文件用于监听合约文件的动向,是否更新,变化

var MyContract = artifacts.require("MyContract");

module.exports = function(deployer) {
  // deployment steps
  deployer.deploy(MyContract);
};

   truffle.js:

module.exports = {
  // See <http://truffleframework.com/docs/advanced/configuration>
  // to customize your Truffle configuration!
  networks: {
    development: {
      host: "127.0.0.1",  //主机
      port: 7545,  //端口,和ganache对应
      network_id: "*" // Match any network id
    }
  }
};

  部署合约:[truffle] migrate

输出结果:Adoption.json  [编译出的文件做出了更新]

 这时,ganache中可以发现,已经出来了4个区块:

还有交易信息:

 获取合约实例,调用函数:

pragma solidity ^0.4.23;

contract Hello {
    //如果使用pure修饰,可以通过合约对象直接调用,否则需要使用call方法调用
    function test() pure public returns (string) {
        return "hello world";
    }
}
Hello.sol

/migrations/3_deploy_hello.js

var Hello = artifacts.require("./Hello.sol");

module.exports = function(deployer) {
  deployer.deploy(Hello);
};

  使用web3获取合约实例: 

>truffle: let contract;   //声明contract变量

    contract = Hello.deployed().then(instance => contract=instance)             //Hello 是上面迁移文件的合约实例

pragma solidity ^0.4.23;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/Adoption.sol";

contract TestAdoption {
    Adoption adoption = Adoption(DeployedAddresses.Adoption());

    function testUserCatAdoptPet() public {
        uint returnId = adoption.adopt(8);

        uint expect = 8;
        Assert.equal(returnId, expect, "Adoption of pet Id 8 should be recorded");
    }

    function testGetAdoptorAddByPetId() public {
        address expect = this;
        address adoptor = adoption.adoptors(8);
        Assert.equal(expect, adoptor, "get adopt by pet id");
    }
}
View Code

  注意:修改完合约文件后,重新编译【compile】后,重新部署命令【migrate --reset】

  调用合约方法:contract.test();

   使用断言测试:Assert

同时会多出很多新的区块和交易

 3.web3.js api的使用

官网

  进入truffle开发环境:truffle.cmd develop

  获取账户余额:web3.eth.getBalace("").toString();

truffle(develop)> web3.eth.getBalance("0x627306090abab3a6e1400e9345bc60c78a8bef57").toString()
   '100000000000000000000'

  获取所有账户:web3.eth.accounts;

truffle(develop)> null [ 
  '0x627306090abab3a6e1400e9345bc60c78a8bef57',
  '0xf17f52151ebef6c7334fad080c5704d77216b732',
  '0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef',
  '0x821aea9a577a9b44299b9c15c88cf3087f3b5544',
  '0x0d1d4e623d10f9fba5db95830f7d3839406c6af2',
  '0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e',
  '0x2191ef87e392377ec08e7c08eb105ef5448eced5',
  '0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5',
  '0x6330a553fc93768f612722bb8c2ec78ac90b3bbc',
  '0x5aeda56215b167893e80b4fe645ba6d5bab767de' ]

  获取当前账号:【数组中的第0个账号】

truffle(develop)> web3.eth.coinbase;
  '0x627306090abab3a6e1400e9345bc60c78a8bef57'

   web3.fromWei(num, 单位);

truffle(develop)> web3.fromWei(5, 'ether')
    '0.000000000000000005'

  web3.toWei(num,单位)

  默认的区块:

truffle(develop)> web3.eth.defaultBlock
  'latest'

  交易:

truffle(develop)> web3.eth.sendTransaction({from:account1, to:account2, value:100000000000000000})
  '0xb5065a9a03d75f08d7e704d352d08de5c8c4f8f19cc654cb1261d254f6194d90'
truffle(develop)> web3.eth.getBalance(account1)
  BigNumber { s: 1, e: 19, c: [ 998999, 99999999979000 ] }
truffle(develop)> web3.eth.getBalance(account2)
  BigNumber { s: 1, e: 20, c: [ 1001000 ] }
truffle(develop)> web3.eth.getBalance(account1).toString()
  '99899999999999979000'
truffle(develop)> web3.eth.getBalance(account2).toString()
  '100100000000000000000'
truffle(develop)> web3.fromWei(web3.eth.getBalance(account1).toString(), 'ether')
  '99.899999999999979'
truffle(develop)> web3.fromWei(web3.eth.getBalance(account2).toString(), 'ether')
  '100.1'
truffle(develop)> web3.fromWei(web3.eth.getBalance(web3.eth.accounts[2]).toString(), 'ether')
  '100'

  

4. 代币合约的概念

pragma solidity ^0.4.4;

contract EncryptedToken {
    uint256 INITAL_SUPPLY = 10000;
    mapping(address => uint) public balanceOf;
    constructor() {
        balanceOf[msg.sender] = INITAL_SUPPLY;
    }
    function transfer(address _to, uint256 _value) public {
        require(_to != address(0));
        require(balanceOf[msg.sender] >= _value);
        require(balanceOf[_to] + _value > balanceOf[_to]);

        balanceOf[msg.sender] -= _value;
        balanceOf[_to] += _value;
    }
}
EncryptedToken.sol
var EncryptedToken = artifacts.require("./EncryptedToken.sol");

module.exports = function(deployer) {
  deployer.deploy(EncryptedToken);
};
1_deploy_encryptedToken.js

部署:

  truffle.cmd develop

  compile

  migate

  let c;

  EncryptedToken.deployed().then(inc => c=inc);

  c.balanceOf("0x627306090abab3a6e1400e9345bc60c78a8bef57") ;  ->10000   //钱包地址

默认部署到第一个测试钱包中:

转账:c.transfer("0xf17f52151ebef6c7334fad080c5704d77216b732",1000)

truffle(develop)> c.balanceOf("0x627306090abab3a6e1400e9345bc60c78a8bef57")
       BigNumber { s: 1, e: 3, c: [ 9000 ] }

5. web端

4.1 使用npm管理项目

  npm init

  安装web server:npm install lite-server

配置文件:bs-config.json

{
    "server" : {
        "baseDir":["./src", "./build/contracts"]
    }
}

package.json:

启动服务:npm run dev

原文地址:https://www.cnblogs.com/zhuxiang1633/p/9486914.html