Back to Blog

HKDAP Stablecoin Güvenlik İncelemesi: Canlı, Lisanslı, Hazır Değil

Phalcon Security
August 14, 2026
23 min read
Key Insights
  • HKDAP'ın KYC iptali ölü koddur ve KYC kanıtı hiçbir zaman zincir üzerinde doğrulanmaz

  • Tek bir anahtar; basım, yakma, duraklatma veya dondurma işlemlerini gerçekleştirebilir; iki anahtar tüm yükseltmeleri ve rolleri kontrol eder

  • Birkaç zincir üzeri özellik, HKMA stablecoin ihraççı kılavuzundan sapma göstermektedir

A BlockSec güvenlik ve uyum incelemesi: HKDAP (Anchorpoint), 13 Ağustos 2026 itibarıyla.

TL;DR. Hong Kong'da ihraç edilen ilk düzenlenmiş stablecoin olan ve Ethereum ana ağında canlı çalışan HKDAP'ın dağıtılmış sözleşmesini inceledik ve üretime hazır değil. KYC ve iptal kontrolleri yazıldığı gibi çalışmıyor; yönetimi, tek bir anahtarın mint, burn veya freeze yapabileceği kadar yoğunlaşmış durumda ve zincir üstü özelliklerinin birçoğu HKMA'nın kendi kılavuzuyla çelişiyor. Altında yatan ortak bir izlek var: sözleşme, ekosistemin hâlihazırda sağladığı ve ölçekte denetlediği ilkel yapıları sıfırdan yeniden icat ediyor (bir multisig, erişim kontrol katmanı, bir timelock, ERC-20'nin kendisi) ve kusurların çoğu standart bileşenleri yeniden kullanan kısımlarda değil, bu özel mekanizmada yaşıyor. "Beta Access" etiketi bu açığı kapatmıyor.

12 Ağustos 2026'da Anchorpoint, bir Hong Kong doları stablecoin'i olan HKDAP'ın ilk aşamasını başlattı. Bu önemli bir lansman. Standard Chartered Bank (Hong Kong) liderliğinde HKT ve Animoca Brands ile kurulan bir ortak girişim olan Anchorpoint, 36 başvuru arasından HKMA'nın verdiği yalnızca iki stablecoin ihraççısı lisansından birine sahip ve HKDAP, Hong Kong'un Stablecoins Yönetmeliği kapsamında ihraç edilen ilk stablecoin'ler arasında.

Düzenlenmiş bir bankanın çoğu ürününden farklı olarak HKDAP doğrudan incelenebilir. Ethereum ana ağında çalışıyor ve sözleşme kaynak kodu Etherscan'de doğrulanmış durumda. Bu yararlı bir özellik: bu şekilde ihraç edilen bir stablecoin için ihraç, transfer ve dondurmayı yöneten kurallar bir belgede anlatılmaz; herkesin okuyabildiği ve yazıldığı gibi yürütülen kodda uygulanır. Lisans bir iddiadır; dağıtılan sözleşme bu iddianın uygulamasıdır ve herkese açıktır.

Bu, somut bir incelemeyi mümkün kılıyor ve biz de bunu yaptık. Dağıtılmış sözleşmeyi iki eksende inceledik. Birincisi, yazılım olarak: doğru ve üretim sınıfı mı? İkincisi, düzenlenmiş bir stablecoin olarak: zincir üstü davranışı HKMA'nın Lisanslı Stablecoin İhraççılarının Denetimine İlişkin Kılavuzu ile örtüşüyor mu?

Bulgular her iki eksende de tutarlı. Sözleşme, yazıldığı gibi çalışmayan uyum kontrolleri de dahil olmak üzere birden çok işlevsel kusur içeriyor. Yönetimi oldukça yoğunlaşmış durumda ve birkaç yüksek riskli işlem tek bir anahtarla yürütülebiliyor. Ayrıca, zincir üstü özelliklerinden bir kısmı HKMA kılavuzunun belirli maddeleriyle çelişiyor. Değerlendirmemiz, bir beta sürümü olarak bile sözleşmenin ticari bir stablecoin'in gerektirdiği kalite çıtasını karşılamadığı yönünde.

Bu yazının geri kalanı, 13 Ağustos 2026 itibarıyla güncel olan bu incelemeyi sunuyor. İncelememiz herkese açık olarak dağıtılmış koda ve gözlemlenebilir zincir üstü gerçeklere dayanıyor. Blok zincirinin belirleyemeyeceği konularda, örneğin rezerv karşılığı veya zincir dışı anahtar saklama hakkında herhangi bir iddiada bulunmuyoruz.

Sözleşmeyi nasıl bulduk

Bir token listesinden değil, ihraççıdan başladık. Anchorpoint'in şirket varlığı, anchorpoint.hk adresindeki sitesine bağlanıyor. Beta Access sayfası dağıtımı adlandırıyor: Ethereum ana ağı, proxy 0x87622385F960fcCB3121d6D0A9513bd1D9Bed6cA; kaynak kodu Etherscan'de doğrulanmış.

Buradan tüm sistemi zincir üstünde haritalandırdık: token proxy'si ve uygulaması (ControllableAHKD, 0xe42d38b05d7ff702193ac5ccedb411b7298ffbfc), onu yöneten yönetim sözleşmesi (0x47dd47a776902bee03abdd5aeff43f41b0ffbc2b), üst düzey rol kayıt defteri (0xa7287701f7ab8f38ef57cdb2a2a69a40128ec89c) ve her biri kendi yönetim sözleşmesine sahip beş uyum modülü. Aşağıdaki her ilişki, yalnızca kaynak koddan çıkarım yapılarak değil, ana ağda depolama slotları okunarak ve view fonksiyonları çağrılarak doğrulandı.

Sözleşme neye benziyor

HKDAP'ın üç katmanı: bir yönetişim kontrol düzlemi token'ı yönetir ve token her transferde beş uyum modülünü sorgular
HKDAP'ın üç katmanı: bir yönetişim kontrol düzlemi token'ı yönetir ve token her transferde beş uyum modülünü sorgular

