[ERC7787] 貢献度に応じたガバナンストークンの仕組み理解しよう！

# はじめに

『DApps開発入門』という本や色々記事を書いているかるでねです。

https://amzn.asia/d/gxvJ0Pw

今回は、徐々にガバナンス権が減衰していくガバナンストークンの仕組みを提案している**ERC7787**についてまとめていきます！

:::note info
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

https://eips.ethereum.org/EIPS/eip-7787

他にも様々なEIPについてまとめています。

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

# 概要

**ERC7787**は、ガバナンス権を譲渡不可能なトークン（ソウルバウンドトークン）として付与し、時間の経過とともにその権限が弱まっていく仕組みを提案しています。
このトークンはSoulbound Degradable Governance（SDG）と命名されています。
弱まったガバナンス権は、継続的なDAO（分散型自律組織）への参加によってのみ更新されるため、DAOの初期段階において経済力ではなく貢献度を基準としたガバナンスモデルを実現することができます。

# 動機

従来のDAOガバナンスモデルでは、通常投票権は経済的なトークンの保有量に比例する形で割り当てられます。
この仕組みは一定の用途では有効ですが大きな問題も抱えています。
特に、資本力のある少数のメンバーに権力が集中しやすくなるリスクがあります。
このような状況では、資本を持たない小規模なステークホルダーの影響力が制限され、DAOの民主的な意思決定が妨げられる可能性があります。

さらに、経済的なインセンティブを重視するこのモデルは、財務的な利益を目的とした参加者を惹きつけやすく、DAOが短期的な利益を追求する財務管理組織のような性質を帯びてしまいます。
その結果、DAOの長期的なガバナンスやコミュニティの健全な成長が後回しにされてしまうことが多くなります。

特にDAOの黎明期には、経済力に基づく統治ではなく、積極的な貢献を促すガバナンスモデルが求められます。
この提案は、ガバナンス権を経済力から切り離し、継続的な参加によってのみ政治的影響力を維持できるようにすることで、DAOの初期段階における権力の集中を防ぎつつ過度なインフレ政策に依存しない持続可能なガバナンスを実現しようとするものです。

SDGでは、ガバナンストークンが単なる所有権ではなく、DAOに対する積極的な関与を反映する「継続的な証明」として機能します。
一定期間活動を行わないとトークンの効果が減少するため、ガバナンスへの影響力を維持するには継続的な貢献が不可欠になります。
このシステムによって、投票権を長期間保持するためにはDAOの活動に積極的に関わる必要が生じ、コミュニティのエンゲージメントを促進することができます。

# 仕様

SDG（Soulbound Degradable Governance）では、ガバナンス権と経済的価値を別々のトークンで管理することが必須となります。
ガバナンスに関するトークンは譲渡不可能であり、時間とともにその効力が弱まっていく性質を持たせます。
これに対し、経済的な価値を持つトークンは自由に取引できるものであり、DAOの運営に必要な流動性や財務的な役割を果たします。
一般的には、この経済トークンは**ERC20**標準に準拠することが推奨されています。

この標準を実装する際には、以下の仕様に準拠する必要があります。

まず、ガバナンス権を持つトークンの譲渡を防ぐために、`transfer`関数を上書きし、アドレス間の移動を禁止します。
これにより、ガバナンストークンが市場で売買されることなく、DAOメンバーの権限が経済力によって左右されることを防ぐことができます。

また、時間の経過に応じてガバナンストークンの投票権を減衰させる必要があります。
そのために、`getVotes`関数を上書きし、最後に投票権が更新された時点からの経過時間を考慮して、トークンの影響力を減少させる仕組みを実装します。
投票権の減衰方式については、線形（一定の割合で減少）または指数関数的（時間が経つにつれて急激に減少）な方法を推奨しています。

さらに、DAOの透明性を確保し、メンバーが投票権の推移を追跡できるようにするため、ガバナンストークンの投票力が変化する時には適切なイベントを発行することが求められます。

## インターフェース

