3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Ethereumコントラクト長期メンテTips[2025年]

Last updated at Posted at 2025-12-02

58df05e3451525016c4a8daee8af1ae33f4d82cd6cda2c0536e1c3981c851945.jpg

こんにちは。Tomo(X: HAIL)といいます。この記事はWeb3 Advent Calendar 2025 2日目の記事になります。

最近ステーブルコイン周りやDeFi, Prediction Marketあたりをよく見ているのでそのあたりのことを書こうかなとも思ったんですが、これまで5年以上にわたり同じEthereumスマートコントラクトをメンテナンスしてきたので、長くメンテするTipsをまとめようかなと思いました。
読者層としては、Ethereum開発の初級者~中級者を想定しています。こんなん分かるわというところは適宜飛ばしてお読みください。
実際長期メンテナンスしてきたコードはこちらにあります。

開発初期

フレームワーク、ライブラリ

新しくプロジェクトを始めるなら、まずは

ではじめられるでしょう。IDEについては僕はCursor、AIモデルはGPT-5かGemini 3を使っていますが、まあここは個人の好み次第でしょう。コードを書き、テストし、デプロイする。多くのプロジェクトにおいて初期のコードはこれらだけで完成するのではないでしょうか。OpenZeppelinでカバーされていないものが欲しくなったら

あたりを見てみると良いかも。しかし経験者の方はよく分かっていると思いますが、ブロックチェーン開発で大事なのは「長く信用できるか」「代替手段が見つかるか」です。その点において、OpenZeppelin, Alchemy, Consensys あたりはいなくならない信用が置けます。ただ後ろ2つも個別プロダクトの撤退はしています。例えばAlchemyのSubgraph, ConsensysのInfura ITXあたりは撤退済みもしくは撤退が決定しており、それぞれ代替手段を見つけることとなりました。長くなるのでこれらが何だったのかの解説は控えます。

Upgradability

Web2と違いデプロイされたコードはimmutable(変更不可)です。ですので初回リリース以降にロジックをアップデートするかもしれない、しかしそのアドレスが変更されてしまっては困るものについては初回リリース前に対応をする必要があります。それがProxyパターンです。ウォレットや呼び出し元コントラクトは不変のProxyアドレスを参照し、そのProxyが可変のImplementation(実装)アドレスを持つ形です。
詳しくはOpenZeppelinのドキュメントを読むもしくはLLMに食わせてもらえればと思いますが、おすすめはまずUUPSUpgradeableで考える、もしFactoryパターンなどと併用して、複数のProxyのImplementationを一気に変更したいという需要があればBeaconProxyを考えましょう。なんか違うなと思ったら何が違うかを言語化してAIに聞きましょう。Proxy自体をリリース後に取り替えるというのは不可能もしくは凄く大変です。そういう意味でも枯れたものを使うほうが安全で、OpenZeppelinに頼っておくのが安心です。

ストレージ衝突防止

コントラクトに何かデータ( unit256 bytes32 mapping )などを保存していくと思いますが、それぞれにはスロットが割り当てられており、その割り当ては記載してある順番や、importしているライブラリの順番に依存しています。なので安易に

    mapping(address account => uint256) private _balances;
    mapping(address account => mapping(address spender => uint256)) private _allowances;
    uint256 private _totalSupply;
    string private _name;
    string private _symbol;

から

    uint256 newUint256Value; // 一番下以外に新規追加
    mapping(address account => mapping(address spender => uint256)) private _allowances;
    uint256 private _totalSupply;
    mapping(address account => uint256) private _balances; // 並び替え
    string private _name;
    string private _symbol;

などにリリース後に変更すると破綻します。より詳しくは他の記事やAIに聞いてもらえればと思いますが一回ミスると面倒すぎると思うので気をつけましょう。何かプラグインなどを使うかEIP-7201 Namespaced Storage Layoutを使うのが良いです。

Explorer

image.png

メインネットで言うところのEtherscanに相当するものですね。ローカルでAnvil(Foundryフレームワークの一部。ローカルで高速動作するEVM)にコントラクトをデプロイして、ウォレットから何かトランザクションを投げて、その動作を確認するのにエクスプローラが欲しいこともあります。Otterscanを使いましょう。公式のDockerイメージですぐに使えます。

新しいコードを参照する

大分マシになりましたが、SolidityはC, Java, Goなどのように熟した言語ではないし、EIPも次々提案されます。例で言うと、バリデーションとそれにもとづくエラー処理などは require を使うのが良かったですが、 error 構文が後から追加されました。人のコードを参考にする際には、書かれた日時やSolidityのバージョン(pragma solidity ^0.8.30;)の部分を見て新しい情報か気をつけましょう。

開発中期

フレームワーク, ライブラリ