HKDAP token'ı, OpenZeppelin'in standart ERC-20 referans uygulamasını kullanmıyor; ERC-20 mantığı sıfırdan yazılmış (aşağıdaki hataların bir kısmı buradan geliyor). Sistemin üç katmanı var:

  • Token. Yükseltilebilir bir proxy arkasındaki ControllableAHKD. Mint, burn, pause ve zorla imha işlevlerine sahip, ayrıca her transferde uyum kontrolleri yapılan kontrollü bir ERC-20.
  • Özel yapım bir M-of-N yönetim motoru. Her ayrıcalıklı işlem (yükseltme, mint, burn, pause, blacklist, freeze, uyum modülü değiştirme) düz bir multisig yerine bir request, approve, execute töreninden geçer.
  • Beş uyum modülü. Blacklist, dondurma, bir KYC aktivasyon hizmeti ve depozito ile itfa beyaz listeleri. Her modül, kendi kontrol-otoritesi sözleşmesi tarafından yönetilen bir proxydir.

Yapısal olarak, aynı "kontrol otoritesi artı proxy artı uygulama" birimi altı kez tekrarlanıyor (token artı beş modül) ve altı kontrol otoritesinin tamamı rollerini tek bir kayıt defterinde çözümlüyor. Sistemdeki tüm kontrol nihayetinde bu tek kayıt defterinde toplanıyor ve içindeki rolleri kimin yeniden yazabileceği, aşağıda ayrıntılı olarak gösterdiğimiz gibi, çok küçük bir imzacı anahtar kümesine indirgeniyor.

Bölüm 1: Güvenlik ve hatalar

Bu bölümdeki bulgular aşağıda özetlenmiştir; her satır belirtilen bölümde ayrıntılandırılmıştır.

Alan Bulgu Nerede Etki
1.1 KYC ve iptal kontrolleri başarısız oluyor KYC iptali ölü kod TokenHolderActivationServerLibrary.sol:221-235 isActive, sağlayıcı kaydının kaldırılmasını yok sayar (döngü asla çalışmaz ve = yerine == kullanır); fail-open.
Doğrulayıcı kaydının kaldırılması asla INACTIVE ayarlamaz TokenHolderActivationServer.sol:504-511 "Kaydı kaldırılmış" bir doğrulayıcı yine de cüzdanları dahil edip devre dışı bırakabilir; ikinci çağrı revert olur.
KYC kanıtı zincir üstünde asla doğrulanmaz TokenHolderActivationServer.sol:575-578 Kanıt iletilir ancak atılır; boş dize dahil herhangi bir kanıt kabul edilir.
Ücretsiz transfer muafiyeti parçalara bölünerek aşılabilir ControllableAHKD.sol:337-535 freeTransferLimit kümülatif olarak değil, çağrı başına kontrol edilir; KYC'siz etkinlik için bir sınır olarak kullanılırsa, transferleri alt sınıra bölerek bypass edilebilir.
1.2 Yönetim aşırı yoğunlaşmış Yüksek riskli işlemler tek imzalı authorizationMatrix; mint tx 0xa7e53c…b33d7 mint / burn / freeze / KYC-deactivate (rol C), pause / destroy (rol D), blacklist / unfreeze (rol F) her biri tek anahtarla yürütülür.
Bir anahtar çifti (A + B) her şeyi yükseltir authorizationMatrix Token ve beş modülün tamamı için upgradeTo, rol A + B gerektirir; iki kişi herhangi bir uygulamayı değiştirebilir.
Aynı çift her rolü yeniden yazar kayıt defteri 0xa728… authorizationMatrix Kayıt defterindeki grantRole / revokeRole da rol A + B gerektirir (ADMIN_ROLE yalnızca sözleşmede tutulur; DEFAULT_ADMIN_ROLE = address(0)); hiçbir dış anahtar rolleri doğrudan değiştiremez.
Bir adres altı rol tutuyor rol kayıt defteri 0xa728… 0x2f7f00…, rol C'nin yanı sıra ADMIN_TOKEN_HOLDER ve dört denetçi rolünün tamamını tutar; yürütme ve denetim çakışır.
İptal anında gerçekleşmez; timelock yok HybridControlEngine.sol:158-227 Sayılmış bir imza, bir rol iptal edildikten sonra yeniden doğrulanmaz; yürütme, son imzayla atomiktir ve gecikmesizdir.
Motorun denetim izi güvenilmez HybridControlEngine.sol:36-129, 177-196 evtApprove, imzacı olarak address(0) yayar; etkin-istek listesi nonce 0'ı hem gerçek bir kimlik hem de boş işaretçi olarak kullanır, bu nedenle geriye doğru gezinme ilk isteği kaçırır.
1.3 Tutarsız transfer kontrolleri transfer ve transferFrom farklı kurallar uygular ControllableAHKD.sol:313-502 Beyaz liste erken dönüşü KYC'yi yalnızca transferFrom ile atlar; checkingMode farklı tarafları kontrol eder; aynı transfer farklı kurallara tabidir.
1.4 Üretim öncesi yapıya işaretler hata ayıklama günlükleri, yanlış yorum, ad/karma uyuşmazlığı, testlerin yüklenmesi UpgradeableProxy.sol:115-119; ControllableAHKD.sol:25 Proxy fallback'inde console.log (kalıcı gas); proxy yorumu kodla çelişiyor; rol adı/karma uyuşmazlığı; testler dahil 117 dosya yüklenmiş; optimizer runs = 0.
1.5 Tek yükseltme kusurları yerinde bıraktı tek yükseltmenin izini sürme tx 0x742372…85136, 0xa7a400…630c Dağıtım 28 Nis → yükseltme 10 Tem; A + B töreninin iki işlemi bir blok aralıklaydı (~12sn); Bölüm 1'deki her kusur kurulu uygulamada mevcut.

1.1 KYC ve iptal kontrolleri yazıldığı gibi çalışmıyor

Düzenlemeye göre, HKDAP'ın hizmet verdiği B-tarafı (kurumsal) kullanıcıların KYC'den geçmesi gerekiyor. Sözleşmede bu, en az iki şey yapması anlamına gelir: KYC'den geçmemiş bir cüzdanın engellenmesi için transferlerde KYC'yi zorunlu kılmak ve bir kimlik sağlayıcısı veya bir kullanıcı kaldırıldığında erişimi iptal etmek. HKDAP'ta bu yol üç bağımsız noktada bozuk.

