LoginSignup
1
2

More than 5 years have passed since last update.

コントラクトをweb3.eth.sendTransactionでデプロイする方法

Posted at

まえがき

コントラクトをデプロイする際にcontract addressを取得せず、transaction hashだけすぐに欲しい場合に困ったのでメモ

詳しくはこちらを参照

コントラクト

いくつかの引数をコンストラクタに持ったコントラクトを作成

pragma solidity ^0.4.23;

contract Sunday {

    uint        public uint_;
    string      public string_;
    bool        public bool_;
    address     public address_;
    uint[]      public uintArr_;

    constructor(uint _uint,string _string,bool _bool,address _address,uint[] _uintArr) public {
        uint_ = _uint;
        string_ = _string;
        bool_ = _bool;
        address_ = _address;
        uintArr_ = _uintArr;
    }

}

コントラクトのコンパイル

// 必要なパッケージをインポート
const solc = require('solc');
const Web3 = require('web3');

// web3の初期化
const web3 = new Web3();
// ネットワークと接続
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
// コントラクトの読込
let source = // 上記のコントラクトコード
// コンパイル
let contract = solc.compile(source, 1);

引数の値について

type value example
uint 123 000000000000000000000000000000000000000000000000000000000000007b
string test 00000000000000000000000000000000000000000000000000000000000000a0(offset) & 0000000000000000000000000000000000000000000000000000000000000003 + 6162630000000000000000000000000000000000000000000000000000000000
boolean true 0000000000000000000000000000000000000000000000000000000000000001
address 0xca35b7d915458ef540ade6068dfe2f44e8fa733c 000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c
uint[] [123,234,345] 00000000000000000000000000000000000000000000000000000000000000e0(offset) & 0000000000000000000000000000000000000000000000000000000000000003 + 000000000000000000000000000000000000000000000000000000000000007b + 00000000000000000000000000000000000000000000000000000000000000ea + 0000000000000000000000000000000000000000000000000000000000000159

デプロイコード

// コントラクトコンパイルの続き

// 引数一覧
let uint = 123;
let string = 'abc';
let bool = true;
let address = '0xca35b7d915458ef540ade6068dfe2f44e8fa733c';
let uintArr = [123,234,345];

// 第1引数のuint
let uintHex = web3.toHex(uint)                                          // 値をHexへ変換
let uintValue = uintHex.slice(2)                                        // 先頭の0xを削除
let uintResult =  '0'.repeat(64 - uintValue.length) + uintValue         // 左側を0で埋めて合計64文字(32byte)にする

// 第2引数のoffsetを取得
let offset1 = web3.toHex(5 * 32)                                        // offsetの計算方法は省略
let offset1Value = offset1.slice(2)                                     // 先頭の0xを削除
let offset1Result = '0'.repeat(64 - offset1Value.length) + offset1Value // 左側を0で埋めて合計64文字(32byte)にする

// 第3引数のboolean
let flg = bool ? 1 : 0
let booleanHex = web3.toHex(flg)                                        // 値をHexへ変換
let booleanValue = booleanHex.slice(2)                                  // 先頭の0xを削除
let booleanResult = '0'.repeat(64 - booleanValue.length) + booleanValue // 右側を0で埋めて合計64文字(32byte)にする

// 第4引数のaddress
let addressValue = address.slice(2)                                     // 先頭の0xを削除
let addressResult = '0'.repeat(64 - addressValue.length) + addressValue // 左側を0で埋めて合計64文字(32byte)にする

// 第5引数のoffsetを取得
let offset2 = web3.toHex((5 + 2) * 32)                                  // offsetの計算方法は省略
let offset2Value = offset2.slice(2)                                     // 先頭の0xを削除
let offset2Result = '0'.repeat(64 - offset2Value.length) + offset2Value // 左側を0で埋めて合計64文字(32byte)にする

// 第2引数のstring
let stringHex = web3.toHex(string)                                      // 値をHexへ変換
let stringValue = intHex.slice(2)                                       // 先頭の0xを削除
let stringResult = stringValue + '0'.repeat(64 - stringValue.length)    // 右側を0で埋めて合計64文字(32byte)にする

// 第5引数のuint[]
let uintCount = uintArr.length
let uintArrValue = uintArr.map((item)=>{
    let itemHex = web3.toHex(item)                                      // 値をHexへ変換
    let itemValue = itemHex.slice(2)                                    // 先頭の0xを削除
    let itemResult = '0'.repeat(64 - itemValue.length) + itemValue      // 左側を0で埋めて合計64文字(32byte)にする
    return itemResult
})
let uintArrResult = '0'.repeat(64 - web3.toHex(uintCount).length) + web3.toHex(uintCount) + uintArrValue.join(''))

デプロイ


let _data = contract.bytecode + 
            uintResult + 
            offset1Result + 
            booleanResult + 
            addressResult + 
            offset2Result + 
            stringResult + 
            uintArrResult

// 推奨ガス値取得
let _gas = web3.eth.estimateGas(_data)
// 平均ガスプライス取得
let _gasPrice = web3.eth.gasPrice
// トランザクション送出 戻り値はトランザクションハッシュ
let transaction = web3.eth.sendTransaction({
    from:_from,         // coinbase等トランザクション発行主を指定
    // to:_to,             // 今回は使用せず
    gas:_gas,           // 適当な値を指定
    gasPrice:_gasPrice, // 適当な値を指定
    data:_data,         // コントラクトのデプロイbytecode + コンストラクタの引数のHex値
    // value:_value,       // 今回は使用せず
    nonce:_nonce        // 適当な値を指定
})

_dataの中身

見やすいように32bytes毎に区切ってます

0x...                                                            // ここにはコントラクトのbytecodeが入る。長すぎるので省略
000000000000000000000000000000000000000000000000000000000000007b // 第1引数 123
00000000000000000000000000000000000000000000000000000000000000a0 // 第2引数のoffset
0000000000000000000000000000000000000000000000000000000000000001 // 第3引数 true
000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c // 第4引数 0xca35b7d915458ef540ade6068dfe2f44e8fa733c
00000000000000000000000000000000000000000000000000000000000000e0 // 第5引数のoffset
0000000000000000000000000000000000000000000000000000000000000003 // 第2引数の文字数
6162630000000000000000000000000000000000000000000000000000000000 // 第2引数のHex値
0000000000000000000000000000000000000000000000000000000000000003 // 第5引数の配列の要素数
000000000000000000000000000000000000000000000000000000000000007b // 第5引数の配列[0]のHex値
00000000000000000000000000000000000000000000000000000000000000ea // 第5引数の配列[1]のHex値
0000000000000000000000000000000000000000000000000000000000000159 // 第5引数の配列[2]のHex値

あとがき

駆け足でしたが以上。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2