```js
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

interface SDG {
  /**
   * @dev Returns the grace period duration before the voting units begins decaying. This period is
   * fixed to 90 days. But it can be overridden in derived contracts.
   * @return The duration of the grace period in seconds.
   */
  function gracePeriod() public view virtual returns (uint256);

  /**
   * @dev Returns the duration of the decay period during which the voting units decreases. This
   * period is fixed to 90 days. But it can be overridden in derived contracts.
   * @return The duration of the decay period in seconds.
   */
  function decayPeriod() public view virtual returns (uint256);

  /**
   * @dev Should be implemented by derived contracts to return the current voting units of an account.
   * This function calculates the voting units based on the last time it was updated and decays it
   * over time.
   * @param account The address to check for voting units.
   * @return The current voting units of the account.
   */
  function getVotes(address account) public view virtual returns (uint256);
}
```

この標準では、以下の3つの関数を定義しています。

### `gracePeriod`

投票権が減衰し始めるまでの猶予期間を返す関数。
この期間は90日間に固定されていますが、継承したコントラクトで変更することも可能です。
例えば、新しくDAOに参加したメンバーがすぐに投票権を失わないようにするため、この猶予期間が設けられています。

### `decayPeriod`

投票権が減衰する期間を返す関数。
この期間も90日間に固定されていますが、継承したコントラクトで変更することが可能です。
投票権はこの期間内で徐々に減少し、DAOの活動に積極的に関与しないメンバーの影響力が弱まるように設計されています。

### `getVotes`

特定のアカウントの現在の投票権を計算して返す関数。
この計算では、最後に投票権が更新された時点を基準に、減衰ルールに従って投票権を算出します。
例えば、アカウントが一定期間DAOの活動に参加していない場合、その投票権は減少し続けることになります。

# 補足

SDG（Soulbound Degradable Governance）標準は、特定のトークン規格に依存せず柔軟な設計を採用しています。
これにより、DAO（分散型自律組織）は**ERC20**、**ERC721**、**ERC1155**といった既存のトークン規格だけでなく、今後登場する新しいトークン標準とも互換性を持たせることが可能になります。
この設計方針により、異なるガバナンスモデルを採用するDAOにおいても、この標準を適用しやすくなっています。

また、ガバナンス権を経済的な資産から切り離すことで、DAOの初期段階における中央集権化を防ぎつつ、積極的な参加を促す仕組みを実現しています。
通常、DAOのガバナンスはトークンの保有量に基づいて決定されることが多く、初期段階では資本力のある少数のメンバーが影響力を独占しやすい傾向があります。
しかし、SDGではガバナンストークンが譲渡不可能であり、さらに時間の経過とともにその影響力が減衰するため、DAOの活動に積極的に関与し続けなければ影響力を維持できません。
これにより、DAOの意思決定において、単なる資産の保有量ではなく、貢献度が重要な要素となります。

この標準の設計においては、初期段階のDAO運営者が特別な権限を持ったり、固定された減衰方式を組み込まないようにしています。
これにより、SDGの仕様をできるだけシンプルかつモジュール化されたものとし、DAOごとに適切な運営方法を自由に選択できるようにしています。
各DAOが独自の方針に基づいてガバナンスを構築できるようにすることで、無駄な複雑さを排除して実装の柔軟性を確保しています。
例えば、あるDAOが急激なガバナンス権の減衰を導入したい場合や、特定のメンバーに初期権限を与えたい場合にそれらはSDG標準の範囲外でカスタマイズ可能です。
この設計方針により、必要最小限のツールのみを提供しつつ、DAOごとの実験や調整の余地を確保しています。

さらに、SDGでは「猶予期間」と「減衰期間」を設定することで、公平性と流動性のバランスを取っています。
猶予期間を設けることで、メンバーは一定期間ガバナンス権を保持し、短期間の不参加によって即座に影響力を失うことがありません。
一方で、減衰期間を通じて、長期間非活動のメンバーの投票権が徐々に失われる仕組みになっています。
この設計により、DAO内での発言力や影響力が最近の貢献に応じた形で維持され、長期間非活動のメンバーが意思決定に影響を及ぼすことを防ぎます。
結果として、DAOのガバナンスが停滞せず、積極的な参加者が継続的に影響力を持ち続けるダイナミックなシステムが実現されます。

# 参考実装

