Ethereumのトランザクションの流れ(1) フロント編


web3.jsからトランザクションを実行する流れを追っていきます。
web3.jsのversionはv1.0.0-beta.36です。

call web3編

transfer(address) を実行するコード

const Web3 = require('web3');
const web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
web3.eth.defaultAccount=web3.eth.accounts[0];
const ABI = require("./abi.js").abi;

const ADDRESS = "0x09ce7c529fd05ca8e5599f0ed424f48cd2a5424e";
const OWNER = "0x0be26a388d0524eeb0afbc08ee015e08e83e802c";
const contract = new web3.eth.Contract(ABI, ADDRESS);

const transfer = async (address) => {
    return await contract.methods.transfer(address, 100).send({
        from: OWNER,
    });
};

(async () => {
    console.log(await transfer("0xfc49f3aedc6d2f0cab4e0a1ff66913ccf2fe3661"));
})();

json-rpcとして下記のリクエストを実行する

{ jsonrpc: '2.0',
  id: 3,
  method: 'eth_sendTransaction',
  params:
   [ { from: '0xd986f2cb72530f45bfd575196fbad7064c454ecc',
       data:
        '0xa9059cbb000000000000000000000000d986f2cb72530f45bfd575196fbad7064c454ecc0000000000000000000000000000000000000000000000000000000000000064',
       gasPrice: '0x1',
       gas: undefined,
       to: '0xf30a6701ff5e70aabf27f474b3b4ae72563c3217' } ] }

dataの仕組み

signatureの作成

    {
      "constant": false,
      "inputs": [
        {
          "name": "_to",
          "type": "address"
        },
        {
          "name": "_value",
          "type": "uint256"
        }
      ],
      "name": "transfer",
      "outputs": [
        {
          "name": "",
          "type": "bool"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    }

上のようなabiのObjectから

// web3.js/packages/web3-eth-abi/src/index.js
var utils = require('web3-utils');
// 省略
ABICoder.prototype.encodeFunctionSignature = function (functionName) {
    if (_.isObject(functionName)) {
        functionName = utils._jsonInterfaceMethodToString(functionName);
    }

    return utils.sha3(functionName).slice(0, 10);
};

transfer(address,uint256) が 0xa9059cbbになる

引数の部分

// web3.js/packages/web3-eth-abi/src/index.js
ABICoder.prototype.encodeParameters = function (types, params) {
    return ethersAbiCoder.encode(this.mapTypes(types), params);
};

var ret = coder.encodeParameters(['address'], ['0xd986f2cb72530f45bfd575196fbad7064c454ecc']);

で、 000000000000000000000000d986f2cb72530f45bfd575196fbad7064c454ecc0000000000000000000000000000000000000000000000000000000000000064 となる