Ethereum(11) - クラウドファンディング用のスマートコントラクト(キャンペーン成功)

前回は、クラウドファンディング用のスマートコントラクトを作成とデプロイを行いました。

今回は、このスマートコントラクトに対して、キャンペーンが成功するケースでテストしていきます。

コンストラクタ

デプロイ時(コンストラクタのコール時)の設定値は下記のように設定しました。

  • SELECT CONTRACT TO DEPLOY
    ‘Crowd Funding’を選択。
  • _duration
    テスト用に10分に設定。
  • _goal amount
    目標額に20etherを設定。
    Mist Walletで設定する場合はwei表記のため 20000000000000000000 を設定。

[入力イメージ画面]

アカウントごとの役割

アカウントを3つ用意し、次のように役割分担をしておきます。

  • MAIN ACCOUNT (eth.accounts[0])
    オーナー
  • ACCOUNT1 (eth.accounts[1])
    投資家1
  • ACCOUNT2 (eth.accounts[2])
    投資家2

投資家1と投資家2のアカウントからは、etherを送る必要がありますのでマイニングするなどしてetherを増やしておいてください。

[アカウントイメージ]

キャンペーンに成功するケース

geth上でcfという変数に、スマートコントラクトを割り当てます。

アドレスとインタフェースはMist Walletから取得しておきます。

[コマンド]

1
var cf = eth.contract([ { "constant": false, "inputs": [], "name": "checkGoalReached", "outputs": [], "payable": false, "type": "function" }, { "constant": true, "inputs": [], "name": "ended", "outputs": [ { "name": "", "type": "bool", "value": false } ], "payable": false, "type": "function" }, { "constant": true, "inputs": [], "name": "numInvestors", "outputs": [ { "name": "", "type": "uint256", "value": "0" } ], "payable": false, "type": "function" }, { "constant": true, "inputs": [], "name": "totalAmount", "outputs": [ { "name": "", "type": "uint256", "value": "0" } ], "payable": false, "type": "function" }, { "constant": true, "inputs": [], "name": "status", "outputs": [ { "name": "", "type": "string", "value": "Funding" } ], "payable": false, "type": "function" }, { "constant": true, "inputs": [], "name": "goalAmount", "outputs": [ { "name": "", "type": "uint256", "value": "20000000000000000000" } ], "payable": false, "type": "function" }, { "constant": true, "inputs": [], "name": "deadline", "outputs": [ { "name": "", "type": "uint256", "value": "1625274319" } ], "payable": false, "type": "function" }, { "constant": true, "inputs": [ { "name": "", "type": "uint256" } ], "name": "investors", "outputs": [ { "name": "addr", "type": "address", "value": "0x0000000000000000000000000000000000000000" }, { "name": "amount", "type": "uint256", "value": "0" } ], "payable": false, "type": "function" }, { "constant": false, "inputs": [], "name": "kill", "outputs": [], "payable": false, "type": "function" }, { "constant": true, "inputs": [], "name": "owner", "outputs": [ { "name": "", "type": "address", "value": "0x63f25b9bbd974fdfa07477cb99c60d2073cfe560" } ], "payable": false, "type": "function" }, { "constant": false, "inputs": [], "name": "fund", "outputs": [], "payable": true, "type": "function" }, { "inputs": [ { "name": "_duration", "type": "uint256", "index": 0, "typeShort": "uint", "bits": "256", "displayName": "&thinsp;<span class=\"punctuation\">_</span>&thinsp;duration", "template": "elements_input_uint", "value": "" }, { "name": "_goalAmount", "type": "uint256", "index": 1, "typeShort": "uint", "bits": "256", "displayName": "&thinsp;<span class=\"punctuation\">_</span>&thinsp;goal Amount", "template": "elements_input_uint", "value": "" } ], "payable": false, "type": "constructor" } ]).at('0xF9376fc03ebdF73713d757cB8d1cd10448D1Af2f')