```js
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

import { SDG } from "./SDG.sol"; // SDG implementation
import { SOULERC721 } from "./ERC721/SOULERC721.sol"; // Soulbounded ERC721 implementation
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; // Oz Ownable contract

/**
 * @title Valocracy
 * @dev Implements the SDG governance model where governance power decays over time if not actively maintained.
 * Only the DAO governance contract, as the owner, can mint new tokens or grant additional governance power.
 */
contract Valocracy is SDG, SOULERC721, Ownable {
  // Event emitted when voting units are updated
  event VotingUnitsUpdated(address indexed account, uint256 oldVotingUnits, uint256 newVotingUnits);

  // Sequential ID and total supply of tokens
  uint256 public totalSupply;

  // Mapping of addresses to their token IDs
  mapping(address => uint256) private _tokens;

  /**
   * @param _name The name of the ERC721 token.
   * @param _symbol The symbols of the ERC721 token.
   */
  constructor(
    string memory _name,
    string memory _symbol
  ) Ownable(_msgSender()) SOULERC721(_name, _symbol) {}

  /**
   * @dev See {IERC721Metadata-tokenURI}.
   * @notice This function returns a static string as the token URI. In a real implementation, this
   * function should return an URI that points to a JSON file with metadata about the token. Or even
   * better, a dynamic SVG that displays the governance power of the token holder.
   */
  function tokenURI(uint256 tokenId) public pure override returns (string memory) {
    return "Custom images or Dynamic NFT that displays the governance power";
  }

  /**
   * @dev See {ISDG-getVotes}.
   */
  function getVotes(address account) public view override returns (uint256) {
    uint256 grantedTime = _lastUpdateOf(account);

    // If no voting units was granted or still in grace period, return all voting units
    if (grantedTime == 0 || block.timestamp < grantedTime + gracePeriod()) {
      return _votingUnitsOf(account);
    }

    // Calculate time passed since grace period ended
    uint256 timeSinceGracePeriod = block.timestamp - (grantedTime + gracePeriod());

    // If decay period is over, return 0
    if (timeSinceGracePeriod >= decayPeriod()) {
      return 0;
    }

    // Linear decay: Calculate remaining voting units during decay period
    uint256 decayPercentage = (timeSinceGracePeriod * 1e18) / decayPeriod(); // Percentage in 18 decimals
    uint256 remainingVotes = (_votingUnitsOf(account) * (1e18 - decayPercentage)) / 1e18;

    return remainingVotes;
  }

  /**
   * @dev Grants voting units to the specified account by `amount`. Only the contract owner can
   * mint new tokens and grant additional votings units. If the users doesn't have a token, one
   * will be minted for them.
   * @param to The address to mint the new token or grant additional voting units.
   * @param amount The amount of voting units to grant alongside the token.
   */
  function grantVotingUnits(address to, uint256 amount) public virtual onlyOwner {
    if (_tokens[to] == 0) {
      _mint(to, ++totalSupply);
      _tokens[to] = totalSupply;
    }

    uint256 votingUnits = getVotes(to);
    _setVotingUnits(to, votingUnits + amount);

    emit VotingUnitsUpdated(to, votingUnits, amount);
  }

  /**
   * @notice Burns an ERC721 token and erases the voting units associated with the token holder.
   * @dev The token must exist and be burnable by the token holder or authorized entity.
   * @param tokenId The ID of the token to burn.
   */
  function burn(uint256 tokenId) public virtual {
    address from = ownerOf(tokenId);
    uint256 votingUnits = getVotes(from);

    _tokens[from] = 0;
    _setVotingUnits(from, 0);
    _burn(tokenId);

    emit VotingUnitsUpdated(from, votingUnits, 0);
  }
}
```

# 引用

Guilherme Neves (@0xneves), Rafael Castaneda <rafaelcastaneda@gmail.com>, "ERC-7787: Soulbound Degradable Governance [DRAFT]," Ethereum Improvement Proposals, no. 7787, October 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7787.

# 最後に

今回は「徐々にガバナンス権が減衰していくガバナンストークンの仕組みを提案している**ERC7787**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

他の媒体でも情報発信しているのでぜひ他も見ていってください！

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4