KYC iptali ölü kod. Token, transferleri KYC modülünde isActive(address) çağrısıyla kapılandırır. isActive iki şey yapmalıdır: önce, cüzdan başına sayaçtan bir taban değer belirler; cüzdan, KYC ile devre dışı bırakıldığından daha fazla kez KYC ile etkinleştirilmişse etkindir; ardından, cüzdan için kefil olan herhangi bir kimlik sağlayıcısı o zamandan beri kayıttan kaldırılmışsa bu değeri false'a daraltır. İkisi iki tür iptali kapsar: bir kullanıcının KYC'sini iptal etmek (sayaç) ve bütün bir sağlayıcıyı iptal ederek onun eklediği her cüzdanı da birlikte düşürmek (döngü). Yalnızca ilki gerçekleşir.

// contracts/hce/erc20/libs/TokenHolderActivationServerLibrary.sol
221    active = ( tokenHolderRegistration[_address].deactivationCount < tokenHolderRegistration[_address].activationCount ) ;
223    uint256 entryCount = 0 ;
224    uint256 index = chainedItemList.firstEntry ;        // 0 if such ChainedList is empty
226    while ( entryCount > chainedItemList.entryCount && active ) {
227        ChainedListLibrary.ChainedItem storage chainedItem = identityProvidersByStatuss[index] ; // deregistered provider
230        // NDLR: .... not too sure about that one to be frank
231        active == ( tokenHolderKYCProofDirectoryByProvider[_address][identityProviders[chainedItem.objectId].identifier] == 0 ) ;
233        entryCount++ ;
234        index = chainedItem.pointNext ;
235    }

Satır 221 gerçek bir atamadır (=) ve etkili olan tek atama budur: active, deactivationCount < activationCount değerine dönüşür. Döngü (satır 226-235) bu değeri daraltması gereken yerdir, ancak iki kez başarısız olur. Satır 226'daki koşulu entryCount > chainedItemList.entryCount, 0 > N olduğundan gövde asla çalışmaz; ve çalışsaydı bile, satır 231 sonucu atılan bir karşılaştırma olan == kullanır, oysa = ile atama yapmalıdır. isActive bu nedenle yalnızca sayaç karşılaştırmasını döndürür ve sağlayıcı iptalini tamamen yok sayar. Bu fail-open'dur: ele geçirilmiş bir KYC sağlayıcısının kaydını kaldırmak, onun eklediği cüzdanların işlem yapmasını engellemez. Ayrıca unregisterVerifier bu sayaçlara dokunmadığı için, kaydı kaldırılmış bir sağlayıcının cüzdanları pozitif sayıyı korur ve etkin kalır.

Sağlayıcı iptali diğer tarafta da bozuk. unregisterVerifier yalnızca bağlı listedeki bir düğümü taşır; sağlayıcının dizin durumunu asla INACTIVE yapmaz:

// contracts/hce/erc20/modules/TokenHolderActivationServer.sol
504    function _unregisterVerifier(string calldata _verifierId) internal {
505        _removeToList(_verifierId, ACTIVE_IDENTIY_PROVIDER, "60a");
507        uint256 _ipIdx       = identityProviders.length - 1;
508        uint256 _newIdx      = identityProvidersByStatuss.length + 1;
510        _addToList(_ipIdx, _newIdx, INACTIVE_IDENTIY_PROVIDER, _verifierId, "60b");
511    }

Durum ACTIVE kaldığı için, "kaydı kaldırılmış" bir doğrulayıcı yine de kullanıcıları kaydedip devre dışı bırakabilir; bir sağlayıcıyı yeniden etkinleştirmeyi amaçlayan dal erişilemezdir ve ikinci bir unregisterVerifier çağrısı underflow olup revert eder.

KYC kanıtı zincir üstünde asla doğrulanmaz. Yetkili bir doğrulayıcı, registerOrRenew aracılığıyla bir cüzdanı kaydettiğinde veya yenilediğinde (yalnızca o anda etkin bir doğrulayıcının çağırabilmesi için kapılandırılmıştır), akış _checkKYCProofa ulaşır; bu fonksiyon, sunulan kanıtı sağlayıcının şemasına göre doğrulamalıdır. Arayüze göre bu kanıt, "bir Oracle için URI veya doğrulanabilir bir kaynaktan imzalı bir hash"tir. Fonksiyon onu yok sayar:

// contracts/hce/erc20/modules/TokenHolderActivationServer.sol
575    function _checkKYCProof( string memory _ipIdentifier, string memory, string memory _rcCode ) internal view returns ( bool isVerified ) {
576        require( identityProviderDirectory[_ipIdentifier].status == ACTIVE_IDENTIY_PROVIDER, string.concat(ERROR_404, _rcCode, "41b")) ;
577        return true ;
578    }

Kanıt bu fonksiyona ulaşır. registerOrRenew, gönderilen kycProofu _registerOrRenew üzerinden taşır ve ikinci argüman olarak iletir. Ancak satır 575'te bu argüman hiç adı olmayan bir parametreye düşer; fonksiyonun üzerindeki doc yorumu da bunu atlar ve gövde onu asla okumaz. Fonksiyon yalnızca sağlayıcının etkin olduğunu doğrular ve satır 577'de true döndürür; böylece kanıt kontrol edilmek yerine atılır. Bu bir dışarıdan bypass değildir, çünkü oraya yalnızca etkin bir doğrulayıcı ulaşabilir; ancak zincir üstünde sözleşme KYC kanıtı üzerinde hiçbir doğrulama yapmaz, bu nedenle bütünlüğü tamamen zincir dışı doğrulayıcıya dayanır. Ele geçirilmiş veya dikkatsiz bir doğrulayıcı, boş dize dahil herhangi bir kanıtla herhangi bir cüzdanı etkinleştirebilir.

Birlikte ele alındığında bu üçü, temel bir uyum özelliği olan erişimi denetleme ve iptal etme yeteneğinin yazıldığı gibi çalışmadığı anlamına geliyor.

Bu üçünün ötesinde ilişkili bir zayıflık daha var: ücretsiz transfer muafiyeti parçalara bölünerek aşılabilir. Token'ın bir freeTransferLimit değeri var ve bunun altındaki bir transfer isActive (KYC) kontrolünü atlar. Ancak limit yalnızca mevcut transferin tutarıyla karşılaştırılır; sözleşme adres veya dönem başına kümülatif bir toplam tutmaz. Dolayısıyla limit, KYC'siz etkinlik için bir tavan olarak kullanılıyorsa, bir kullanıcı transferleri her biri limitin hemen altında olacak şekilde tekrar ederek toplamda istediği tutarı taşıyabilir; bu da tavanı etkisiz kılar.

1.2 Yönetim aşırı yoğunlaşmış ve yüksek riskli işlemler tek imzalı

