問題一覧に戻る
上級高度なパターン
問題91: ダイヤモンドパターン

Solidityのダイヤモンドパターンを学習 - 無制限の関数追加を持つモジュラーアーキテクチャ。ダイヤモンドはファセット(コントラクト)で機能を整理し、コントラクトサイズ制限を回避。関数セレクターがdelegatecallルーティングで特定ファセットアドレスにマップ。このEIP-2535標準は無制限コントラクト機能、モジュラーアップグレード、共有ストレージを可能にします。ダイヤモンドの理解は大規模でモジュラーなスマートコントラクトシステム構築に重要です。

pragma solidity ^0.8.0;

struct FacetCut {
address facetAddress;
uint8 action; // 0=add, 1=replace, 2=remove
bytes4[] functionSelectors;
}

contract DiamondStorage {
// 関数ルーティング用ダイヤモンドストレージ
mapping(bytes4 => address) internal facets;
address[] internal facetAddresses;
}

contract Diamond is DiamondStorage {
// fallbackがファセットに呼び出しをルーティング
fallback() external payable {
address facet = facets[];
require(facet != address(0), "Function not found");

// ファセットへのdelegatecall
assembly {
calldatacopy(0, 0, calldatasize())
let result := (gas(), facet, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())

switch result
case 0 { revert(0, returndatasize()) }
default { return(0, ) }
}
}

// 関数管理用ダイヤモンドカット
function diamondCut(FacetCut[] memory cuts) external {
for (uint256 i = 0; i < cuts.length; i++) {
FacetCut memory cut = cuts[i];

if (cut.action == 0) { // Add
_addFunctions(cut., cut.functionSelectors);
} else if (cut.action == 1) { // Replace
_replaceFunctions(cut.facetAddress, cut.);
}
}
}

// 新しい関数を追加
function _addFunctions(address facet, bytes4[] memory selectors) internal {
for (uint256 i = 0; i < selectors.length; i++) {
facets[selectors[i]] = ;
}
}

// 既存関数を置換
function _replaceFunctions(address facet, bytes4[] memory selectors) internal {
for (uint256 i = 0; i < ; i++) {
facets[selectors[i]] = facet;
}
}
}

// ファセット実装例
contract UserFacet {
mapping(address => string) public names;

function setName(string memory name) external {
names[] = name;
}

function getName(address user) external view returns (string memory) {
return [user];
}
}