LoginSignup
8
3

More than 5 years have passed since last update.

Slack の Reaction で ERC20 Token を付与するシステムを自分でも作ってみた

Posted at

はじめに

tiperc20: Slack上でERC20トークンを送りあってコミュニケーション
の話を聞いて、これは面白そうだと思ったので、勉強がてら自分で実装してみました。

基本的には、この repository のコンセプトを nodejs で実装し直した形です。

また、誰が誰に何のリアクションでトークンを送ったかを簡単に確認出来るように、ちょっとした web 面も作りました。

image.png

ユーザーは slack で自分の発言に reaction がつくと、前もって登録しておいた自分の Ethereum アカウントに ERC20 準拠の Token をもらえます。チームの Ethereum に対するリテラシー向上や Slack チーム内のコミュニケーションを促す目的での導入を想定しています。

ユーザー体験

1. Slack 上から自分の Ethereum Address を登録する

slash command を先に登録しておいて、address を登録します
スクリーンショット 2018-03-31 15.57.36.png

App が、アドレスを登録したよ!と教えてくれます
スクリーンショット 2018-03-31 15.57.44.png

これで準備は完了です

2. イケてる発言を行い、誰かが Reaction をつけてくれるのを待つ

スクリーンショット 2018-03-31 16.00.52.png

3. Reaction がついたら、Web サイトや Metamask などを見て Token が付与されたのを確認

スクリーンショット 2018-03-31 16.03.54.png

トークンの付与とガスの支払いアカウントに関して

ERC20 トークンを発行したマスターアカウントの秘密鍵を nodejs のサーバーに環境変数として保管し、Token 付与はそのアカウントから行います。

このサーバーに保存したアカウント (便宜上マスターアカウントと呼ぶことにします) が Token 付与のガス代を支払うため、マスターアカウントには Ethereum をディポジットしておく必要があります。

全体の構成

全体の構成は以下のような感じです。

slack-token-image4.png

Ethereum へは Infura API を通してアクセスします。

Reaction 発生時の処理

Reaction は Slack の Event API 経由で受け取ります。

Reaction が発生したら

  1. ユーザーの slack userid から上記で登録した ethereum address を取得します。
  2. reaction の種類が予め登録されたものかどうかをチェックし、token を送信するための job を作って queue に入れます。
  3. Queue に入った job は 1 つずつ順番に取り出され、token の付与を行う Tx を作って ethereum に投げます。

slack-token-image5.png

Job Queue の必要性

Ethereum には Account nonce と呼ばれる仕組みがあり、各アカウントのトランザクションは順番にしか実行できません。

Account nonce: a transaction counter in each account. This prevents replay attacks where a transaction sending eg. 20 coins from A to B can be replayed by B over and over to continually drain A's balance.

https://github.com/ethereum/wiki/wiki/Glossary

リアクションが一斉についたりした際に、1 つ前のトランザクションが終わる前に次のトランザクションを発行しようとすると nonce が合わなくなる可能性があります。