初回リリースを過ぎ、コード量がかさみチーム体制も大きくなってきました。E2Eっぽいテストやロジックの分割、より効率的なデプロイなどを考えるようになります。そのときに役立ってくるのは

あたりでしょう。

まずHardhatについては、Foundry登場以前は開発初期からほぼ導入必須な開発フレームワークでした。TypeScriptでテストやデプロイを管理します。Foundryが出たことで、Solidityで完結できるようになり初期の開発には不要になってきたと感じますが、Solidityでは表現しづらい複雑なデプロイのロジックやテストを書きたいときにはHardhatが活躍します。冒頭でリンクしたプロダクトは5年ものなので、Hardhatではじめて途中からFoundryを導入したものですが、何がHardhatでテストされているのかやデプロイの仕組みなど参考になれば幸いです。

EIP-2535については、先に述べたProxyの先のImplementationコントラクトが巨大になってきたり、もしくは複数のコントラクトが同じ共通ライブラリを呼びたいときに重宝します。実装については記載済みのSolidStateなどを利用してください。

EIP内の画像
EIPにある画像

Tenderlyについては、自分たちのTestnetが欲しい、MainnetやPublic testnetをコピーしてきて新規のトランザクションをシミュレーションしたい、既存のトランザクションを分析したいみたいな、複数人数での開発やリリース済みプロダクトの分析に役立つプロダクトを複数リリースしています。

これまでのデプロイを再現できるようにしておく

方法はDevnet, Testnetのsnapshotを取っておくでも、以下の画像のようにデプロイごとにバージョンを振って保存しておくでも良いのですが、いつでも過去のデプロイをすべて再現し、その後に次リリースのデプロイをして問題が起きないかのRegression Testができるようにしましょう。

image.png

開発中はロジックを書き換え、Unit Testを書き、最新のものだけデプロイして使ってみて、で良いのですが長く運用しているものほど新規ではなく追加でデプロイをしようとしたときに問題が起きがちです。本番同様の追加デプロイができる状況を確保しておきましょう。

Auditを受ける

ユーザが増えトラクションが出てくると攻撃する人も出てくるので、AIに脆弱性がないか聞くのは勿論のことですがプロのAuditを受けたほうが安全です。いくつかサービス挙げておきます。

鍵が一つ奪われたら終わり、という状況を避ける

96a5b3285209547ea5623bbc0c7c60841cd57e1d053ddb454a8ff69898deed11.jpg

  • 複数のウォレットが署名しないと大事な命令(コントラクトのアップグレード、コントラクトからの資産の引き出しなど)が実行できないようにする
  • OpenZeppelinのAccessControlUpgradeableなどを使って複数のRoleを定義し、一つのアドレスが全管理者権限を持たないようにする
  • KMS(AWS, GCP)などを使い、そもそも秘密鍵を知らないで署名が行える環境を作る

などを行い、鍵が一つ奪われたらサービス運営が崩壊する自体を防ぎましょう。

ちなみに上のは「鍵が一つ奪われたら終わり、という状況を避ける」を表す画像をテキスト無しで生成して、とGPTに言ったら作られた画像。全然分かんないけどなんか面白い。

データ分析

自分たちのプロダクトや他社のプロダクトを分析したいとなったとき、言わずもがなですがブロックチェーンはデータをindexすること、検索、分析することに優れている構造ではないのでSQLやGraphQLでクエリできる環境にデータを移して分析する必要があります。DuneGOLDSKYなどを活用しましょう。

各種ウォレット対応

常人にはEthereumの秘密鍵は扱えない、強い人でも一つ漏らしたら終わりというのはひどい、ユーザではなくサービスプロバイダ側がトランザクション手数料(gas代)を払えるようにしたいなど様々な懸念から様々なウォレットやそれを支えるEIPが提案されてきました。書いたコントラクトの関数をどう叩くか、呼び出し元(e.g. msg.sender)をどう取得するかなど作法が違ったりするので、いくつかのEIPに目を通しておきましょう。

Stripeに買収されたPrivyも見ておくと良いでしょう。

終わりに

読んでいただきありがとうございました。少しでも役に立つTipsがあったら幸いです。

image.png

私事ですが、ちょうど転職をしまして、Tanéという組織にCTOとしてジョインしました(X)。FounderのXはこちらです。

ウェブサイト上では投資リサーチ会社とあるのですが、各種ブロックチェーンプロダクトのガバナンス、バリデータに関わっている他、新規でプロダクト開発を行っているところです。領域はPrediction Market, DeFi(ステーブルコイン含む), ブロック生成ミドルウェアあたりを見ています。エンジニア(特にフロントエンドとブロックチェーンが分かる勢)、デザイナーなど幅広く募集しています。Xで連絡いただければ嬉しいです!

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?