Zincir üstünde her rolü ve her rol sahibini numaralandırdık. Ayrıntılardan önce iki şey öne çıkıyor.

Birincisi, M-of-N törenlerini yetkilendiren rollerin okunabilir adları yok. Dağıtılmış yapılandırmada yalnızca 32 baytlık hash'ler olarak görünüyorlar ve hiçbiri doğrulanmış kaynakta adlandırılmış bir rol sabitiyle eşleşmiyor (SUPPLY_CONTROLLER_ROLE gibi adlandırılmış roller, imzacılar tarafından değil, sözleşmelerin kendisi tarafından tutuluyor). Altı imzacı rolünü A'dan F'ye etiketliyoruz. Sistemdeki en güçlü rollerin opak tanımlayıcılar olması başlı başına bir zayıflıktır: yönetimi, adlandırılmış rollere kıyasla daha zor incelenebilir kılar.

İkincisi, sahip sayısı azdır. Aşağıdaki tablo zincir üstünde rol kayıt defterinden okunmuştur; adresler kısaltılmıştır.

Rol (bizim etiketimiz) Zincir üstü hash Sahip(ler) Yetki verdiği
A 0x37f0f656… 0x747356d525bf47f495af7c6e42f3ab9b8ba87a4b upgradeTo / changeAdmin / setControlAuthority için ilk imza
B 0x95c27f81… 0x8117a657df7a1c399231bfe26a096eb8f8ad5973, 0x5d9d9b28e83382e694916b0feeaf7a9badbb659c, 0xebb73f78e253539acceb4e6cc287095788eee5d4 neredeyse her iki imzalı işlemde ikinci imza
C 0xfa2fe896… 0x2f7f00cc5334fe2861e485ff610f74890a0316ed mintToDeposit, burnFrom, freeze, KYC deactivate (tek)
D 0x3dce3265… 0x5092af62a1625fa57404557d3ad417474f3f494c pause, destroyBlackFunds, depozito ve itfa adreslerini kaydet/kaydını kaldır, registerVerifier (tek)
E 0xfd21a76d… 0xa9315aadc89ba681f1fe5df3375ab1a87d37eca2 uyum modüllerini değiştirme (setBlacklistServer vb.)
F 0x510ac1ff… 0x7daabe5092d3feea5cc19ddbb5380a4eac38f89c addBlackList, unfreeze (tek)

Tablodan birkaç sonuç çıkıyor.

Tek imzacılı yüksek riskli işlemler. Yüksek riskli işlemlerin çoğu, kotası bir olan tek bir rol gerektirir. Aşağıdaki tablo, token'ın yönetim sözleşmesinin ve beş modül yönetim sözleşmesinin authorizationMatrix değerinden zincir üstünde okunmuştur (bir + B ikinci imzası gösterilmedikçe tek imza):

İşlem Tarafından yönetilir Gerekli imzalar
mintToDeposit, burnFrom token C x1
freeze, batchFreeze dondurma modülü C x1
deactivate, adminDeactivate (KYC) KYC modülü C x1
pause, destroyBlackFunds token D x1
register, unregister (depozito / itfa) dizin modülleri D x1
registerVerifier, unregisterVerifier KYC modülü D x1
addBlackList, batchBlackList blacklist modülü F x1
unfreeze dondurma modülü F x1
removeBlackList blacklist modülü F x1 + B x1
setBlacklistServer, setFreezingServer, setCheckingMode token E x1 + B x1
dizin sunucusu ve arz limiti ayarlayıcıları token D x1 + B x1
upgradeTo / changeAdmin / setControlAuthority (token ve her modül), unpause token + modüller A x1 + B x1

İhraç, dondurma ve KYC devre dışı bırakma tek imzalıdır (hepsi rol C altında); pause, destroy, dizin değişiklikleri ve doğrulayıcı kaydı, rol D altında tek imzalıdır; blacklist ve unfreeze, rol F altında tek imzalıdır. Yalnızca yükseltmeler ve yapılandırma değişiklikleri ikinci bir imza gerektirir. Asimetriye dikkat edin: freeze ve addBlackList tek imza gerektirirken removeBlackList iki imza gerektirir; yani bir hesabı kısıtlamak, serbest bırakmaktan daha kolaydır.

Bu yalnızca matrisin okunması değil; canlı bir mint işleminde gözlemlenebilir. Bu yazı hazırlanırken en son ihraç olan tx 0xa7e53c…b33d7, tek rol-C hesabı (0x2f7f00cc5334fe2861e485ff610f74890a0316ed) tarafından token'ın yönetim sözleşmesine gönderilen tek bir işlemdir. request çağrısı yapar ve aynı işlem yeter sayıya ulaşıp address(0)'dan mint Transfer olayını yayar; ayrı bir onay işlemi ve ikinci bir imzacı yoktur. İhraç, talep edenin kendi işlemi içinde kesinleştiği için, tek anahtar mint'i hem talep etmiş hem de yürütmüştür.

Ayrıca motorda hiçbir yerde timelock yoktur. Gereken son imza düştüğü anda işlem aynı işlem içinde yürütülür; incelenebileceği, iptal edilebileceği veya itiraz edilebileceği bir gecikme yoktur. Motor bir executedAt zaman damgası kaydeder ancak asla kontrol etmez. Bu nedenle iki imzalı işlemler bile ikinci anahtar imzaladığı anda anında kesinleşir.

Bir anahtar çifti her şeyi yükseltir. Token'ı yükseltmek ve beş uyum modülünün tamamını yükseltmek aynı gereksinimi kullanır: A artı B. A tek bir hesap ve B aynı rolü paylaşan üç hesap olduğundan, iki kişi sistemdeki herhangi bir uygulamayı değiştirebilir.

Aynı çift rol tablosunu da kontrol eder. Roller yalnızca kayıt defterinde (HybridControlledAuthority, 0xa7287701f7ab8f38ef57cdb2a2a69a40128ec89c) kendi töreni aracılığıyla verilebilir ve iptal edilebilir; hiçbir dış anahtar bunları doğrudan değiştiremez. Zincir üstünde okunan authorizationMatrix de bir rol değişikliği için yükseltmeyle aynı imzaları gerektirir: rol A artı rol B. Dolayısıyla herhangi bir uygulamayı değiştirebilen iki kişi, rol C'ye bir anahtar ekleyebilir, mevcut bir sahibi kaldırabilir ve tüm rol tablosunu yeniden yazabilir. Bu iki imzalı kapı, yukarıdaki tek imzalı işlemlerden daha iyidir, ancak sistemin kökü için hâlâ düşük bir çıtadır; çünkü rol A, artıklığı olmayan tek bir hesaptır.