web3 (1.0系) では transaction を sign する際に nonce を指定しなければ自動で account の transaction カウントを取得して利用します。(http://web3js.readthedocs.io/en/1.0/web3-eth-accounts.html?highlight=nonce#signtransaction)

この挙動によって、トランザクションの結果が確定する前に次のトランザクションを署名してしまうと、同じ nonce を持ったトランザクションが作られてしまうためどちらかが必ず失敗してしまいます。これを避けるために job queue を利用して順番にトランザクションを処理していく方法を採用しました。

使い方

ここからは、実際のシステムの使い方を説明していきます。作成した repository は こちらです。

ライブラリのインストールとイメージの起動

システムは docker-compose を利用しているため、Docker for Mac などを予めインストールしておく必要があります。

repository を git clone したら、まずは依存関係のあるライブラリをインストールします。

$ sh script/prepare.sh

インストールが終わったら docker-compose を起動します。

$ sh script/dev/start.sh

環境ファイル

環境ファイルは ./app 以下に .env という名前で作成します。
例となるファイルをコピーして作っても問題ありません。

$ cp ./app/.env.example ./app/.env

内容は以下を参考に自分の環境に合わせて埋めてください

MONGO_DATABASE=slack-token

SALT=

ETHERESCAN_URL=https://<main 以外の場合はネットワーク名>.etherscan.io/
INFURA_ENDPOINT=https://rinkeby.infura.io/<Access Token>
SERVER_ACCOUNT_ADDRESS=<Ether account address>
SERVER_ACCOUNT_PRIVATE_KEY=<Ether account private key>
CONTRACT_ADDRESS=<Deploy 済みの ERC20 token address>

SLACK_CLIENT_ID=
SLACK_CLIENT_SECRET=
SLACK_VERIFICATION_TOKEN=
SLACK_TOKEN=<起動時に emoji.list を叩いてカスタム絵文字を取得するために使う>

# カンマ区切りで記載。指定しなければ全てに反応する
EMOJI=slightly_smiling_face,bug

# カンマ区切りで Slack のチャンネルIDを記載。指定しなければ全てに対応する
CHANNEL=

ここで指定した SERVER_ACCOUNT_ADDRESS アカウントがマスターアカウントになります。CONTRACT_ADDRESS は Token を作成して Deploy した後で記載してください。また、設定した INFURA_ENDPOINT の向先によって、どのネットワークを利用するかが決まります。

Token の作成と Deploy

まずは、Token を作成します。

app/contract/contracts/CustomToken.sol の変数を修正してください

string public name = "Token の名前";
string public symbol = "TICKER";
uint8 public decimals = 18; // Token の最小単位 
uint256 initialSupply = 10000e18; // 初期発行量 (1 = 最小単位なのでこの場合 10000 token の発行になる) 

コントラクトのテスト

ganache-cli を利用して、実際に ethereum の network にはコントラクトを deploy せずにテストを行い、正しく solidity が記述できているかを確認します。

$ sh script/contract/test.sh

Deploy

$ sh script/contract/deploy.sh

Deploy されたら、環境ファイルにコントラクトアドレスを記載してください。

サーバーを立ち上げる

Slack App を配布するためには https 化する必要がある (恐らく配布時のみ?) 参考

Let's encrypt などで取得した fullchain.pemprivkey.pem を この repository の root に置いてください (Symbolic link でも問題ありません)

本番(ステージング)環境でシステムを起動する際には docker-compose-ssl.yml を使います。ssl 用の証明書は実行時に volume mount されます。

# 下記コマンドで ssl 設定をしてある nginx image を build します
$ sudo sh script/stg/build.sh

# 下記コマンドで証明書を上記コンテナにマウントしつつ、docker-compose でサービスを起動します
$ sudo sh script/stg/start.sh

Slack との結合

Scope

Slack token を利用するためには以下のスコープの設定が必要です。

  • Slash command Scope
  • Reactions Scope
  • Emoji Scope

slack-token-image7.png

Slash command

Slack の slash command は /api/register/ に来るように設定してください

slack-token-image1.png

Reaction Event

Event は reaction_added を購読してください。Slack の管理画面メニューの Event Sbuscriptions を選択して、Event 送信先の Request URL を指定します。Add Workspace Event ボタンから reaction_added を追加してください。

Emoji

カスタム絵文字対応を行うために emoji.list API を起動時に呼びます。API を呼ぶための Token を管理画面から取得して、.envSLACK_TOKEN に指定してください。

動作確認

設定が完了したらサーバーを起動してください。サーバーに ssh した状態で docker の状態を確認すると下記のようにプロセスが立っているはずです。

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                      NAMES
hogehogehoge        slack-token-nginx   "nginx -g 'daemon of…"   2 days ago          Up 2 days           0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   slack-token-nginx
hogehogehoge        slack-token-queue   "/bin/sh -c 'node qu…"   2 days ago          Up 2 days                                                      slack-token-queue
hogehogehoge        slack-token-app     "/bin/sh -c 'node ap…"   2 days ago          Up 2 days                                                      slack-token-app
hogehogehoge        slack-token-mongo   "docker-entrypoint.s…"   2 days ago          Up 2 days           27017/tcp                                  slack-token-mongo
hogehogehoge        slack-token-redis   "docker-entrypoint.s…"   2 days ago          Up 2 days           6379/tcp                                   slack-token-redis

ブラウザからアクセスしてみてください。Web 面が表示されるはずです。

この状態で、slack から reaction を付け、Web 面をリロードすると処理中のトランザクションが表示されます。Etherscan へのリンクを表示するようにしているのでクリックすれば Etherscan からトランザクションを確認する事が出来ます。

終わりに

自分で作ってみると勉強になる事が多くて、今後も出来るだけ手を動かして行きたいと思いました。
account nonce 周りの対応などはこれがベストプラクティスかはまだ解っていないので、もっと良いやり方をご存知の方がいらっしゃれば是非教えて下さい。

8
3
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
8
3