Vinu Digital’in karmaşık ve yükseltilebilir Solidity sistemlerinde neden ERC-2535 Diamond Proxy kullandığını; UUPS, Beacon, Diamond Storage ve mimari trade-off’lar üzerinden inceleyin.
Vinu Digital, büyük, gelişen ve heterojen yükseltilebilir Solidity sistemlerinde ERC-2535 Diamond Proxy kullanır; çünkü bu mimari selector seviyesinde yükseltmeler, modüler facet yapıları, açık storage mimarisi, standartlaştırılmış introspection ve sabit bir kontrat adresi sunarken sistemin birden fazla sürüm döngüsü boyunca gelişmesine olanak tanır.
Daha küçük ve bütünlüklü bir mantık yüzeyine sahip sistemlerde UUPS daha iyi bir seçenek olmaya devam edebilir. Birlikte yükseltilmesi gereken homojen kontrat instance’larından oluşan yapılar için Beacon Proxy çoğu zaman doğru abstraction’ı sunar. Ancak yükseltilebilirlik gerçek bir yaşam döngüsü gereksinimi olduğunda ve sistemin birden fazla domain boyunca büyümesi beklendiğinde, ERC-2535’i uzun vadede daha güçlü bir mimari olarak değerlendiriyoruz.
Bu ayrım önemlidir çünkü yükseltilebilirlik yalnızca bir akıllı kontratın devreye alındıktan sonra değiştirilip değiştirilemeyeceğiyle ilgili değildir. Asıl mesele, sistemin ne kadarının değişmesi gerektiği, bu değişikliklerin nasıl yönetildiği, storage’ın nasıl güvenli kaldığı ve karmaşıklık arttıkça mimarinin ne kadar anlaşılır kalabildiğidir.
Değişmezlik, Operasyonel Bir Kısıta Dönüşene Kadar Güçlüdür
Ethereum, çoğaltılmış bir durum makinesidir: her node aynı işlemleri ortak durum üzerinde yürütür ve devreye alınmış bir akıllı kontrat, zincir üstünde belirli bir adrese bağlı kod ve kalıcı storage’dan oluşur. Bu yürütme modeli, kontratların pratikte deterministik olmasının ve blok zinciri sistemlerinin güven modelinin önemli bir bölümünü devreye alındıktan sonra sessizce değiştirilemeyen koddan almasının temel nedenidir.
Ethereum’un kendi dokümantasyonu da devreye alınan akıllı kontratların, deployment sırasında tanımlanan iş mantığını yürüttüğünü ve geliştiriciler açıkça bir yükseltme mekanizması eklemediği sürece tasarım gereği değişmez olduğunu vurgular.
Bu değişmezlik yalnızca estetik bir tercih değildir. Tek taraflı müdahaleyi sınırlar, yönetişim belirsizliğini azaltır ve denetim kapsamını istikrarlı tutar. Ancak aynı özellik, production kodunun yayına alındıktan sonra güvenlik yaması, hata düzeltmesi, özellik genişletmesi veya standart güncellemesi gerektirdiği durumlarda mühendislik açısından bir çıkmaza da dönüşebilir.
Ethereum’un dokümantasyonu bunu doğrudan belirtir: değişmezlik, trustless yapı ve güvenlik için gereklidir; ancak iş mantığının gelişmesi gerektiğinde dezavantaj haline gelebilir.
Bu nedenle yükseltilebilirlik kendi başına bir anti-pattern değildir. Asıl soru mimaridir: ciddi bir protokol yüzeyi için hangi yükseltilebilirlik biçimi en düşük operasyonel riski ve en iyi uzun vadeli sürdürülebilirliği sağlar?
Küçük ve istikrarlı sistemlerde cevap minimal proxy’ler veya UUPS olabilir. Factory odaklı yapılarda Beacon çoğu zaman uygun bir seçimdir. Büyük, gelişen ve domain açısından zengin sistemlerde ise Vinu Digital olarak cevabımız nettir: ERC-2535 olarak standartlaştırılmış Diamond Proxy, üstün production pattern’idir.
ERC-2535 Diamond Proxy, UUPS ve Beacon: Yükseltilebilirlik Mimarisinin Genel Görünümü
Genel olarak bugün Solidity mimarları açısından en önemli üç yükseltilebilir pattern UUPS (Universal Upgradeable Proxy Standard), Beacon Proxy ve Diamond Proxy’dir.
UUPS, yükseltme mantığını implementation kontratına yerleştirir ve genellikle ERC-1967 slotlarını kullanır. Beacon, çok sayıda proxy’yi aktif implementation’ı döndüren ortak bir beacon kontratı üzerinden yönlendirir. Diamond ise ayrı ayrı function selector’ları facet kontratlarına yönlendirerek sistemin kontrat bazında değil, fonksiyon bazında gelişmesine olanak tanır.
| Pattern | Yükseltme Birimi | Operasyonel Yapı | Tipik En Uygun Kullanım |
|---|---|---|---|
| UUPS | Tüm implementation | Bir proxy tek bir implementation’a delegate eder; yükseltme mantığı implementation içinde bulunur | Görece bütünlüklü bir mantık yüzeyine sahip, yalın tek sistem yükseltmeleri |
| Beacon Proxy | Ortak implementation’ın tamamı | Çok sayıda proxy implementation bilgisini tek bir beacon’dan alır ve ona delegate eder | Aynı anda yükseltilmesi gereken büyük homojen instance filoları |
| Diamond | Facet’ler altında gruplanmış ayrı selector’lar | Tek bir Diamond adresi farklı selector’ları farklı facet kontratlarına delegate eder | Büyük, modüler, uzun ömürlü ve heterojen özelliklere sahip sistemler |
OpenZeppelin’in proxy dokümantasyonu UUPS’ı açık biçimde lightweight ve versatile bir çözüm olarak, Beacon’ı ise çok sayıda proxy’nin birlikte yükseltilmesi gerektiğinde kullanılan pattern olarak tanımlar. Buna karşılık ERC-2535 Diamond Proxy, “virtually no size limit” sunan modüler ve multi-facet bir proxy yapısını standartlaştırır.
Yükseltme granularity’sindeki bu fark, mimari açıdan en önemli ayrım noktasıdır. UUPS ve Beacon implementation değiştirir; Diamond ise protokol yüzeyinin kendisini düzenler.
Vinu Digital Neden ERC-2535 Diamond Proxy Üzerinde Standardizasyon Sağlıyor?
Vinu Digital olarak yükseltilebilir kontratların gerçekten gerekli olduğu durumlarda, Nick Mudge tarafından geliştirilen Diamond Proxy (ERC-2535) yaklaşımını standart olarak kullanıyoruz. Bunun nedeni, karmaşık protokollerin gerçekte nasıl geliştiğiyle en iyi şekilde örtüşmesidir: tek bir monolitik implementation’ın tamamen yeniden yazılması şeklinde değil; farklı özelliklerin, izinlerin, workflow’ların ve domain modüllerinin zaman içinde büyüyen bir yapısı olarak.
ERC-2535; devreye alındıktan sonra genişletilebilen, tek kontrat boyutu sınırını aşabilen ve mevcut işlevselliğin tamamını ortadan kaldırmadan fonksiyon ekleyebilen, değiştirebilen veya kaldırabilen modüler sistemler için özel olarak tasarlanmıştır.
Bu bir stil tercihi değildir. Bir production mimarisi kararıdır.
Diamond modeli bize sabit bir sistem adresi, facet’ler üzerinden neredeyse sınırsız işlev yüzeyi, DiamondCut event’leri aracılığıyla açık yükseltme kayıtları, loupe fonksiyonlarıyla zorunlu introspection ve kod tabanı büyüdükçe geleneksel proxy layout’larına kıyasla çok daha anlaşılır hale getirilebilen bir storage modeli sunar.
Standardın kendi motivasyon bölümü; sınırsız işlev için tek bir adresi, fine-grained yükseltmeleri, modüler organizasyonu, atomik çoklu fonksiyon değişikliklerini ve daha sonra sistemin immutable hale getirilebilmesini özellikle vurgular.
Bu kombinasyon en çok, protokolün birden fazla sürüm döngüsünü, birden fazla ekibi, denetim ekiplerindeki değişiklikleri, yönetişim geçişlerini ve standart değişikliklerini aşarak uzun süre yaşamasının beklendiği durumlarda önem taşır.
Bu tür ortamlarda kazanan mimari en küçük proxy değildir; yıllar boyunca biriken karmaşıklığa rağmen anlaşılır ve güvenli biçimde geliştirilebilir kalabilen mimaridir.
Diamond’lar, başlıca proxy aileleri arasında en başından itibaren bu varsayım üzerine tasarlanmış tek yapıdır.
ERC-2535 Diamond Proxy Execution’ı Nasıl Yönlendirir?
ERC-2535 Diamond Proxy, function selector’ları ayrı facet kontratlarına eşleyerek ve bunların kodunu delegatecall üzerinden çalıştırarak çağrıları yönlendirir.
Bir Diamond, calldata’nın ilk dört byte’ını inceleyen bir fallback function içeren proxy’dir. Function selector, ilgili selector’dan hangi facet’in sorumlu olduğunu belirler ve Diamond daha sonra facet’in kodunu delegatecall aracılığıyla yürütür.
Solidity’nin ABI spesifikasyonu selector’ı, canonical function signature’ın Keccak-256 hash’inin ilk dört byte’ı olarak tanımlar ve ERC-2535 bu selector’ı açık biçimde Diamond’ın dispatch katmanındaki routing key olarak kullanır.
Kavramsal olarak dispatch path şu şekilde görünür:
fallback() external payable {
address facet = selectorToFacet[msg.sig];
require(facet != address(0), "FunctionNotFound");
assembly {
calldatacopy(0, 0, calldatasize())
let ok := delegatecall(
gas(),
facet,
0,
calldatasize(),
0,
0
)
returndatacopy(0, 0, returndatasize())
switch ok
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
Bu akış standardın routing modelini yansıtır: calldata kopyalanır, çözümlenen facet delegatecall ile çalıştırılır ve return data dış çağrıyı yapan kullanıcıya geri iletilir.
delegatecall, callee kodunu caller bağlamında yürüttüğü için msg.sender ve msg.value değişmeden kalır ve tüm okuma ve yazma işlemleri facet’in storage’ında değil, Diamond’ın storage’ında gerçekleşir. Solidity’nin kendi dokümantasyonu delegatecall mekanizmasını aynı şekilde tanımlar ve ERC-2535 bu özelliği doğrudan kullanır.
diamondCut ERC-2535 Yükseltmelerini Nasıl Yönetir?
Yükseltme yüzeyi diamondCut içinde tanımlanır.
Tüm implementation adresini değiştirmek yerine diamondCut, her bir öğenin bir facet adresi, bir işlem — Add, Replace veya Remove — ve bir selector seti içerdiği bir değişiklik dizisi alır.
Standart ayrıca _init adresi ve _calldata payload’ı aracılığıyla, yine aynı işlem içinde delegatecall ile post-cut initialization yapılmasına olanak tanır.
Bu önemli bir mühendislik avantajıdır: veri migration mantığı, ayrı operasyonel adımlara dağıtılmak yerine kod değişikliğiyle aynı transaction içinde bağlanır.
ERC-2535 ayrıca tüm değişikliklerin tek bir transaction içinde yürütülmesinin, yükseltmelerin birden fazla transaction’a bölündüğü durumlarda ortaya çıkabilecek bozulmaları önlediğini belirtir.
Diamond Loupe ve Fonksiyon Seviyesinde Introspection
Diamond yapıları ayrıca Diamond Loupe interface’i üzerinden introspection’ı standartlaştırır.
Uyumlu bir Diamond şu fonksiyonları sunmak zorundadır:
facets()facetFunctionSelectors(address)facetAddresses()facetAddress(bytes4)
Bu, ilk bakışta göründüğünden çok daha önemlidir.
Geleneksel bir proxy’de yalnızca doğrulanmış kaynak kodu görmek, bileşik bir sistemde fonksiyon bazındaki canlı routing yapısını size göstermez. ERC-2535 Diamond Proxy’de ise standart, fonksiyon grafiğinin machine-readable biçimde incelenebilmesini zorunlu kılar.
Daha da önemlisi, her selector değişikliği DiamondCut event’i aracılığıyla kaydedilmelidir.
ERC-2535 bunu bir şeffaflık avantajı olarak tanımlar: Diamond’lar hem loupe fonksiyonları üzerinden mevcut routing yapısının anlık görüntüsünü hem de event’ler üzerinden tüm fonksiyon ekleme, değiştirme ve kaldırma işlemlerinin tarihsel kaydını sunar.
Bu, “implementation slot A’dan B’ye değişti” bilgisinden daha güçlü bir operasyonel denetim izi sağlar çünkü tam olarak hangi fonksiyonların taşındığını, hangilerinin kaldırıldığını ve hangilerinin eklendiğini gösterir.
Diamond Storage Neden Belirleyici Mühendislik Avantajıdır?
Uzun ömürlü yükseltilebilir Solidity sistemlerinde storage disiplini en zor mühendislik problemlerinden biridir.
Proxy tartışmalarının büyük bölümü kod dispatch mekanizmasına gereğinden fazla, storage mimarisine ise gereğinden az odaklanır. Pratikte uzun ömürlü yükseltilebilir sistemlerde en zor konu storage disiplinidir.
UUPS ve Beacon, ERC-1967 / unstructured storage yaklaşımını miras alır. OpenZeppelin’in proxy dokümantasyonu temel fikri açık şekilde anlatır: implementation pointer’ını slot 0’da saklamak yerine proxy, proxy metadata’sının implementation state’iyle çakışmaması için pseudo-random ve standartlaştırılmış slotlar kullanır.
ERC-1967 bu slotları özellikle standartlaştırır çünkü proxy’lerin implementation selector’larıyla çakışabilecek sıradan public method’lar sunmaması ve proxy metadata’sının compiler’ın normal state variable’lar için tahsis etmeyeceği adreslerde tutulması gerekir.
Bu, bir çakışma türünü çözer: proxy-vs-implementation collision.
Ancak gerçek yükseltme programlarında daha tehlikeli olan şu sınıfı çözmez: sürümler arasındaki implementation-vs-implementation collision.
OpenZeppelin, unstructured storage’ın farklı implementation sürümleri arasındaki çakışmalara karşı koruma sağlamadığını açıkça belirtir; geliştiricilerin layout compatibility’yi koruması ve state alanlarını yeniden sıralamak yerine sona eklemesi gerekir.
ERC-1822 de aynı noktayı farklı bir ifadeyle açıklar ve değişkenlerin yükseltmeler arasında yeniden sıralanmaması için ortak bir base contract kullanılmasını önerir.
Diamond’lar bu tartışmayı değiştirir.
ERC-2535 tek bir storage şemasını zorunlu kılmaz; ancak Diamond Storage ve AppStorage yaklaşımlarını Diamond yapıları için geçerli storage layout stratejileri olarak açıkça tanır. Her iki yaklaşımda da storage, inheritance sırasının örtük bir yan etkisi olmaktan çıkar ve açık bir mimari katman haline gelir.
Diamond Storage: Modüler Sistemler İçin Namespaced State
Diamond Storage kullanıldığında, genellikle benzersiz bir hash string’inden hesaplanan deterministic slot’larda tutulan namespaced struct’lar tanımlanır.
Nick Mudge’ın referans açıklamasında namespace string’i fiilen bir storage namespace’i olarak tanımlanır ve struct benzersiz bir storage pozisyonuna sabitlenir.
Bu izolasyon, state’i özellik alanına veya facet ailesine göre doğal biçimde bölümlendirmeyi mümkün kılar.
Namespace’ler benzersiz kaldığı ve struct’lar yalnızca append-only şekilde genişletildiği sürece, modüller arasında yanlışlıkla veri üzerine yazma riski geniş inheritance tabanlı layout’lara kıyasla ciddi ölçüde azalır.
AppStorage: Facet’ler Arasında Ortak Application-Level State
AppStorage farklı bir trade-off sunar.
Çok sayıda namespaced struct yerine, genellikle AppStorage adı verilen uygulama seviyesinde tek bir struct tanımlanır ve bu yapı uygulamaya özel facet’ler arasında ortak state object olarak tutarlı biçimde kullanılır.
Yaygın kullanım şekli şöyledir:
AppStorage internal s;
Mudge, bunun okunabilirliği geliştirdiğini, tekrarlanan storage accessor boilerplate’ini azalttığını ve bazı kullanım senaryolarında tekrarlanan Diamond Storage erişimine kıyasla “bir miktar daha gas efficient” olabildiğini savunur.
Pratik açıdan önemli olan micro-gas iddiası değildir; AppStorage’ın paylaşılan uygulama state’ini facet’ler arasında açık ve tutarlı hale getirmesidir.
ERC-1967 Storage ile Diamond Storage Mimarisi Arasındaki Fark
Dolayısıyla anlamlı karşılaştırma katı bir sınıflandırma açısından “Transparent vs. Diamond storage” değildir.
Asıl karşılaştırma ERC-1967 tarzı unstructured metadata slotları ve append-only implementation layout ile Diamond içinde açıkça namespaced veya application-scoped storage mimarisi arasındadır.
Küçük proxy’ler için ilk yaklaşım yeterlidir. Büyük protokol yüzeylerinde ise ikinci yaklaşımın anlaşılması, refactor edilmesi, denetlenmesi ve yönetilmesi önemli ölçüde daha kolaydır.
Bununla birlikte Diamond yapıları storage kurallarını ortadan kaldırmaz.
Solidity state’i yine deterministic layout kurallarına göre saklar; slot 0’dan başlar, mümkün olduğunda değerleri pack eder ve mapping veya dynamic array lokasyonlarını slot tabanlı hashing üzerinden türetir.
Solidity, storage layout’u açık biçimde dilin external interface’inin bir parçası olarak kabul eder.
Dolayısıyla Diamond Storage ve AppStorage sihirli çözümler değildir; Solidity’nin temel storage semantics’i üzerine kurulmuş disiplinli stratejilerdir.
Canlı bir struct içindeki mevcut namespace’in anlamını değiştirir veya alanları yeniden sıralarsanız yine state corruption’a neden olabilirsiniz.
ERC-2535 Diamond Proxy Hangi Alanlarda UUPS ve Beacon’dan Daha Güçlüdür?
ERC-2535’in avantajları, yükseltilebilir Solidity sistemi boyut, modülerlik, yönetişim karmaşıklığı ve yaşam döngüsü gereksinimleri açısından büyüdükçe daha belirgin hale gelir.
1. Kontrat Boyutu
İlk büyük avantaj kontrat boyutudur.
EIP-170, devreye alınan kod boyutunu 0x6000 byte, yani 24.576 byte ile sınırlar ve runtime kodu bu sınırı aştığında kontrat oluşturma işlemi başarısız olur.
ERC-2535, external functionality’yi çok sayıda facet arasında bölerek ve aynı zamanda tek bir sistem adresini koruyarak bu sınırın aşılması için özel olarak tasarlanmıştır.
Diamond standardı bunu doğrudan ifade eder: Diamond’ların “virtually no size limit” özelliği vardır ve temel motivasyonlarından biri, tek bir kontrat yüzeyi olarak sunulması gereken ilişkili functionality için 24 KB sınırını aşmaktır.
UUPS ve Beacon bu problemi çözmez; her implementation hâlâ aynı kod boyutu sınırına tabi sıradan bir kontrattır.
2. Modülerlik ve Kod Organizasyonu
İkinci avantaj modülerlik ve kod organizasyonudur.
ERC-2535, facet’leri state, internal function’lar ve library’leri paylaşabilen ayrı ve bağımsız kontratlar olarak ele alır.
Standart ayrıca external library kontratlarının facet olarak kullanılabileceğini ve internal library kodunun facet’ler arasında paylaşılabileceğini belirtir.
Bu, inheritance ağacının zaman içinde yeni domain’leri sürekli içine almak zorunda kaldığı tek bir upgradeable implementation kontratına kıyasla çok daha sürdürülebilir bir ayrıştırma modelidir.
Protokolünüz staking, governance, fee logic, account management, settlement logic, admin tooling, migration ve diagnostics gibi alanlara sahipse, bu alanların her biri tek bir dev implementation dosyasında birleşmek yerine ayrı facet’lerde konumlandırılabilir.
3. Fine-Grained Yükseltme Esnekliği
Üçüncü avantaj yükseltme esnekliğidir.
UUPS ve Beacon bir implementation adresini değiştirir. Gerçek kod değişikliği küçük olsa bile bu coarse-grained bir işlemdir.
Diamond yükseltmeleri yalnızca değiştirilmesi gereken selector’ları ekleyebilir, değiştirebilir veya kaldırabilir.
ERC-2535 bunları fine-grained upgrades olarak tanımlar ve Diamond’ın bazı bölümlerinin değiştirilirken diğer bölümlerinin olduğu gibi bırakılabileceğini açıkça belirtir.
Bu, gerçek protokol bakımının nasıl gerçekleştiğine daha yakındır.
Tek bir alt sistemi değiştirdiğiniz için tüm implementation’ı yeniden deploy etmek ve yeniden yetkilendirmek her zaman istemeyeceğiniz bir işlemdir.
4. Granüler Erişim Kontrolü
Dördüncü avantaj granüler erişim kontrolüdür.
Diamond standardı ownership ve authentication konularını kasıtlı olarak kapsam dışında bırakır; ancak bu bir eksiklik değil, avantajdır.
ERC-2535, Diamond authentication modelinin basit veya karmaşık, fine-grained veya coarse olabileceğini açıkça belirtir ve farklı aktörlerin ya da bir DAO’nun yalnızca belirli fonksiyonları ekleme, değiştirme veya kaldırma yetkisine sahip olabileceği örnekler dahi verir.
Başka bir ifadeyle standart tek bir governance modelini hard-code etmez; protokolün modül sınırlarıyla uyumlu bir governance modeline izin verir.
Bu durum, per-facet veya per-function yükseltme yetkilerini mimari açıdan doğal hale getirir. Whole-implementation UUPS yükseltmelerinde bu aynı ölçüde doğal değildir.
UUPS genellikle yükseltme yetkilendirmesini _authorizeUpgrade arkasında toplar; Beacon ise ortak implementation kontrolünü çoğunlukla beacon owner üzerinde merkezileştirir.
5. Sistem Seviyesinde Gas Efficiency
Beşinci avantaj sistem seviyesinde gas efficiency’dir, ancak burada dilin hassas kullanılması gerekir.
Tek ve basit bir call path için UUPS genellikle en yalın general-purpose upgradeable proxy’dir.
OpenZeppelin, UUPS’ı açık biçimde lightweight olarak tanımlar ve transparent-style proxy’lerin upgrade logic proxy’nin içinde bulunduğu için deployment açısından daha maliyetli olduğunu belirtir.
Beacon ise başka bir katman daha ekler çünkü proxy, implementation’ı beacon üzerinden çözümlemek zorundadır.
OpenZeppelin, daha yeni implementation’ların gereksiz storage read’lerini azaltmak amacıyla beacon adresini immutable olarak saklaması sayesinde bazı overhead’leri azaltmasına rağmen, her çağrının implementation’ı beacon’dan aldığını belgeler.
Diamond’lar farklıdır.
Dispatch path selector lookup ve delegatecall içerdiği için basit bir uygulamada otomatik olarak en ucuz proxy değildir.
Ancak ERC-2535’in kendi gas yaklaşımı daha geniş ve gerçeğe daha yakındır: Diamond yapıları çoklu kontrat akışlarını tek bir adres altında birleştirerek, facet’ler arasında doğrudan shared storage erişimine olanak tanıyarak ve tüm akışları generic abstraction’lardan geçirmek yerine belirli kullanım alanları için özel gas-optimized fonksiyonlar eklenmesini sağlayarak mimari seviyede gas tüketimini azaltabilir.
Standart, birden fazla kontratın tek bir Diamond altında birleştirilmesini ve batch operations gibi gas-optimized fonksiyonların uygulanmasını açıkça örnek gösterir.
Sistem karmaşıklığı arttıkça bu avantaj da büyüyebilir.
Tooling tarafında da gas ile ilgili bir nüans vardır.
Nick Mudge’ın referans implementation’ları farklı internal data structure’ların farklı gas profilleri ürettiğini gösterir.
diamond-3 ailesinde loupe fonksiyonları zincir üstünde çağrılabilmeleri için özellikle optimize edilmiştir; daha önceki varyantlar ise daha pahalı loupe read’leri pahasına daha ucuz diamondCut işlemlerine öncelik vermiştir.
Bu, mimarlar açısından önemli bir noktayı gösterir: Diamond tek ve katı bir implementation değildir; farklı internal trade-off profillerine izin veren standartlaştırılmış bir interface’tir.
Sistemin yapısını operasyonel önceliklerinize göre optimize edebilirsiniz.
6. Introspection ve Şeffaflık
Altıncı avantaj introspection ve şeffaflıktır.
ERC-1967, tooling’in implementation, admin veya beacon adresleri gibi proxy slotlarını okuyabilmesini sağlar ve bu son derece kullanışlıdır.
Ancak bu slotlar büyük ve modüler bir sistemin canlı fonksiyon seviyesi topolojisini göstermez.
Diamond’lar gösterir.
Loupe fonksiyonları mevcut facet kompozisyonunu sunar ve DiamondCut event’leri kontrat yüzeyindeki tüm değişiklik geçmişini korur.
Governance yoğun, denetim yoğun veya uzun vadeli decentralization yol haritasına sahip sistemler için bu kozmetik değil, ciddi bir operasyonel avantajdır.
ERC-2535 Diamond Proxy’nin Dikkate Alınması Gereken Trade-Off’ları
ERC-2535 Diamond mimarisi vanilla UUPS proxy’ye göre daha fazla karmaşıklık getirir ve bu karmaşıklığın bilinçli şekilde yönetilmesi gerekir.
Selector bookkeeping, facet composition, storage discipline, ABI management, upgrade orchestration ve governance hataları açısından daha geniş bir yüzey söz konusudur.
ERC-2535, diamondCut işleminin delegatecall aracılığıyla Diamond’ın storage’ına erişebilen arbitrary execution’a izin verdiği konusunda açıkça uyarır; bu nedenle erişimin dikkatle sınırlandırılması gerekir.
Standart ayrıca yanlış kullanımın Diamond’ı veya bir facet’i silebilmesi nedeniyle facet’lerin içinde selfdestruct kullanılmasını önermez.
Selector Yönetimi Hâlâ Disiplin Gerektirir
Ayrıca disiplinli selector yönetimine ihtiyaç vardır.
Solidity function selector’ları yalnızca dört byte’tır ve selector clash ABI genelinde gerçek bir olgudur.
ERC-1967, proxy’lerin implementation selector’larıyla çakışabilecek sıradan public method’lar sunmaması gerektiğini tam da bu nedenle vurgular.
Diamond yapıları bu problemi tipik proxy’lerden daha iyi yönetir çünkü doğru bir diamondCut implementation’ı, zaten var olan selector’ların yeniden eklenmesini reddeder. Ancak riskin kontrol altında kalması, Diamond’ın cut logic’inin doğru uygulanmasına ve titizlikle incelenmesine bağlıdır.
Diamond Her Zaman Doğru Seçim Değildir
Aynı derecede önemli bir başka nokta da Diamond’ın her zaman doğru seçenek olmamasıdır.
Bütünlüklü bir domain modeline ve basit governance yapısına sahip kompakt bir kontratınız varsa, UUPS operasyonel açıdan daha basit ve ekonomik açıdan daha hafif olduğu için mükemmel bir seçenek olmaya devam eder.
Birlikte aynı implementation’a yükseltilmesi gereken çok sayıda homojen instance üreten bir factory çalıştırıyorsanız, Beacon genellikle doğru operasyonel abstraction’dır.
Diamond argümanı “Diamond her benchmark’ta kazanır” değildir.
Doğru argüman daha dar ve daha güçlüdür:
Büyük, gelişen ve heterojen kontrat sistemlerinde Diamond, Ethereum standart ekosisteminde mevcut en güçlü uzun vadeli yükseltme mimarisini sağlar.
Vinu Digital Yükseltilebilir Solidity Mimarisine Nasıl Yaklaşıyor?
Vinu Digital olarak ERC-2535 Diamond Proxy’yi her yükseltilebilirlik probleminde varsayılan cevap olarak değerlendirmiyoruz.
Yaklaşımımız sistemin kendi yaşam döngüsü ve mimarisiyle başlar.
Bir kontrat kompakt ise, domain modeli bütünlüklüyse ve yükseltme gereksinimleri basitse, operasyonel sadeliği nedeniyle UUPS daha uygun seçenek olabilir.
Mimari, aynı implementation’a birlikte geçmesi gereken çok sayıda homojen instance’dan oluşuyorsa Beacon Proxy daha uygun bir operasyonel model sağlayabilir.
ERC-2535 Diamond Proxy’yi, mimarinin temelde farklı bir yapıya ihtiyaç duyduğu durumlarda kullanıyoruz: sabit bir adresi korurken birden fazla fonksiyonel domain boyunca genişlemesi ve sistemin farklı parçalarının birbirinden bağımsız olarak gelişebilmesi beklenen uzun ömürlü kontrat yüzeylerinde.
Bu sistemlerde karar, bu yazı boyunca ele aldığımız aynı mimari gereksinimlere dayanır:
- Tüm implementation’ı değiştirmek yerine selector seviyesinde yükseltmeler
- Facet’ler üzerinden organize edilen modüler functionality
- Açık Diamond Storage veya AppStorage stratejileri
- Diamond Loupe üzerinden fonksiyon seviyesinde introspection
DiamondCutevent’leri aracılığıyla tarihsel görünürlük- Tek bir implementation kontratının kod boyutu sınırını aşan sistemler için destek
- Governance daha sonra yükseltmeleri devre dışı bırakmayı seçerse eventual immutability’ye geçiş yolu
Bu nedenle Diamond tercihimiz proxy minimalizmine veya tek bir gas benchmark’ına dayanmaz.
Mimarinin, sistem büyüdükçe ne kadar anlaşılır, sürdürülebilir, yönetilebilir ve güvenli biçimde geliştirilebilir kaldığına dayanır.
ERC-2535 Diamond Proxy Hakkında Sık Sorulan Sorular
ERC-2535 Diamond Proxy Nedir?
ERC-2535 Diamond Proxy, ayrı function selector’ları facet adı verilen farklı kontratlara yönlendiren modüler ve yükseltilebilir bir akıllı kontrat mimarisidir.
Tüm functionality’yi tek bir implementation kontratına delegate etmek yerine Diamond, farklı fonksiyonları farklı facet’lere yönlendirebilir ve bunu yaparken tek bir external contract adresini ve ortak storage context’ini korur.
ERC-2535 ile UUPS Arasındaki Fark Nedir?
ERC-2535 Diamond Proxy ile UUPS arasındaki temel fark, yükseltmenin granularity seviyesidir.
UUPS genellikle tüm implementation kontratını değiştirirken ERC-2535, farklı facet’ler altında gruplanmış ayrı function selector’ları ekleyebilir, değiştirebilir veya kaldırabilir.
Bu nedenle kompakt sistemlerde UUPS daha basit olabilir. Büyük ve heterojen sistemlerde ise Diamond’ın daha granüler yükseltme modeli daha fazla mimari esneklik sunabilir.
UUPS Yerine Ne Zaman Diamond Proxy Kullanılmalıdır?
Diamond Proxy, Solidity sisteminin büyük, modüler, uzun ömürlü ve fonksiyonel açıdan heterojen hale gelmesinin beklendiği durumlarda en uygun seçenektir.
Uygulamanın kompakt bir logic surface’i ve görece basit upgrade gereksinimleri varsa UUPS daha iyi seçenek olabilir. Farklı alt sistemlerin tüm implementation yüzeyi değiştirilmeden bağımsız biçimde gelişmesi gerektiğinde Diamond daha değerli hale gelir.
Diamond Storage ile AppStorage Arasındaki Fark Nedir?
Diamond Storage, state’i genellikle deterministic storage slot’larında tutulan namespaced struct’lara ayırır ve storage’ın feature veya module bazında izole edilmesine olanak tanır.
AppStorage ise application-specific facet’ler arasında tutarlı biçimde erişilen ortak application-level struct kullanır.
Her iki yaklaşım da storage mimarisini açık hale getirir ancak modüler izolasyon ve paylaşılan application-level state arasında farklı trade-off’lar sunar.
ERC-2535 Solidity’nin Kontrat Boyutu Sınırını Ortadan Kaldırır mı?
ERC-2535, Ethereum’un temel kontrat boyutu kurallarını değiştirmez.
Bunun yerine sistemin functionality’sinin birden fazla facet kontratına dağıtılmasına ve bu fonksiyonların tek bir Diamond adresi üzerinden sunulmasına olanak tanır.
Bu yapı, Diamond mimarisinin tek bir implementation kontratına sığabilecek olandan çok daha büyük birleşik bir functionality yüzeyini desteklemesini sağlar.
ERC-2535 Diamond, UUPS’tan Daha Gas Efficient mıdır?
Otomatik olarak değil.
Basit bir call path için UUPS genel olarak daha yalın bir general-purpose upgradeable proxy’dir. Diamond dispatch, selector lookup ve delegatecall ekler.
Diamond’ın potansiyel avantajı sistem mimarisi seviyesinde ortaya çıkar; burada birden fazla kontrat interaction’ı birleştirilebilir, state facet’ler arasında doğrudan paylaşılabilir ve belirli workflow’lar için özel fonksiyonlar eklenebilir.
Diamond Proxy Her Zaman En İyi Yükseltilebilirlik Pattern’i midir?
Hayır.
UUPS, bütünlüklü logic ve basit governance yapısına sahip kompakt sistemler için güçlü bir seçenek olmaya devam eder. Beacon Proxy ise birlikte yükseltilmesi gereken homojen instance filolarında özellikle kullanışlıdır.
ERC-2535 hakkındaki argümanımız spesifiktir: Diamond, fine-grained yükseltmelerin ve uzun vadeli modülerliğin gerçek mimari gereksinimler olduğu büyük, gelişen ve heterojen kontrat sistemleri için en uygun çözümdür.
Uzun Ömürlü Solidity Sistemlerinde Neden ERC-2535 Diamond Kullanıyoruz?
Vinu Digital olarak uyguladığımız kural budur.
Yükseltilebilirliğin gerçek bir yaşam döngüsü gereksinimi olduğu ve sistem yüzeyinin zaman içinde büyümesinin beklendiği durumlarda Diamond kullanıyoruz.
Bunun nedeni Diamond’ın bize selector seviyesinde yükseltmeler, modüler facet’ler, ölçek büyüdükçe anlaşılır kalabilen storage mimarileri, standart introspection, değişikliklerin daha iyi tarihsel kaydı ve governance daha sonra sistemi kilitlemeyi seçerse iteratif development’tan eventual immutability’ye geçiş için temiz bir yol sunmasıdır.
ERC-2535 tam olarak bu yaşam döngüsü için tasarlanmıştır ve production-grade Solidity mimarisinde bu, minimalizmin kendi başına sunduğu değerden daha önemlidir.
Karmaşık ve Yükseltilebilir Bir Solidity Sistemi mi Geliştiriyorsunuz?
ERC-2535 Diamond Proxy, UUPS, Beacon veya başka bir akıllı kontrat mimarisi arasında yapılacak seçim yalnızca proxy pattern’ine değil; sistemin yaşam döngüsüne, modülerliğine, governance modeline ve operasyonel gereksinimlerine dayanmalıdır.
Vinu Digital olarak modüler Solidity sistemlerinden karmaşık Web3 altyapılarına kadar blok zinciri ve akıllı kontrat mimarilerini bu gereksinimler doğrultusunda tasarlıyor ve geliştiriyoruz.
Yükseltilebilir bir Solidity sistemi tasarlıyor veya mevcut sisteminizi genişletiyorsanız, projenizin arkasındaki mimariyi değerlendirmek için Vinu Digital ile iletişime geçin.