Bir adres, altı rol. Rol C'nin sahibi (0x2f7f00cc5334fe2861e485ff610f74890a0316ed) ayrıca ADMIN_TOKEN_HOLDER_ROLE (KYC doğrulayıcı yönetimi) rolünü elinde tutar ve dört denetçi rolünün tamamının üyesidir (BLACKLIST_AUDITOR_ROLE, FREEZING_AUDITOR_ROLE, WHITELIST_AUDITOR_ROLE ve AFL_TOKEN_AUDITOR_HOLDER_ROLE). Bu tek anahtarın ele geçirilmesi, ihraç, dondurma ve KYC yönetiminin aynı anda kaybı anlamına gelir.

Denetçi rollerinin kendine özgü iki sorunu var. Birincisi, uyum listelerinin salt okunur getter'larını kapılayarak görünüşte bunları kimin okuyabileceğini kontrol ediyorlar; ancak halka açık bir blok zincirinde bu anlamsızdır: temeldeki depolama herkes tarafından okunabilir (depolama slotlarını okumak bu sistemi haritalandırma şeklimizdi), bu nedenle listeler her iki durumda da halka açıktır ve bu kısıtlama tasarımın halka açık bir zincirde olmayı hesaba katmadığını gösterir. İkincisi, yoğunlaşma: dört denetçi rolünün tamamı aynı 23 hesapta toplanmıştır ve yürütme rolleri A, C, D ve F'nin sahipleri de bunların arasındadır; yani mint, burn, freeze ve blacklist yapan aynı anahtarlar, bu eylemleri incelemesi gereken grupta da yer alır.

İptal anında değildir. Tören motorunda, bir imzacının rolü bir kez kontrol edilir ve kota azaltılır; daha önceki imzacılar asla yeniden doğrulanmaz; bu nedenle sonradan bir rolü iptal etmek, zaten sayılmış bir oyu geri çekmez:

// contracts/hce/HybridControlEngine.sol
158    for ( uint256 i=0; i < approvalRequest.ceremony.length; i++ ) {
159        if ( !_hasBeenMandated && !approvalRequest.ceremony[i].completed &&
160                IControlAuthority(authorityContract).hasRole( approvalRequest.ceremony[i].expectation.authority, _signer ) ) {
161            _hasBeenMandated = true ;
163            approvalRequest.ceremony[i].expectation.quota-- ;
167            approvalRequest.ceremony[i].completed = _approvalIntent && approvalRequest.ceremony[i].expectation.quota == 0 ;
168        }

Son olarak, motorun kendi denetim izi güvenilmez. Her onayda evtApprove olayı, gerçek onaylayan yerine imzacı olarak address(0) yayar; gerçek imzacı yalnızca işlemi gönderen adreste ve dahili bir kayıtta hayatta kalır; bu nedenle olay günlükleri bir isteği kimin onayladığını ilişkilendiremez. Ayrıca etkin-istek listesi nonce 0'ı hem gerçek bir istek kimliği hem de boş işaretçi olarak kullanır; bu nedenle listeyi geriye doğru tarayan izleme veya onay araçları nonce 0'daki isteği kaçırır. Bunların hiçbiri kritik değildir, ancak temiz bir denetim izi gerektiren düzenlenmiş bir sistem için ikisi de ondan eksiltir.

1.3 transfer ve transferFrom arasında transfer kontrolleri tutarsız

İkisi arasındaki farkın bir kısmı beklenendir. transferFrom'da başlatan, msg.sender, fonların kaynağı değil onaylanmış bir harcayıcıdır; bu nedenle kod her modda gerçek kaynağı from'u açıkça kontrol eder. transfer'in buna ihtiyacı yoktur, çünkü orada msg.sender kaynağın kendisidir. Bu uyarlama makuldür. Diğer iki fark, başlatan tarafından açıklanmaz ve aynı ekonomik eylemi farklı kurallara tabi kılar.

Birincisi, depozito ve itfa beyaz listeleri yalnızca transferFrom yolunda kontrol edilir; üyelik, isActive (KYC) kontrolünü atlayan erken bir dönüşü tetikler. transfer onlara asla danışmaz. Bir alıcının beyaz listede olup olmamasının, transferi kimin başlattığıyla hiçbir ilgisi yoktur; bu nedenle aynı alıcı transfer ile KYC'ye tabidir ancak transferFrom ile bunu atlayabilir:

// contracts/hce/ControllableAHKD.sol : transfer(), "Source" mode gates only the sender
323            else if ( activateMode == ActivateMode.Source )
325                _transferCheckSourceMode(_value, "80h");

// contracts/hce/ControllableAHKD.sol : transferFrom() -> _transferFromCheckDestinationMode(_to)
428        try depositDirectoryServer.isRegistered(_to)
429                    returns ( bool isIt, IWhitelistServer.WalletAddress memory ) {
430            if ( isIt ) { return ; }
436        try redemptionDirectoryServer.isRegistered(_to)
437                    returns ( bool isIt, IWhitelistServer.WalletAddress memory ) {
438            if ( isIt ) { return ; }
444        try tokenHolderActivationServer.isActive(_to) returns ( bool isIt ) {
445            require(isIt || _value < freeTransferLimit,     string.concat(ERROR_404, _rcCode, "/86a" ) ) ;

İkincisi, checkingMode iki fonksiyonda farklı anlamlara gelir. transfer'de "Source" modu göndereni kontrol eder; transferFrom'da "Source" modu harcayıcıyı (msg.sender) kontrol ederken, from her modda kontrol edilir. Yani tek bir yapılandırma ayarı, giriş noktasına bağlı olarak iki farklı politika uygular.

Sonuç olarak, düzenlenmiş bir token'ın transfer kontrolleri hangi fonksiyonun kullanıldığına bağlıdır; bu da onları akıl yürütmeyi zorlaştırır ve yapılandırmaya bağlı olarak kaçınılabilir kılar.

1.4 Üretim öncesi yapıya işaretler

Belirli mantık hatalarının ötesinde, kod tabanının birkaç özelliği ana ağa üretim öncesi bir yapının dağıtıldığını gösteriyor.

Üretimde hata ayıklama günlüğü. hardhat/console.log çağrıları her yerde duruyor; her kullanıcı işleminde çalışan proxy fallback'inin içi dahil. Proxy'nin kendisi yükseltilebilir olmadığı için bu ek yük kalıcıdır:

// contracts/proxy/UpgradeableProxy.sol
115    function _beforeFallback() internal virtual override {
116        console.log("iam %s, entering fallback as %s", address(this), msg.sender) ;
117        // require(msg.sender != _getAdmin(), "[UPY]404/02");
118        super._beforeFallback();
119    }

Kodun tersini anlatan bir proxy başlık yorumu. Aynı dosya, OpenZeppelin'in TransparentUpgradeableProxy belgelerini taşıyor; bu belgeler admin'in asla uygulamaya düşemeyeceğini söyler. Bu sözleşme bilinçli olarak tersini yapar: satır 117'deki koruma yorum satırı yapılmıştır ve admin gerçekten de uygulamaya düşer. Yoruma güvenen bir inceleyici, güven sınırını yanlış modeller.

Rol adları karma değerleriyle eşleşmiyor. "Elevated risk" rolü, token ve modüllerde aynı sabit adla ancak farklı bir keccak dizesiyle tanımlanmış; bu da iki farklı rol üretir:

// contracts/hce/ControllableAHKD.sol  (token)    hash = 0xd2b9...
25    bytes32 internal constant ELEVATEDRISK_OWNER_ROLE = keccak256('ELEVATED_RISK_OWNER_ROLE') ;
// contracts/hce/erc20/modules/BlackListServer.sol  (module)    hash = 0x4de4...
18    bytes32 internal constant ELEVATEDRISK_OWNER_ROLE = keccak256('ELEVATEDRISK_OWNER_ROLE') ;

Dağıtım, yalnızca her modül kendi kopyasını tuttuğu için sorundan kaçınır; ikinci bir rol adı (AFL_TOKEN_HOLDER_AUDITOR_ROLE) aynı şekilde yer değiştirmiştir.

Diğer işaretler. Proxy'nin doğrulama paketi, projenin test paketi dahil 117 dosyayı herkese açık gezgine yükledi; bu da okuyucuya dahili testleri ve uç durumları verir. En son yükseltme, döngüde üçüncü taraf denetimi olmadan yalnızca derleyici uyarısı temizliğini değiştirdi. Ayrıca optimizer sıfır çalıştırma olarak ayarlanmış; bu da yoğun kullanılan bir token'ın sık kullanılan kod yollarını daha ucuz değil daha pahalı hale getirir.

Bunların hiçbiri tek başına ciddi değildir. Birlikte, kodun ana ağda değer tutan bir sözleşmeden beklenen yayın disiplininden geçmediğini gösteriyorlar.

1.5 Sözleşmenin tek yükseltmesinin izini sürmek

Proxy bir kez yükseltildi. 28 Nisan 2026'da 0x8ff12fe3bed22d9e40afb4b98ef4dee28d94699e uygulamasıyla dağıtıldı ve 10 Temmuz 2026'da mevcut 0xe42d38b05d7ff702193ac5ccedb411b7298ffbfc sürümüne yükseltildi. Yükseltme zincir üstü bir yönetim eylemi olduğu için, onu tam olarak kimin onayladığını görebiliriz.

upgradeTo, rol A artı rol B gerektirir. Yükseltme, bitişik bloklarda yaklaşık on iki saniye arayla yapılan iki işlemdi:

  • istek, rol A, 0xa9315aadc89ba681f1fe5df3375ab1a87d37eca2 adresinden, 25500519 bloğunda (tx 0x742372…85136);
  • onay, rol B, 0x3795300b31429f9d37b0dc805528d9390ce87c50 adresinden, 25500520 bloğunda (tx 0xa7a400…630c); bu işlem yeter sayıya ulaştı ve yükseltmeyi aynı işlem içinde gerçekleştirdi.

İki şey öne çıkıyor. Birincisi, iki imzalı törenin tamamı tek bir blok aralığında tamamlandı. İstekten yürütmeye kadar bir blok vardı; değişiklik canlıya geçmeden önce ikinci imzacının bağımsız olarak inceleyebileceği bir pencere yoktu.

İkincisi, imzacıların hiçbiri mevcut rol kayıt defterinden tanımlanamıyor. Roller o zamandan beri döndürülmüş: istek sahibi 0xa9315a… artık rol A'yı tutmuyor (bugün rol E'yi tutuyor) ve ikinci imzacı 0x3795300b… şu anda hiçbir role sahip değil. Kayıt defterini olduğu gibi okumak size yükseltmeyi kimin yetkilendirdiğini söylemez; bunu yalnızca işlem geçmişi söyler. Bu, "iptalin anında olmaması" özelliğinin diğer taraftan görünümüdür: roller hareket eder, bu nedenle kimin neye sahip olduğunun anlık görüntüsü, kimin ne yaptığının kaydı değildir.

Ayrıca yükseltme, bu incelemedeki kusurların hiçbirini düzeltmedi. Kurduğu uygulama 0xe42d38b0…, Bölüm 1'in tamamının tanımladığı uygulamadır. Zincirden, yükseltmeden önce üçüncü taraf denetimi yapılıp yapılmadığını söyleyemeyiz; diyebileceğimiz şey, yapıldıysa Bölüm 1'deki kusurların ondan sağ çıktığıdır.

Bölüm 2: Hong Kong'un stablecoin çerçevesiyle uyumlu mu?

Hong Kong'un Stablecoins Yönetmeliği 1 Ağustos 2025'te yürürlüğe girdi ve lisanslı ihraççılar, HKMA'nın Lisanslı Stablecoin İhraççılarının Denetimine İlişkin Kılavuzu uyarınca denetleniyor. Yalnızca bir akıllı sözleşmenin kendi başına karşılayabileceği maddeleri karşılaştırdık; rezerv karşılığı, saklama ve zincir dışı anahtar törenleri zincir üstü bir incelemenin kapsamı dışındadır. Aşağıdaki her madde için kılavuzun ne gerektirdiğini, sözleşmenin ne yaptığını ve ikisinin nerede ayrıştığını belirtiyoruz. Karşılaştırma burada özetlenmiş ve takip eden bölümlerde ayrıntılandırılmıştır.

HKMA maddesi Gerektirdiği Sözleşmenin ayrıştığı nokta Değerlendirme
6.5.3 Yüksek riskli işlemler tek taraflı olmamalı (çoklu imza ve hız limitleri veya timelock gibi azaltıcı önlemler) mint, burn, pause ve freeze işlemlerinin her biri tek anahtarla yürütülür; timelock yoktur (yürütme son imzayla atomiktir) Ayrışıyor
6.5.4 Görevleri yetkili kişiler arasında ayırın; yetkiyi derhal iptal edin bir hesap altı rol tutuyor, bu nedenle yürütme ve denetim çakışıyor; sayılmış bir onay daha sonraki bir iptalden sağ çıkar Ayrışıyor
6.5.5 Her kod değişikliği için üçüncü taraf denetimi; doğru, tutarlı, güvenlik açığı içermeyen Bölüm 1'deki kusurlar dağıtılmış uygulamada canlıdır; isActive ve sağlayıcı iptali adlarının yaptığını yapmıyor Ayrışıyor
Uyum kontrollerinin etkinliği blacklist, freeze, whitelist ve KYC kontrolleri etkili olmalı KYC denetimi ve sağlayıcı iptali dağıtılmış kodda işlevsel değil Ayrışıyor
2.2.3 Dondurulmuş veya imha edilmiş coinler tamamen karşılıklı ve mutabakat edilebilir kalmalı destroy, address(0) yerine address(this)e Transfer yayar ve net ihraç sayaçlarına dokunmaz; olaylardan yeniden oluşturulan arz sapar Endişe

Paragraf 6.5.3: yüksek riskli işlemler tek taraflı olmamalı

Gerektirdiği. Yüksek riskli işlemler, hiçbir tek tarafın bunları tek taraflı olarak gerçekleştiremeyeceği şekilde tasarlanmalıdır; örneğin çoklu imza protokolüyle ve kılavuz, hız limitleri ve zaman gecikmeli (timelock) kontroller gibi ek azaltıcı önlemler sıralar.

Sözleşmenin yaptığı. Yönetim sözleşmesinin authorizationMatrix değerinden okunduğunda (tam matris 1.2'deki tablodadır), arz ve acil durum işlemlerinin her biri, kotası bir olan tek bir rol gerektirir:

İşlem Gerekli imza
mintToDeposit ROLE_C x1
burnFrom ROLE_C x1
freeze ROLE_C x1
pause ROLE_D x1
destroyBlackFunds ROLE_D x1

Ayrıştığı nokta. Mint, burn, pause ve freeze işlemlerinin her biri tek bir anahtarla yürütülebilir. Bu, "hiçbir tek taraf tek taraflı olarak" gereksinimini karşılamaz. Ayrıca bir timelock yoktur: 1.2'de gösterildiği gibi, yeter sayıya ulaşıldığında işlem aynı işlem içinde yürütülür; bu nedenle kılavuzun saydığı azaltıcı önlemlerden biri olan zaman gecikmesi de yoktur. Sözleşme bir arz hız limiti (whenWithinRiskThresholds) uygular, bu nedenle bu azaltıcı önlem mevcuttur; ancak işlemlerin kendisinde çoklu imza kontrolünün yerini tutmaz.

Paragraf 6.5.4: görev ayrılığı ve derhal iptal

Gerektirdiği. Farklı işlemler, farklı yetkili kişiler arasında ayrıştırılmalı ve bir yetkili kişinin yetkisi derhal iptal edilebilmelidir.

Sözleşmenin yaptığı. Bir harici sahipli hesap altı rol tutuyor (ihraç, dondurma, KYC yönetimi ve dört denetçi rolünün tamamı), bu nedenle yürütme ve denetim rolleri çakışıyor. Rol değişiklikleri de yalnızca rol A artı rol B gerektirir (bkz. 1.2); bu nedenle kimin yetkili olduğuna aynı küçük grup karar verir ve bu grup yürütme ve yükseltme yapabilir. Ayrıca, imzacının rolü daha sonra iptal edilirse zaten sayılmış bir imza yeniden doğrulanmaz.

Ayrıştığı nokta. Görevler ayrıştırılmak yerine yoğunlaşmıştır ve iptal anında değildir: iptal edilmiş bir imzacının daha önceki onayı, daha sonraki bir yürütme için hâlâ sayılır.

Paragraf 6.5.5: her kod değişikliğini denetleyin; doğru, tutarlı, güvenlik açığı içermeyen

Gerektirdiği. Nitelikli bir üçüncü taraf, her kod değişikliği için akıllı sözleşmeleri denetlemeli ve bunların (i) doğru uygulandığını, (ii) amaçlanan işlevsellikle tutarlı olduğunu ve (iii) yüksek düzeyde güvenle güvenlik açıklarından arınmış olduğunu doğrulamalıdır.

Sözleşmenin yaptığı. Mevcut uygulama, 10 Temmuz yükseltmesiyle kurulan uygulamadır (1.5'te izi sürüldü) ve Bölüm 1'deki kusurlar onun içinde canlıdır.

Ayrıştığı nokta. Zincir dışında bir denetim yapılıp yapılmadığını göremiyoruz, ancak sonuç her iki durumda da standardı karşılamıyor. isActive ve sağlayıcı iptali adlarının yaptığını yapmadığı için (i) ve (ii) koşulları karşılanmıyor; Bölüm 1'deki kusurlar dağıtılmış kodda mevcut olduğundan (iii) de karşılanmıyor.

Uyum kontrollerinin etkinliği

Gerektirdiği. Kılavuzun yaşam döngüsü modeli (blacklist, freeze, whitelist, KYC) bu kontrollerin etkili olduğunu varsayar.

Sözleşmenin yaptığı. 1.1'de gösterildiği gibi, KYC denetimi ve sağlayıcı iptali dağıtılmış kodda işlevsel değildir.

Ayrıştığı nokta. Çalışması gereken bir kontrol çalışmıyor. Bu, biçimsel değil, önemli bir boşluktur.

Paragraf 2.2.3: dondurulmuş veya imha edilmiş coinler tamamen karşılıklı ve mutabakat edilebilir kalmalı

Gerektirdiği. Yaptırım eylemiyle dondurulan veya imha edilen stablecoin'ler tamamen karşılıklı kalmalıdır; böylece arz ve rezervler mutabakat edilebilir.

Sözleşmenin yaptığı. Düzenlenmiş bir stablecoin için olağan iyileştirme akışı, kötü bir adresteki fonları yakmak ve daha sonra mağdura ayrı bir mint olarak eşit miktarı yeniden ihraç etmektir (USDT'nin destroyBlackFunds artı issue mekanizması böyle çalışır). HKDAP'ın destroy'u _totalSupply'ı azaltır; bu bir yakmadır, ancak balances[address(this)] alanına asla alacak kaydetmez, address(0) yerine address(this)e bir Transfer yayar ve mint limitinin kullandığı net ihraç sayaçlarına dokunmaz:

// contracts/hce/ControllableAHKD.sol
628    function destroyBlackFunds(address _blackListedUser) external override whenNotPaused onlySupplyDestroyer() {
636        uint dirtyFunds = balanceOf(_blackListedUser);
637        balances[_blackListedUser] = 0;
638        _totalSupply = _totalSupply - dirtyFunds ;
639        emit DestroyedBlackFunds(_blackListedUser, dirtyFunds);
640        emit Transfer(_blackListedUser, address(this), dirtyFunds);
641    }

Ayrıştığı nokta. Durum değişikliği bir yakmadır, ancak olay token'ların sözleşmeye taşındığını söyler ve orada hiçbir şey tutulmaz (balances[address(this)] sıfır kalır). Bir dizinleyici, sahip olmadığı token'ları address(this)e alacak kaydeder ve olaylardan yeniden oluşturulan toplam arz zincirle eşleşmez. Ayrıca iyileştirmenin kendisini de karıştırır: token'lar bekletilmek yerine yakıldığı için, mağdura yeniden ihraç yeni bir mint olmalıdır; ancak yanıltıcı Transfer(..., address(this), ...), sözleşmenin artık onları sakladığını ve iletebileceğini ima eder; oysa yapamaz. address(0)e temiz bir yakma artı ayrı bir yeniden ihraç hem doğru hem de mutabakat edilebilir olurdu. Yazıldığı gibi, bir rezerv mutabakatının bağlı olduğu zincir üstü muhasebe, zincirin gerçek durumundan sapar. Bu, temiz bir geçiş değil, bir endişe kaynağıdır.

Bu bulguları zincirin gösterdikleriyle sınırlıyoruz. Rezervlerin tamamen karşılıklı olup olmadığı, anahtarların bir HSM'de mi yoksa hava boşluklu bir ortamda mı tutulduğu ve işlemlerin imzalanmadan önce zincir dışında simüle edilip edilmediği sözleşmeden görünmez ve bu konularda herhangi bir iddiada bulunmuyoruz.

Sonuç

İncelemenin her iki ekseninde de tablo tutarlıdır. Bir yazılım olarak HKDAP, yazıldığı gibi çalışmayan uyum kontrolleri de dahil olmak üzere işlevsel kusurlar içeriyor ve üretim öncesi bir yapıya dair birçok işaret gösteriyor. Düzenlenmiş bir stablecoin olarak, zincir üstü özelliklerinden birkaçı HKMA kılavuzunun belirli maddeleriyle çelişiyor. Zincir üstü kanıtlara dayanarak ve göremediğimiz zincir dışı konuları bir kenara bırakarak, dağıtılmış sözleşme henüz ticari bir stablecoin'in karşılaması gereken standardı karşılamıyor.

Bunu takip eden iki gözlem var ve açıkça belirtilmeye değer.

Birincisi, halka açık bir zincirde ihraç etmek, uyumun nerede kararlaştırıldığını değiştirir. "Hiçbir tek taraf tek taraflı hareket edememeli" gibi bir gereksinim, dağıtılmış koddaki rol kontrolleri tarafından karşılanır veya karşılanmaz ve bu kod herkese açıktır. Böyle bir gereksinimin gerçekten karşılandığı ya da kaçırıldığı yer lisans veya dokümantasyon değil, uygulamadır ve herkes hangisinin geçerli olduğunu doğrulayabilir.

İkincisi, "Beta Access" etiketi dağıtılmış kodun risk profilini değiştirmez. Sözleşme Ethereum ana ağında canlıdır, gerçek anahtarlarla yönetilir ve Hong Kong doları üzerinde bir hak talebini temsil eder. Bu nedenle, nasıl etiketlendiğinden bağımsız olarak üretim standartlarına tabi tutulmalıdır.

Belirli bulguların altında ortak bir izlek var. Mimari, ekosistemin hâlihazırda sağladığı ve ölçekte denetlediği ilkel yapıları özel biçimde yeniden icat ediyor: bir Safe multisig ile OpenZeppelin'in AccessManager ve TimelockController'ının yeterli olacağı yerde sıfırdan bir onay motoru ve rol katmanı; EnumerableSet yerine elle yazılmış bağlı liste koleksiyonu; standart TransparentUpgradeableProxy yerine değiştirilmiş bir proxy; ve OpenZeppelin'in yerine elle yazılmış bir ERC-20. Bu incelemedeki kusurların çoğu, standart bileşenleri yeniden kullanan kısımlarda değil, bu özel mekanizmada yaşıyor. Sistem, zincir üstü geliştirmenin desteklediği küçük, denetlenmiş yapı taşlarından oluşmak yerine, genel amaçlı yazılımların soyutlandığı gibi soyutlanmış görünüyor; özel soyutlamanın her katmanı aynı zamanda gas, saldırı yüzeyi ve yükseltme riskidir. Bu standart bileşenlerden inşa edilmiş bir tasarım daha küçük, daha güvenli ve incelenmesi daha kolay olur ve bu sistemin şu anda eksik olduğu şeyleri beraberinde getirirdi: bir timelock'tan gelen bir müzakere penceresi ve adlandırılmış, okunaklı roller.

Burada açıklanan sorunlar giderilebilir. Yüksek riskli işlemlerde çoklu imzayı yeniden sağlamak, yürütmeyi denetimden ayırmak, KYC iptal mantığını düzeltmek, transfer kontrollerini birleştirmek, hata ayıklama kodunu kaldırmak ve her yükseltmeden önce üçüncü taraf denetimi zorunlu kılmak bunların çoğunu çözecektir. Doğrulanmış kaynakla ana ağda dağıtım yapmak da bu incelemeyi mümkün kılan şeydir ve doğru varsayılandır. Bu tür sürekli zincir üstü güvenlik ve uyum incelemesi, BlockSec'te yaptığımız iştir ve yardımcı olmaktan mutluluk duyarız.

Get Real-Time Protection with Phalcon Security

Audits alone are not enough. Phalcon Security detects attacks in real time and blocks threats mid-flight.

phalcon security