deadline(終了時間)とキャンペーンのステータスを確認します。

[gethコンソール]

1
2
3
4
5
> cf.deadline()
1625274319

> cf.ended()
false


fund関数をトランザクションで呼び出します。

投資家Aと投資家Bからそれぞれ10etherを送金します。

アカウントごとにロックを解除する必要があります。

[gethコンソール]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
> personal.unlockAccount(eth.accounts[1])
Unlock account 0x63f25b9bbd974fdfa07477cb99c60d2073cfe560
Passphrase:
true

> cf.fund.sendTransaction({from:eth.accounts[1], gas:5000000, value:web3.toWei(10, "ether")})
"0x996b426f48dca2f4d47728863589748ab578cce7cd9267c511d66a476b582ca9"

> personal.unlockAccount(eth.accounts[2])
Unlock account 0xd5adf1e9fbc1ed869ed4c7372961238fddc760a5
Passphrase:
true

> cf.fund.sendTransaction({from:eth.accounts[2], gas:5000000, value:web3.toWei(10, "ether")})
"0x65f7cee0c725421ffeeb4265569948e1598337fe4b9c0916737e26bf87e760f2"


投資家Aからの投資額を確認します。

[gethコンソール]

1
2
3
4
5
> cf.investors(0)[0]
"0x63f25b9bbd974fdfa07477cb99c60d2073cfe560"

> web3.fromWei(cf.investors(0)[1], "ether")
10


投資家Bからの投資額を確認します。

[gethコンソール]

1
2
3
4
5
> cf.investors(1)[0]
"0xd5adf1e9fbc1ed869ed4c7372961238fddc760a5"

> web3.fromWei(cf.investors(1)[1], "ether")
10

それぞれ10etherずつ投資していることが確認できます。


投資の総額を確認します。

[gethコンソール]

1
2
> web3.fromWei(cf.totalAmount(), "ether")
20


コントラクトの残高を確認します。

[gethコンソール]

1
2
> web3.fromWei(eth.getBalance(cf.address), "ether")
20

目標金額の20etherに達していることが確認できます。


キャンペーンが終了する前のオーナーの残高を確認しておきます。

[gethコンソール]

1
2
> web3.fromWei(eth.getBalance(eth.accounts[0]), "ether")
27555


あとは、終了時間まで待ってcheckGoalReached関数を呼び出せば、投資された20etherがオーナーのアドレスに振り込まれるはずです。

checkGoalReached関数を実行するためには手数料(gas)が必要となりますので、オーナーのアカウントをアンロックしておく必要があります。

[gethコンソール]

1
2
3
4
5
6
7
8
9
10
11
12
13
> personal.unlockAccount(eth.accounts[0])
Unlock account 0xec3b01f36b44182746ca109230567c4915512e35
Passphrase:
true

> cf.checkGoalReached.sendTransaction({from:eth.accounts[0], gas:5000000})
"0xf3b15cbacb1b9aeaad5a646d924fe54c78f4e34b6eda37321f8b6438626b77ef"

> web3.fromWei(eth.getBalance(eth.accounts[0]), "ether")
27554.985

> cf.ended()
false

・・・なにかおかしいです。

まずcheckGoalReached関数の呼び出し自体はうまくいっているようですが、オーナーのetherが増えていません。(手数料だけはちゃんと引き落とされてます・・・)

あと修了確認のcf.ended関数を呼び出しても、キャンペーンが終わっていません。

Mist Walletで確認しても、終了にはなっておらず、投資された20etherもそのままです。
(本来であれば、目標金額に達しているのでオーナーに20etherが送金され、コントラクト上は0etherになっているはず・・)



またDeadlineを確認すると、27分前に締め切りは過ぎているようです。



今回の動きがおかしい件はスマートコントラクトの処理が問題だと思われますので、次回はデバッグを行い想定通りの処理ができるようにしたいと思います。