一.环境安装

1.1 nodejs安装

  • 1.下载nodejs二进制包
    wget https://nodejs.org/download/release/v10.12.0/node-v10.12.0-linux-x64.tar.xz
  • 2.解压压缩包
    tar xvf node-v10.12.0-linux-x64.tar.xz 
  • 更改包名
    mv node-v10.12.0-linux-x64 /usr/local/nodejs
  • 添加环境变量
    # vim /etc/profile
    #nodejs
    export NODE_HOME=/usr/local/nodejs
    export PATH=$NODE_HOME/bin:$PATH
  • 生效环境变量
    source /etc/profile
  • 查看nodejs版本号
    # node -v
    v10.12.0
  • 查看npm版本号
    ```

    npm -v

6.4.1

## 1.2 solc安装
- 安装solc版本为erc20_usdt合约指定版本

npm -g install solc@0.4.17

- 查看solc版本

solcjs --version

0.4.17+commit.bdeb9e52.Emscripten.clang

# 二.下载ERC20_USDT合约

## 2.1 erc20_sudt合约查看链接
https://cn.etherscan.com/address/0xdac17f958d2ee523a2206206994597c13d831ec7#contracts

## 2.2 erc20_sudt合约文件存放
将链接中erc20_sudt合约复制下来放到以下文件中

vim /opt/data/contract/usdt.sol

/**
*Submitted for verification at Etherscan.io on 2017-11-28
*/

pragma solidity ^0.4.17;

/**

  • @title SafeMath

  • @dev Math operations with safety checks that throw on error

  • /
    library SafeMath {
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {

      if (a == 0) {
          return 0;
      }
      uint256 c = a * b;
      assert(c / a == b);
      return c;

    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {

      // assert(b > 0); // Solidity automatically throws when dividing by 0
      uint256 c = a / b;
      // assert(a == b * c + a % b); // There is no case in which this doesn't hold
      return c;

    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {

      assert(b <= a);
      return a - b;

    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {

      uint256 c = a + b;
      assert(c >= a);
      return c;

    }
    }

/**

  • @title Ownable

  • @dev The Ownable contract has an owner address, and provides basic authorization control

  • functions, this simplifies the implementation of "user permissions".

  • /
    contract Ownable {
    address public owner;

    /**

    * @dev The Ownable constructor sets the original `owner` of the contract to the sender
    * account.
    */

    function Ownable() public {

      owner = msg.sender;

    }

    /**

    * @dev Throws if called by any account other than the owner.
    */

    modifier onlyOwner() {

      require(msg.sender == owner);
      _;

    }

    /**

    • @dev Allows the current owner to transfer control of the contract to a newOwner.
    • @param newOwner The address to transfer ownership to.
    • /
      function transferOwnership(address newOwner) public onlyOwner {
      if (newOwner != address(0)) {
         owner = newOwner;
      }
      }

}

/**

  • @title ERC20Basic
  • @dev Simpler version of ERC20 interface
  • @dev see https://github.com/ethereum/EIPs/issues/20
  • /
    contract ERC20Basic {
    uint public _totalSupply;
    function totalSupply() public constant returns (uint);
    function balanceOf(address who) public constant returns (uint);
    function transfer(address to, uint value) public;
    event Transfer(address indexed from, address indexed to, uint value);
    }

/**

  • @title ERC20 interface
  • @dev see https://github.com/ethereum/EIPs/issues/20
  • /
    contract ERC20 is ERC20Basic {
    function allowance(address owner, address spender) public constant returns (uint);
    function transferFrom(address from, address to, uint value) public;
    function approve(address spender, uint value) public;
    event Approval(address indexed owner, address indexed spender, uint value);
    }

/**

  • @title Basic token

  • @dev Basic version of StandardToken, with no allowances.

  • /
    contract BasicToken is Ownable, ERC20Basic {
    using SafeMath for uint;

    mapping(address => uint) public balances;

    // additional variables for use if transaction fees ever became necessary
    uint public basisPointsRate = 0;
    uint public maximumFee = 0;

    /**

    • @dev Fix for the ERC20 short address attack.

    • /
      modifier onlyPayloadSize(uint size) {
      require(!(msg.data.length < size + 4));
      _;
      }

      /**

    • @dev transfer token for a specified address

    • @param _to The address to transfer to.

    • @param _value The amount to be transferred.

    • /
      function transfer(address _to, uint _value) public onlyPayloadSize(2 * 32) {
      uint fee = (_value.mul(basisPointsRate)).div(10000);
      if (fee > maximumFee) {

         fee = maximumFee;

      }
      uint sendAmount = _value.sub(fee);
      balances[msg.sender] = balances[msg.sender].sub(_value);
      balances[_to] = balances[_to].add(sendAmount);
      if (fee > 0) {

         balances[owner] = balances[owner].add(fee);
         Transfer(msg.sender, owner, fee);

      }
      Transfer(msg.sender, _to, sendAmount);
      }

      /**

    • @dev Gets the balance of the specified address.

    • @param _owner The address to query the the balance of.

    • @return An uint representing the amount owned by the passed address.

    • /
      function balanceOf(address _owner) public constant returns (uint balance) {
      return balances[_owner];
      }

}

/**

  • @title Standard ERC20 token

  • @dev Implementation of the basic standard token.

  • @dev https://github.com/ethereum/EIPs/issues/20

  • @dev Based oncode by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol

  • /
    contract StandardToken is BasicToken, ERC20 {

    mapping (address => mapping (address => uint)) public allowed;

    uint public constant MAX_UINT = 2**256 - 1;

    /**

    • @dev Transfer tokens from one address to another

    • @param _from address The address which you want to send tokens from

    • @param _to address The address which you want to transfer to

    • @param _value uint the amount of tokens to be transferred

    • /
      function transferFrom(address _from, address _to, uint _value) public onlyPayloadSize(3 * 32) {
      var _allowance = allowed[_from][msg.sender];

      // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
      // if (_value > _allowance) throw;

      uint fee = (_value.mul(basisPointsRate)).div(10000);
      if (fee > maximumFee) {

         fee = maximumFee;

      }
      if (_allowance < MAX_UINT) {

         allowed[_from][msg.sender] = _allowance.sub(_value);

      }
      uint sendAmount = _value.sub(fee);
      balances[_from] = balances[_from].sub(_value);
      balances[_to] = balances[_to].add(sendAmount);
      if (fee > 0) {

         balances[owner] = balances[owner].add(fee);
         Transfer(_from, owner, fee);

      }
      Transfer(_from, _to, sendAmount);
      }

      /**

    • @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.

    • @param _spender The address which will spend the funds.

    • @param _value The amount of tokens to be spent.

    • /
      function approve(address _spender, uint _value) public onlyPayloadSize(2 * 32) {

      // To change the approve amount you first have to reduce the addresses// allowance to zero by callingapprove(_spender, 0)` if it is not
      // already 0 to mitigate the race condition described here:
      // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
      require(!((_value != 0) && (allowed[msg.sender][_spender] != 0)));

      allowed[msg.sender][_spender] = _value;
      Approval(msg.sender, _spender, _value);
      }

      /**

    • @dev Function to check the amount of tokens than an owner allowed to a spender.

    • @param _owner address The address which owns the funds.

    • @param _spender address The address which will spend the funds.

    • @return A uint specifying the amount of tokens still available for the spender.

    • /
      function allowance(address _owner, address _spender) public constant returns (uint remaining) {
      return allowed[_owner][_spender];
      }

}

/**

  • @title Pausable

  • @dev Base contract which allows children to implement an emergency stop mechanism.

  • /
    contract Pausable is Ownable {
    event Pause();
    event Unpause();

    bool public paused = false;

/**

  • @dev Modifier to make a function callable only when the contract is not paused.

  • /
    modifier whenNotPaused() {
    require(!paused);
    _;
    }

    /**

  • @dev Modifier to make a function callable only when the contract is paused.

  • /
    modifier whenPaused() {
    require(paused);
    _;
    }

    /**

  • @dev called by the owner to pause, triggers stopped state

  • /
    function pause() onlyOwner whenNotPaused public {
    paused = true;
    Pause();
    }

    /**

  • @dev called by the owner to unpause, returns to normal state

  • /
    function unpause() onlyOwner whenPaused public {
    paused = false;
    Unpause();
    }
    }

contract BlackList is Ownable, BasicToken {

/////// Getters to allow the same blacklist to be used also by other contracts (including upgraded Tether) ///////
function getBlackListStatus(address _maker) external constant returns (bool) {
    return isBlackListed[_maker];
}

function getOwner() external constant returns (address) {
    return owner;
}

mapping (address => bool) public isBlackListed;

function addBlackList (address _evilUser) public onlyOwner {
    isBlackListed[_evilUser] = true;
    AddedBlackList(_evilUser);
}

function removeBlackList (address _clearedUser) public onlyOwner {
    isBlackListed[_clearedUser] = false;
    RemovedBlackList(_clearedUser);
}

function destroyBlackFunds (address _blackListedUser) public onlyOwner {
    require(isBlackListed[_blackListedUser]);
    uint dirtyFunds = balanceOf(_blackListedUser);
    balances[_blackListedUser] = 0;
    _totalSupply -= dirtyFunds;
    DestroyedBlackFunds(_blackListedUser, dirtyFunds);
}

event DestroyedBlackFunds(address _blackListedUser, uint _balance);

event AddedBlackList(address _user);

event RemovedBlackList(address _user);

}

contract UpgradedStandardToken is StandardToken{
// those methods are called by the legacy contract
// and they must ensure msg.sender to be the contract address
function transferByLegacy(address from, address to, uint value) public;
function transferFromByLegacy(address sender, address from, address spender, uint value) public;
function approveByLegacy(address from, address spender, uint value) public;
}

contract TetherToken is Pausable, StandardToken, BlackList {

string public name;
string public symbol;
uint public decimals;
address public upgradedAddress;
bool public deprecated;

//  The contract can be initialized with a number of tokens
//  All the tokens are deposited to the owner address
//
// @param _balance Initial supply of the contract
// @param _name Token Name
// @param _symbol Token symbol
// @param _decimals Token decimals
function TetherToken(uint _initialSupply, string _name, string _symbol, uint _decimals) public {
    _totalSupply = _initialSupply;
    name = _name;
    symbol = _symbol;
    decimals = _decimals;
    balances[owner] = _initialSupply;
    deprecated = false;
}

// Forward ERC20 methods to upgraded contract if this one is deprecated
function transfer(address _to, uint _value) public whenNotPaused {
    require(!isBlackListed[msg.sender]);
    if (deprecated) {
        return UpgradedStandardToken(upgradedAddress).transferByLegacy(msg.sender, _to, _value);
    } else {
        return super.transfer(_to, _value);
    }
}

// Forward ERC20 methods to upgraded contract if this one is deprecated
function transferFrom(address _from, address _to, uint _value) public whenNotPaused {
    require(!isBlackListed[_from]);
    if (deprecated) {
        return UpgradedStandardToken(upgradedAddress).transferFromByLegacy(msg.sender, _from, _to, _value);
    } else {
        return super.transferFrom(_from, _to, _value);
    }
}

// Forward ERC20 methods to upgraded contract if this one is deprecated
function balanceOf(address who) public constant returns (uint) {
    if (deprecated) {
        return UpgradedStandardToken(upgradedAddress).balanceOf(who);
    } else {
        return super.balanceOf(who);
    }
}

// Forward ERC20 methods to upgraded contract if this one is deprecated
function approve(address _spender, uint _value) public onlyPayloadSize(2 * 32) {
    if (deprecated) {
        return UpgradedStandardToken(upgradedAddress).approveByLegacy(msg.sender, _spender, _value);
    } else {
        return super.approve(_spender, _value);
    }
}

// Forward ERC20 methods to upgraded contract if this one is deprecated
function allowance(address _owner, address _spender) public constant returns (uint remaining) {
    if (deprecated) {
        return StandardToken(upgradedAddress).allowance(_owner, _spender);
    } else {
        return super.allowance(_owner, _spender);
    }
}

// deprecate current contract in favour of a new one
function deprecate(address _upgradedAddress) public onlyOwner {
    deprecated = true;
    upgradedAddress = _upgradedAddress;
    Deprecate(_upgradedAddress);
}

// deprecate current contract if favour of a new one
function totalSupply() public constant returns (uint) {
    if (deprecated) {
        return StandardToken(upgradedAddress).totalSupply();
    } else {
        return _totalSupply;
    }
}

// Issue a new amount of tokens
// these tokens are deposited into the owner address
//
// @param _amount Number of tokens to be issued
function issue(uint amount) public onlyOwner {
    require(_totalSupply + amount > _totalSupply);
    require(balances[owner] + amount > balances[owner]);

    balances[owner] += amount;
    _totalSupply += amount;
    Issue(amount);
}

// Redeem tokens.
// These tokens are withdrawn from the owner address
// if the balance must be enough to cover the redeem
// or the call will fail.
// @param _amount Number of tokens to be issued
function redeem(uint amount) public onlyOwner {
    require(_totalSupply >= amount);
    require(balances[owner] >= amount);

    _totalSupply -= amount;
    balances[owner] -= amount;
    Redeem(amount);
}

function setParams(uint newBasisPoints, uint newMaxFee) public onlyOwner {
    // Ensure transparency by hardcoding limit beyond which fees can never be added
    require(newBasisPoints < 20);
    require(newMaxFee < 50);

    basisPointsRate = newBasisPoints;
    maximumFee = newMaxFee.mul(10**decimals);

    Params(basisPointsRate, maximumFee);
}

// Called when new token are issued
event Issue(uint amount);

// Called when tokens are redeemed
event Redeem(uint amount);

// Called when contract is deprecated
event Deprecate(address newAddress);

// Called if contract ever adds fees
event Params(uint feeBasisPoints, uint maxFee);

}

# 三.编辑js文件
## 3.1 编写合约js文件

vim /opt/data/deploy_usdt.js

let Web3 = require("web3")
let solc = require("solc")
let fs = require("fs")

// 监听同步节点
web3 = new Web3(new Web3.providers.HttpProvider("http://192.168.21.207:8545"));

// 导入合约文件
let source = fs.readFileSync("./contract/usdt.sol", "utf8");

// 编译合约
let cacl = solc.compile(source, 1);

console.log("=============================")
console.log("version: " + web3.version);
console.log("=============================")
console.log(solc.version())
console.log("=============================")
console.log(cacl.contracts)

let abi = JSON.parse(cacl.contracts[':TetherToken'].interface);
console.log("=============================")
console.log(abi)
console.log("=============================")

let bytecode = cacl.contracts[':TetherToken'].bytecode;
console.log(bytecode)
console.log("=============================")

let sender = "0x6e60f5243e1a3f0be3f407b5afe9e5395ee82aa2";

// 部署合约
new web3.eth.Contract(abi).deploy({
data: "0x" + bytecode,
arguments: [2718282552619854,"Tether USD","USDT",6],
}).send({
from: sender,
gas: 3070000,
gasPrice: 130000000000
}, function (error) {
if (error != null) {
console.log("部署失败: " + error);
}
}).then(function (newContractInstance) {

// 获取合约地址
var newContractAddress = newContractInstance.options.address
console.log("部署成功,合约地址:\n" + newContractAddress.toLowerCase());

});

## 3.2 修改合约js文件相应参数

- 1、监听以太坊节点地址

> 注:以太坊私链可连接地址

web3 = new Web3(new Web3.providers.HttpProvider("http://192.168.21.207:8545"));

- 2、导入的合约文件路径

> 注:智能合约文件目录为:./contract/erc20.sol

let source = fs.readFileSync("./contract/usdt.sol", "utf8");

- 3、需要部署的合约名称

> 注:TetherToken为修改的合约名称

let abi = JSON.parse(cacl.contracts[':TetherToken'].interface);
console.log("=============================")
console.log(abi)
console.log("=============================")

let bytecode = cacl.contracts[':TetherToken'].bytecode;
console.log(bytecode)
console.log("=============================")

- 4、部署合约的地址

> 注:该地址需要提前准备,并充值足够的ETH用于部署智能合约

let sender = "0x6e60f5243e1a3f0be3f407b5afe9e5395ee82aa2";

- 5、部署合约参数
arguments: [2718282552619854,"Tether USD","USDT",6],
> 参数解释

参数1:发行总量: 2718282552619854 (注意:此处erc20_usdt因小数位精度为6,所以需要有6位小数,)
参数2:币名全称:Tether USD
参数3:币名:USDT
参数4:小数位精度:6 (注意:此处含义是小数位精度为多少)

- 6、修改gas费
gas: 3070000,
gasPrice: 130000000000
> 注:以上表示在以太坊中部署该合约愿意花费 200 gwei * 3070000 的手续费,即0.3991 ETH,而==部署合约的地址中ETH余额必须大于此值==

# 四.解锁以太坊账户

docker exec -it eth-v1.10.5 bash
bash-5.0# geth attach

解锁以太坊账户

personal.unlockAccount('0x6e60f5243e1a3f0be3f407b5afe9e5395ee82aa2','111222333',300)
true

# 五.部署合约
命令:node deploy_usdt.js

node deploy_usdt.js

=============================
version: 1.4.0
=============================
0.4.17+commit.bdeb9e52.Emscripten.clang
=============================
......
=============================
部署成功,合约地址:
0x0f794c5803c04b18ecf5dd90ea8831212580321e

> 注:以太坊私链测试环境erc20_usdt智能合约地址:0x0f794c5803c04b18ecf5dd90ea8831212580321e

# 六.以太坊私链代币接口使用

## 6.1 获取ETH指定代币的余额
### 6.1.1 请求参数详情及解释
- 请求参数详情

{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "0x6e60f5243e1a3f0be3f407b5afe9e5395ee82aa2",
"to": "0x0f794c5803c04b18ecf5dd90ea8831212580321e",
"data": "0x70a082310000000000000000000000006e60f5243e1a3f0be3f407b5afe9e5395ee82aa2"
},"latest"
],
"id": 1
}

- 请求参数解释

method:eth_call :获取代币的余额
from:钱包地址,即转账方
to:代币地址,即智能合约地址

data数据格式:最前边的“0x70a08231000000000000000000000000”是固定的,后边“6e60f5243e1a3f0be3f407b5afe9e5395ee82aa2”的是钱包地址(不带“0x”前缀)

### 6.1.2 请求响应详情及解释
- 请求响应详情

{
"jsonrpc": "2.0",
"id": 1,
"result": "0x0000000000000000000000000000000000000000000000000009a84379f2b34e"
}

- 请求响应解释

result字段的值,就是余额

### 6.1.3 命令行请求实例

curl -H Content-Type:application/json -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"from":"0x6e60f5243e1a3f0be3f407b5afe9e5395ee82aa2","to":"0x0f794c5803c04b18ecf5dd90ea8831212580321e","data":"0x70a082310000000000000000000000006e60f5243e1a3f0be3f407b5afe9e5395ee82aa2"},"latest"],"id":1}' http://127.0.0.1:8545

请求响应:
{"jsonrpc":"2.0","id":1,"result":"0x0000000000000000000000000000000000000000000000000009a84379f2b34e"}

## 6.2 ETH代币转账
### 6.2.1 请求参数详情及解释
- 请求参数详情

{
"jsonrpc": "2.0",
"method": "eth_sendTransaction",
"params": [
{
"from": "0x6e60f5243e1a3f0be3f407b5afe9e5395ee82aa2",
"to": "0x0f794c5803c04b18ecf5dd90ea8831212580321e",
"gas": "0x186a0",
"gasPrice": "0x0",
"value": "0x0",
"data": "0xa9059cbb000000000000000000000000dac76091b14c8f638245a1a501f8ef797437515e0000000000000000000000000000000000000000000000000000000005f5e100"
}
],
"id": 1
}

- 请求参数解释

method:eth_sendTransaction :代币转账
from:钱包地址,即转账方
to:代币地址,即智能合约地址
gas:交易执行可用gas量
gasPrice:gas价格

data数据格式:
共分为三段含义:
最前边的“0xa9059cbb000000000000000000000000”是固定的,含义为转账调用的方法;
中间“dac76091b14c8f638245a1a501f8ef797437515e”是钱包地址,即接收方方(不带“0x”前缀)
最后“0000000000000000000000000000000000000000000000000000000005f5e100”是转账金额,为十六进制

### 6.2.2 请求响应详情及解释
- 请求响应详情

{
"jsonrpc": "2.0",
"id": 1,
"result": "0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1"
}

- 请求响应解释

result字段的值,就是交易哈希

### 6.2.3 命令行请求实例

curl -H Content-Type:application/json -X POST --data '{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{"from":"0x6e60f5243e1a3f0be3f407b5afe9e5395ee82aa2","to":"0x0f794c5803c04b18ecf5dd90ea8831212580321e","gas":"0x186a0","gasPrice":"0x0","value":"0x0","data":"0xa9059cbb000000000000000000000000dac76091b14c8f638245a1a501f8ef797437515e0000000000000000000000000000000000000000000000000000000005f5e100"}],"id":1}' http://127.0.0.1:8545

请求响应:
{"jsonrpc":"2.0","id":1,"result":"0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1"}

## 6.3 ETH交易哈希查询
### 6.3.1 请求参数详情及解释
- 请求参数详情

{
"jsonrpc": "2.0",
"method": "eth_getTransactionByHash",
"params": [
"0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1"
],
"id": 1
}

- 请求参数解释

method:eth_getTransactionByHash :根据交易哈希查询交易信息
0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1:需要查询的交易哈希

### 6.3.2 请求响应详情及解释
- 请求响应详情

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"blockHash": "0x34167f9d85316401e944f41ec976b8aea5d23c1f1d66f87a01954eb1cdfb4dd4",
"blockNumber": "0x800",
"from": "0x6e60f5243e1a3f0be3f407b5afe9e5395ee82aa2",
"gas": "0x186a0",
"gasPrice": "0x0",
"hash": "0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1",
"input": "0xa9059cbb000000000000000000000000dac76091b14c8f638245a1a501f8ef797437515e0000000000000000000000000000000000000000000000000000000005f5e100",
"nonce": "0x1",
"to": "0x0f794c5803c04b18ecf5dd90ea8831212580321e",
"transactionIndex": "0x0",
"value": "0x0",
"type": "0x0",
"v": "0x145878",
"r": "0x865deb166afb2c6b8fe8f2e7b43d26914d3c895a4cf94cef9f917e8fb179be66",
"s": "0x1744da9f64d0b09860a24848227038f6a5214e453593f4a5a036196c092e3dcc"
}
}

- - 请求响应解释

blockHash:区块哈希
blockNumber:区块编号
from:交易发起账号
gas:gas用量
gasPrice:gas价格
hash:交易哈希
input:交易额外数据
nonce:nonce值
to:智能合约地址
transactionIndex:交易序号
value:交易金额

### 6.3.3 命令行请求实例

curl -H Content-Type:application/json -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1"],"id":1}' http://127.0.0.1:8545

请求响应:
{"jsonrpc":"2.0","id":1,"result":{"blockHash":"0x34167f9d85316401e944f41ec976b8aea5d23c1f1d66f87a01954eb1cdfb4dd4","blockNumber":"0x800","from":"0x6e60f5243e1a3f0be3f407b5afe9e5395ee82aa2","gas":"0x186a0","gasPrice":"0x0","hash":"0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1","input":"0xa9059cbb000000000000000000000000dac76091b14c8f638245a1a501f8ef797437515e0000000000000000000000000000000000000000000000000000000005f5e100","nonce":"0x1","to":"0x0f794c5803c04b18ecf5dd90ea8831212580321e","transactionIndex":"0x0","value":"0x0","type":"0x0","v":"0x145878","r":"0x865deb166afb2c6b8fe8f2e7b43d26914d3c895a4cf94cef9f917e8fb179be66","s":"0x1744da9f64d0b09860a24848227038f6a5214e453593f4a5a036196c092e3dcc"}}

## 6.4 ETH检查智能合约交易
查看智能合约交易是否详情,是否成功
### 6.4.1 请求参数详情及解释
- 请求参数详情

{
"jsonrpc": "2.0",
"method": "eth_getTransactionReceipt",
"params": [
"0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1"
],
"id": 1
}

- 请求参数解释

method:eth_getTransactionReceipt :根据交易哈希查询交易信息
0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1:需要查询的交易哈希

### 6.4.2 请求响应详情及解释

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"blockHash": "0x34167f9d85316401e944f41ec976b8aea5d23c1f1d66f87a01954eb1cdfb4dd4",
"blockNumber": "0x800",
"contractAddress": null,
"cumulativeGasUsed": "0xdc82",
"effectiveGasPrice": "0x0",
"from": "0x6e60f5243e1a3f0be3f407b5afe9e5395ee82aa2",
"gasUsed": "0xdc82",
"logs": [{
"address": "0x0f794c5803c04b18ecf5dd90ea8831212580321e",
"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000006e60f5243e1a3f0be3f407b5afe9e5395ee82aa2", "0x000000000000000000000000dac76091b14c8f638245a1a501f8ef797437515e"],
"data": "0x0000000000000000000000000000000000000000000000000000000005f5e100",
"blockNumber": "0x800",
"transactionHash": "0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1",
"transactionIndex": "0x0",
"blockHash": "0x34167f9d85316401e944f41ec976b8aea5d23c1f1d66f87a01954eb1cdfb4dd4",
"logIndex": "0x0",
"removed": false
}],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000200000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000004000000000000008000000000000000008000000010000000000001000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0x0f794c5803c04b18ecf5dd90ea8831212580321e",
"transactionHash": "0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1",
"transactionIndex": "0x0",
"type": "0x0"
}
}

### 6.4.3 命令行请求实例

curl -H Content-Type:application/json -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1"],"id":1}' http://127.0.0.1:8545

{"jsonrpc":"2.0","id":1,"result":{"blockHash":"0x34167f9d85316401e944f41ec976b8aea5d23c1f1d66f87a01954eb1cdfb4dd4","blockNumber":"0x800","contractAddress":null,"cumulativeGasUsed":"0xdc82","effectiveGasPrice":"0x0","from":"0x6e60f5243e1a3f0be3f407b5afe9e5395ee82aa2","gasUsed":"0xdc82","logs":[{"address":"0x0f794c5803c04b18ecf5dd90ea8831212580321e","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000006e60f5243e1a3f0be3f407b5afe9e5395ee82aa2","0x000000000000000000000000dac76091b14c8f638245a1a501f8ef797437515e"],"data":"0x0000000000000000000000000000000000000000000000000000000005f5e100","blockNumber":"0x800","transactionHash":"0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1","transactionIndex":"0x0","blockHash":"0x34167f9d85316401e944f41ec976b8aea5d23c1f1d66f87a01954eb1cdfb4dd4","logIndex":"0x0","removed":false}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000200000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000004000000000000008000000000000000008000000010000000000001000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000","status":"0x1","to":"0x0f794c5803c04b18ecf5dd90ea8831212580321e","transactionHash":"0x3adb3046c4fb8e2798608256d5399a9d72f7e16eac1c6d33a7ecb1e2e96d57f1","transactionIndex":"0x0","type":"0x0"}}


# 七.报错解决
## 7.1  Error: Cannot find module 'web3'

- 使用npm部署合约时报错:Error: Cannot find module 'web3'

- 报错解决执行命令: npm install web3

## 7.2 Error: Cannot find module 'solc'

- 使用npm部署合约时报错:Error: Cannot find module 'solc'

- 报错解决执行命令: npm install solc

## 7.3 AssertionError [ERR_ASSERTION]: Invalid callback object specified.

- 使用npm部署合约时报错:AssertionError [ERR_ASSERTION]: Invalid callback object specified.

- 报错解决执行命令: 

切换solc版本为合约指定版本

npm install solc@0.4.17 单项目切换solc版本

npm -g install solc@0.4.17 全局切换solc版本