Work Writing About Work with me

RWA: Past, Present and FutureCzęść 5 z 13

Klucz prywatny nie wystarcza: kto może odebrać token RWA

Najmocniejsze uprawnienie w kontrakcie BUIDL, funkcja setTarget podmieniająca całą implementację, należało 4 września 2026 do jednego konta zewnętrznego, bez wielopodpisu i bez timelocka. Produkt o rząd wielkości mniejszy, OUSG od Ondo, rozłożył uprawnienia na trzy struktury wielopodpisowe o progach 4 z 7, 3 z 5 oraz 1 z 9. Jakość zarządzania uprawnieniami administracyjnymi w permissioned RWA jest odwrotnie proporcjonalna do wielkości emitenta.

W tym artykule

Wszystkie odczyty on-chain w tym tekście pochodzą z 4 września 2026, przez publiczne endpointy eth.blockscout.com (Ethereum mainnet) i horizon.stellar.org (Stellar). Adresy kontraktów podaję, żeby dało się je powtórzyć.

Backdoor nie jest luką w tych produktach, jest wymogiem

W permissioned RWA klucz prywatny nie daje kontroli nad saldem: potrzebny jest klucz oraz zgoda emitenta zapisana w rejestrze on-chain. To wiadomo z dokumentacji. Z dokumentacji nie wiadomo natomiast tego, co da się odczytać z kodu, i temu poświęcony jest ten tekst.

Zwykły ERC-20 ma jedną regułę transferu: saldo wystarcza, żeby je wysłać. Papier wartościowy takiej reguły mieć nie może, bo prawo nakłada na jego obrót pięć warunków: kto może posiadać, kiedy może przenieść, ile może posiadać, co się dzieje po nakazie sądowym, kto to nadzoruje.

Ten ostatni punkt jest najbardziej niewygodny. Transfer agent, czyli podmiot prowadzący rejestr posiadaczy udziałów funduszu (w tradycyjnym świecie bazę danych, a w RWA smart contract), ma prawny obowiązek wykonywania nakazów sądowych i korygowania błędów rejestru. Transfer agent zarejestrowany w SEC, który nie potrafi technicznie przenieść udziałów na podstawie nakazu, nie może wykonywać swojej funkcji. Stąd wniosek, który brzmi jak zarzut, a jest opisem konstrukcji: produkt zgodny z prawem musi mieć backdoora. Nie „może mieć". Musi.

Dlatego pytanie „czy ten produkt ma admin keys" jest źle postawione, bo odpowiedź zawsze brzmi „tak". Właściwe pytanie ma trzy części: jak wąsko zdefiniowano te uprawnienia, kto je trzyma, czy da się zweryfikować, że ich nie użyto.

seize to sześć linijek kodu i jedna rola

BUIDL, tokenizowany fundusz BlackRocka z rejestrem udziałów prowadzonym on-chain przez Securitize jako transfer agenta, działa na własnościowej architekturze DS Protocol firmy Securitize. Nie jest to żaden EIP; kod ma nagłówek SPDX-License-Identifier: UNLICENSED, ale jest w pełni zweryfikowany na łańcuchu i można go przeczytać.

Funkcja przymusowego przeniesienia (forced transfer, czyli przeniesienie tokenów z adresu A na adres B bez zgody posiadacza A) nazywa się tu seize i wygląda tak:

function seize(address _from, address _to, uint256 _value, string memory _reason)
    public virtual override onlyTransferAgentOrAbove {
    TokenLibrary.seize(tokenData, getCommonServices(), _from, _to, _value);
    emit Seize(_from, _to, _value, _reason);
    emit Transfer(_from, _to, _value);
    checkWalletsForList(_from, _to);
}

W tych sześciu linijkach istotne są trzy rzeczy.

Modyfikator to onlyTransferAgentOrAbove, nie onlyMaster. W DS Protocol role są czterostopniowe: MASTER (1), ISSUER (2), EXCHANGE (4), TRANSFER_AGENT (8). Do przejęcia tokenów wystarcza druga rola od dołu. Rolę TRANSFER_AGENT na kontraktcie BUIDL mają dziś dwa podmioty (odczyt getRole() na Trust Service 0x3a68756d0335e75c909ba1e8fefc1d4832c36c60, 4 września 2026): konto zewnętrzne 0xA9994621F1c3EE59846Df756488229E8efDCB8bf i kontrakt TokenReallocator 0xf33675685C8Ee774c7f5655C93AfEdC7B9818EcD. Do tego konto MASTER.

Pole _reason przyjmuje dowolny string. Nie ma odwołania do hashu dokumentu, do rejestru nakazów, do żadnej weryfikowalnej podstawy. Uzasadnienie przejęcia udziałów jest polem tekstowym.

Operacji nie da się ukryć. Obok standardowego Transfer emitowane jest osobne zdarzenie Seize, więc każde użycie jest widoczne w indeksach natychmiast. To ważne i pozytywne.

Odpowiednik clawbacku, czyli odebranie tokenów bez przenoszenia ich na wskazany adres, to w BUIDL burn wywołany na cudzym adresie, z modyfikatorem onlyIssuerOrTransferAgentOrAbove. Krąg uprawnionych jest tu szerszy niż dla seize: rola ISSUER wystarcza do palenia z dowolnego adresu, ale nie do przymusowego przeniesienia. Rolę ISSUER ma dziś 2 konta zewnętrzne i 6 kontraktów systemowych (odczyt on-chain, 4 września 2026), łącznie osiem uprawnionych podmiotów.

Najgroźniejsza funkcja nie nazywa się seize, a setTarget

Proxy BUIDL (0x7712c34205737192402172409a8F7ccef8aA2AEc) to nie standardowy wzorzec OpenZeppelin. To własny, czterdziestolinijkowy kontrakt. Jego istotna część:

function setTarget(address _target) public onlyOwner {
    target = _target;
    emit ProxyTargetSet(_target);
}

Czego tu nie ma, a w standardowych rozwiązaniach jest: timelocka (zmiana wchodzi natychmiast), rozdzielenia admina proxy od właściciela logiki, wielopodpisu na poziomie kontraktu. Jedna zmienna, jedno wywołanie, cała implementacja podmieniona.

Odczyt owner() na tym adresie zwraca 0xE01605f6b6dc593b7d2917F4a0940dB2A625b09e. Typ adresu: konto zewnętrzne (EOA), nie kontrakt, nie multisig, nie Safe. Ten sam adres ma rolę MASTER w Trust Service, bo getRole() zwraca 1 (odczyt on-chain, 4 września 2026).

Jeden klucz prywatny może zatem w jednej transakcji podmienić całą implementację kontraktu i jednocześnie trzyma najwyższą rolę administracyjną w systemie ról. Wszystkie odpowiedzi na pytanie „co ten kontrakt potrafi" są wobec tego tymczasowe, bo nowa implementacja może potrafić cokolwiek.

Uwaga metodologiczna: rola w kontraktcie nie mówi, kto trzyma klucz. Za adresem EOA może stać HSM z proceduralnym wielopodpisem po stronie operacyjnej Securitize i prawdopodobnie tak jest, ale on-chain tego nie widać. Multisig widać; procedura wewnętrzna nie.

Dobra praktyka jest w historii tego kontraktu widoczna: wdrożenie nastąpiło w bloku 19 343 277 (2024-03-01 22:20 UTC), a deployer zrzekł się roli MASTER 22 minuty później, w bloku 19 343 383, przekazując ją docelowemu adresowi.

Drugi produkt nie ma tej funkcji w kodzie w ogóle

OUSG od Ondo to kontrakt CashKYCSenderReceiver (0x1CEB44b6E515aBf009E0CCb6ddaFD723886cf3Ff), czyli minimalne rozszerzenie OpenZeppelin z hookiem sprawdzającym KYC dla nadawcy, odbiorcy oraz wywołującego transakcję. Pełny zestaw funkcji mutujących odczytany z ABI (4 września 2026) to: approve, burn(uint256), burn(address,uint256), burnFrom, decreaseAllowance, grantRole, increaseAllowance, initialize, mint, pause, renounceRole, revokeRole, setKYCRegistry, setKYCRequirementGroup, transfer, transferFrom, unpause.

Czego na tej liście nie ma: seize, forcedTransfer, freeze, setAddressFrozen, recoveryAddress. Kontrakt OUSG nie potrafi przenieść tokenów posiadacza na inny adres. W ogóle, nie ma takiej funkcji w kodzie.

Funkcja burn(address, uint256), czyli palenie z cudzego adresu, istnieje, ale jest chroniona rolą BURNER_ROLE, której nigdy nikomu nie nadano. Weryfikacja dwiema metodami: skan wszystkich zdarzeń RoleGranted od bloku wdrożenia (16 234 210) do bieżącego nie pokazuje ani jednego nadania tej roli, a hasRole(BURNER_ROLE, addr) zwraca false dla wszystkich adresów, które kiedykolwiek dostały jakąkolwiek rolę (odczyt on-chain, 4 września 2026).

To daje trzeci stan, którego większość analiz nie zna. Zwykle mówi się „ma uprawnienie" albo „nie ma". W praktyce najczęstszy jest stan pośredni: funkcja jest, uprawnionego nie ma, a odległość do stanu trzeciego mierzy się liczbą transakcji i podpisów.

Funkcji nie ma w kodzie · funkcja jest, brak uprawnionego · funkcja jest, są uprawnieni. Przy każdym przejściu liczba transakcji i podpisów, które je wykonują.
Funkcji nie ma w kodzie · funkcja jest, brak uprawnionego · funkcja jest, są uprawnieni. Przy każdym przejściu liczba transakcji i podpisów, które je wykonują.

Dla OUSG przejście z drugiego stanu do trzeciego to jedno wywołanie grantRole przez Safe o progu 4 z 7. Dla BUIDL nie ma żadnego przejścia, bo uprawnieni są już na miejscu.

Trzy multisigi o trzech progach ma średni emitent, nie największy

Uprawnienia OUSG rozłożono na trzy osobne struktury wielopodpisowe o trzech różnych progach (weryfikacja getThreshold() i getOwners(), 4 września 2026):

Zakres Struktura Próg
administracja tokena (DEFAULT_ADMIN, MINTER, KYC_CONFIGURER) Safe 0xaed4caf2e535d964165b4392342f71bac77e8367 4 z 7
rejestr tożsamości OndoIDRegistryView 0x56a5d911052323d688c731d516530878557463e7 Safe 0x5ae21c99fc5f1584d8cb09a298cffd92b5d178ef 3 z 5
pauza awaryjna (PAUSER) Safe 0x2e55b738f5969eea10fb67e326bee5e2fa15a2cc 1 z 9

Ten ostatni próg wygląda jak błąd, a jest projektem: dziewięciu właścicieli, jeden podpis wystarcza, każda z dziewięciu osób może samodzielnie zatrzymać cały token. Uprawnienia destrukcyjne dostały wysoki próg, uprawnienia obronne niski. Do tego rejestr tożsamości: deployer nadał sobie rolę w bloku 22 141 359, przekazał ją multisigowi w bloku 22 141 361, a zrzekł się jej w bloku 22 141 362, czyli w trzech blokach komplet.

Dźwignia w OUSG leży nie w forced transfer, którego kontrakt nie ma, ale w rejestrze KYC. Hook _beforeTokenTransfer wymaga statusu KYC dla nadawcy, odbiorcy oraz wywołującego, więc zarządca rejestru może skutecznie zablokować posiadacza, mimo braku funkcji freeze: po usunięciu z rejestru jego transfer będzie revertował. Funkcja setKYCRegistry pozwala podmienić cały rejestr tożsamości pod tokenem; uprawnienie ma Safe 4 z 7. Freeze przez usunięcie z rejestru jest przy tym trudniejszy do wykrycia z zewnątrz niż jawna flaga frozen: nie ma zdarzenia „zamrożono adres X", jest zdarzenie usunięcia z rejestru, wyglądające jak rutynowa operacja compliance.

Na Stellarze clawback wykonuje jeden z dziesięciu sygnatariuszy

BENJI Franklin Templetona nie ma smart contractu z compliance. Ma flagi na koncie emitenta, czyli reguły egzekwowane przez protokół sieci, nie przez kod emitenta. Konto emitenta to GBHNGLLIE3KWGKCHIKMHJ5HVZHYIK7WTBE4QF5PLAKL4CJGSEU7HZIW5, weryfikowalne przez home_domain = www.franklintempleton.com (odczyt Horizon, 4 września 2026). Wszystkie trzy flagi kontrolne są włączone: auth_required (nikt nie trzyma BENJI bez jawnej autoryzacji), auth_revocable (autoryzację można odebrać, czyli zamrozić saldo), auth_clawback_enabled (tokeny można odebrać z dowolnego konta). Czwarta, auth_immutable, jest na false, więc flagi wciąż można zmienić.

Model podpisów jest nietypowy. Master key konta ma wagę 0, czyli jest wyłączony i nie podpisze samodzielnie niczego. Sygnatariuszy o wadze 3 jest dziesięciu, o wadze 1 czterech, suma wag 34. Progi: low = 2, med = 2, high = 6.

Operacja Clawback podlega progowi medium. Skoro med_threshold = 2, a sygnatariusz wagi 3 sam przekracza ten próg, to jeden z dziesięciu sygnatariuszy może samodzielnie odebrać BENJI z dowolnego konta albo je zdeautoryzować. Zmiana samych reguł przez SetOptions (dodanie sygnatariusza, zmiana progów, zmiana flag) wymaga progu 6, więc dwóch sygnatariuszy wagi 3. Projekt jest świadomie asymetryczny: operacje w ramach reguł mają niski próg, zmiana reguł wysoki. Ta sama filozofia co progi 4 z 7 i 1 z 9 w OUSG, wyrażona w innym systemie.

Skuteczność allow-listy widać w liczbach: BENJI ma 1 357 autoryzowanych trustlinek i 953 nieautoryzowane (odczyt Horizon, 4 września 2026). Trustline to na Stellarze deklaracja konta, że chce trzymać dany asset, czyli 41% chętnych odrzucono na poziomie protokołu.

Rodzaj uprawnienia różni się bardziej niż jego siła

Trzy produkty, trzy modele władzy: kto może przejąć, odebrać, zamrozić, zmienić reguły, oraz jakiego typu podmiotem jest posiadacz każdego uprawnienia.
Trzy produkty, trzy modele władzy: kto może przejąć, odebrać, zamrozić, zmienić reguły, oraz jakiego typu podmiotem jest posiadacz każdego uprawnienia.

Te trzy modele różnią się nie stopniem, ale rodzajem:

Wymiar BUIDL (DS Protocol) OUSG (ERC-20 + rejestr KYC) BENJI (Stellar)
Przejęcie tokenów seize → dowolny adres brak funkcji w kodzie Clawback → unicestwienie
Wycofanie tokenów burn, 8 uprawnionych burn(address,…), 0 uprawnionych Clawback, próg 2 (1 sygnatariusz wagi 3)
Zamrożenie salda pośrednio (usunięcie z rejestru) pośrednio (usunięcie z rejestru KYC) wprost, auth_revocable
Pauza całego tokena TRANSFER_AGENT lub wyżej Safe 4 z 7 lub Safe 1 z 9 brak globalnej pauzy
Zmiana reguł setTarget, 1 EOA ProxyAdmin 0xba80aa44cc25e85cc30359150dfb1c7d041cf6d5 → Safe 4 z 7 SetOptions, próg 6 (2 sygnatariusze)
Timelock brak brak brak

seize przenosi tokeny na wskazany adres, więc token dalej istnieje i można go zwrócić. Clawback unicestwia, więc nie ma czego zwracać. Te dwie rzeczy bywają opisywane tym samym zwrotem „możliwość zamrożenia tokenów" i to jest nieprecyzyjne do bezużyteczności.

Drugi wynik jest mniej oczekiwany. Największy produkt ma najsłabszą higienę kluczy, średni najlepszą. BUIDL ma jeden EOA na upgrade i osiem podmiotów uprawnionych do palenia z cudzego adresu. OUSG ma trzy multisigi o trzech progach i zero uprawnionych do palenia. Powód jest strukturalny, nie kulturowy: BUIDL to fundusz działający na wyłączeniu Section 3(c)(7) z Investment Company Act, z transfer agentem zarejestrowanym w SEC, który ma obowiązki rejestrowe wymagające tych funkcji. Więcej uprawnień nie oznacza gorszego produktu, ale inne obowiązki. Oznacza też inny profil ryzyka.

Trzeci wynik: żadne z tych uprawnień nie jest audytowalne przed użyciem. Wszystkie trzy są audytowalne po. Nie ma timelocka w żadnym z tych produktów, więc użycie seize na danym adresie staje się widoczne dopiero po fakcie.

Compliance jest w kontraktcie i kosztuje cztery razy więcej gazu

Parametry, które w tradycyjnym funduszu leżą w dokumencie ofertowym, w BUIDL leżą w kontraktcie ComplianceConfigurationService (0x1dc378568cefd4596c5f9f9a14256d8250b56369). Odczyt getterów, 4 września 2026:

Parametr Wartość Znaczenie
getTotalInvestorsLimit() 1 999 maksymalna liczba inwestorów
getTotalInvestorsCount() 89 stan faktyczny, 4,5% limitu
getUSAccreditedInvestorsCount() 32 inwestorzy akredytowani z USA
getForceAccredited() / getForceAccreditedUS() 1 / 1 wszyscy muszą być akredytowani
getUSLockPeriod() / getNonUSLockPeriod() 86 400 s (24 h) lock-up, czyli minimalny czas między nabyciem i możliwością zbycia
getBlockFlowbackEndTime() 1 703 980 800 (31 grudnia 2023) data w przeszłości, blokada flowbacku wygasła
getMaximumHoldingsPerInvestor() 0 brak limitu górnego

Limit 1 999 inwestorów jest wykorzystany w 4,5%, co przeczy narracji o „ograniczonej pojemności" tych funduszy. Lock-up wynosi 24 godziny, nie rok. To nie produkt zablokowany na długo, ale produkt zablokowany dla wąskiej grupy. Osobno: cap() zwraca 0, czyli podaż nie ma limitu emisji, a setCap jest jednorazowy i przysługuje transfer agentowi.

Ta warstwa ma mierzalny koszt. Compliance BUIDL jest rozproszony na jedenaście osobnych kontraktów wywoływanych przy transferze, w tym InvestorLockManager (0x0a65a40a4b2f64d3445a628abcfc8128625483a4) i ComplianceServiceRegulated (0x07a1ebfb9a9a421249ddc71bddb8860cc077e3a9). Pomiar gasUsed dla transfer(address,uint256) na Ethereum mainnet, mediana z potwierdzonych transakcji (4 września 2026):

Token Architektura gasUsed n Mnożnik
USDC zwykły ERC-20 45 160 40 1,00×
OUSG 1 kontrakt + 1 rejestr 91 335 17 2,02×
BUIDL 11 kontraktów DS Protocol 183 672 46 4,07×

Rozstrzał w BUIDL sięga od 178 569 do 1 139 537 jednostek, a górna wartość to transfer uruchamiający dodatkowe operacje rejestrowe. Dwa razy więcej reguł to dwa razy więcej gazu, czyli techniczny sufit dla produktów detalicznych na Ethereum mainnet.

Zero użyć w dwa i pół roku nie jest dowodem bezpieczeństwa

Skan logów kontraktu BUIDL po topic0 zdarzeń, od bloku wdrożenia (19 343 277) do 4 września 2026:

  • Seize — 0
  • OmnibusSeize — 0
  • OmnibusBurn — 0
  • Pause — 0, Unpause — 0
  • Burn — 208
  • Issue — ponad 1 000

Uprawnienie do przymusowego przeniesienia istnieje od 1 marca 2024 i nie zostało użyte ani razu; token nigdy nie był zatrzymany. Na OUSG rola do palenia z cudzego adresu nigdy nie została nikomu nadana. Na BENJI nie znalazłem operacji clawback, ale to próbka 200 ostatnich operacji konta emitenta, pokrywająca około 7,5 godziny, więc nie jest to dowód braku użycia w całej historii aktywa.

Z 208 zdarzeń Burn na BUIDL nie da się odróżnić wykupu od konfiskaty. Oba emitują to samo zdarzenie z polem _reason wypełnianym dowolnym stringiem, a treści tych pól nie odczytano. Interpretacja „to niemal na pewno wykupy" jest uzasadniona mechaniką umorzenia w tym modelu, ale nie jest pomiarem.

Zero użyć nie jest dowodem bezpieczeństwa; jest dowodem, że dotąd nie użyto. To jednak jedyny dowód, jaki w tej sprawie istnieje, i pozwala oddzielić ryzyko potencjalne od zmaterializowanego. W tych trzech produktach ryzyko admin keys jest dziś potencjalne, a to sformułowanie jest uczciwsze niż obie skrajne narracje.

Cztery sieci, ten sam backdoor, cztery różne implementacje

Wszystko powyżej opierało się na odczycie z Ethereum. To była największa dziura w tym tekście, bo BUIDL istnieje w wielu wdrożeniach, a każde jest osobnym kontraktem, nie kopią. Odczytałem więc uprawnienia BUIDL bezpośrednio z trzech kolejnych łańcuchów: Avalanche, Solany, Aptosa, 5 września 2026. Adresy wzięte z mapowania platform w CoinGecko, ale każdy zweryfikowany odczytem symbol(), name() albo metadanych na docelowej sieci. Adres z serwisu trzeciego nie jest jeszcze dowodem, że odczytywany kontrakt jest właściwy. Adres solanowy zgadza się także z komunikatem Securitize z 25 marca 2025 🟢.

Wynik jest jednoznaczny w jednej rzeczy: odpowiednik funkcji seize istnieje na każdej sprawdzonej sieci. Nigdzie nie znalazłem multisiga.

BUIDL na czterech sieciach z dziewięciu: odpowiednik funkcji seize istnieje na każdej, multisiga nie ma na żadnej. Odczyt z łańcuchów, 4–5 września 2026.
BUIDL na czterech sieciach z dziewięciu: odpowiednik funkcji seize istnieje na każdej, multisiga nie ma na żadnej. Odczyt z łańcuchów, 4–5 września 2026.

Avalanche nie powtarza wzorca proxy z Ethereum

Token 0x53fc82f14f009009b440a706e31c9021e1196a2f, proxy o długości 171 bajtów wskazujące na implementację 0xf93667d01c7675e2667ee392aa69104df79c4ad0 (19 063 bajty). Skan bytecode implementacji na selektory funkcji daje obecne: seize(address,address,uint256,string), omnibusSeize(...), burn(address,uint256,string), omnibusBurn(...), pause(), unpause(), transferOwnership(address), setDSService(uint256,address), preTransferCheck(address,address,uint256). Nieobecne: forcedTransfer, freeze, unfreeze, mint(address,uint256) oraz setTarget(address). Wdrożenie na Avalanche nie powtarza więc wzorca proxy z Ethereum, opisanego wyżej jako najgroźniejszy. Tu jest standardowe ERC-1967 z pustym slotem admina, a ścieżka aktualizacji prowadzi przez upgradeToAndCall w samej implementacji, czyli UUPS.

Uprawnienie właścicielskie: owner() zwraca 0xe01605f6b6dc593b7d2917f4a0940db2a625b09e, a eth_getCode na tym adresie zwraca pustkę, czyli to konto zewnętrzne, nie kontrakt, nie multisig. isPaused() zwraca 0. Z odczytu bloku wdrożenia wynika, że kontrakt stoi na łańcuchu od 4 listopada 2024, 14:12 UTC, czyli dziewięć dni przed komunikatem o ekspansji z 13 listopada 2024 🟢.

Na Solanie uprawnienie trzyma program, a nie klucz prywatny

Mint GyWgeqpy5GueU2YbkE8xqUeVEokCMMCEeUrfbtMw6phr działa na programie Token-2022. Rozszerzenie permanentDelegate jest włączone, a delegatem jest APm3MWbXfMMKAWgsDVnxcAGbLjvRxubPu1A8a5SA2kbJ. Permanent delegate może przenieść albo spalić tokeny z dowolnego konta posiadacza bez jego udziału i, inaczej niż zwykłe zezwolenie, nie da się go odwołać. Ten sam adres jest jednocześnie mintAuthority, freezeAuthority, mintCloseAuthority, authority transferHook i authority metadanych. Pięć uprawnień, jeden adres.

Tu jednak zaczyna się rzecz, której nie przewidziałem: APm3MW… nie jest kluczem prywatnym. Konto ma 73 bajty danych i należy do programu 7tXjmbkZVY3Gmg9kDBebcNXT1yC5pyoxxXVLwdbv9tvP, czyli jest kontem sterowanym programowo. Nikt nie „ma klucza do seize" na Solanie w tym sensie, w jakim ma go na Ethereum. Struktura jest lepsza niż na Ethereum, ale tylko o jeden poziom. Program-kontroler został wdrożony 14 marca 2025, a program transfer hooka (FsE8mCJyvgMzqJbfHbJQm3iuf3cRZC6n2vZi1Q8rQCy2) 26 sierpnia 2025, i upgrade authority obu jest ten sam adres 8d36iv2YUD8yDChuVZchx1NqE4qkDWCAEgsUEEUqzbB6, który należy do System Program i ma zero bajtów danych, czyli jest zwykłym kontem-kluczem. Kto go kontroluje, nie przejmie tokenów jednym podpisem, ale może podmienić kod programu, który to robi. To ta sama koncentracja co na Ethereum, przesunięta o jeden krok w tył.

Na Aptosie token nie jest domyślnie zbywalny

Obiekt fungible asset 0x50038be55be5b964cfa32cf128b5cf05f123959f286b4cc02b86cafd48945f89 ma metadane „BlackRock BUIDL", symbol BUIDL, 6 miejsc po przecinku. Uprawnienia są tu wyrażone w sposób, którego nie ma na żadnym EVM: obiekt ma zasób 0x1::fungible_asset::Untransferable, co wyłącza zwykły transfer na poziomie samego standardu. Token staje się zbywalny wyłącznie przez funkcje dyspozytorskie emitenta. Do tego dochodzi dispatchable_fungible_asset::TransferRefStore, czyli moduł Securitize trzyma referencję pozwalającą ruszyć zawartość dowolnego magazynu, oraz DispatchFunctionStore z własnymi hookami wypłaty i wpłaty, czyli kontrolą compliance przy każdym transferze.

Funkcja jest w Move nazwana dokładnie tak samo jak w Solidity: ds_token::seize(&signer, address, address, u64, String), funkcja typu entry, z tym samym dowolnym stringiem jako uzasadnieniem. Obok niej ds_token::burn(&signer, address, u64, String), set_pause, transfer_from, set_cap, set_features, set_metadata. Cały DS Protocol został przeniesiony na Move jako dziewięć modułów: ds_token, lock_manager, token_issuer, bulk_operator, trust_service, wallet_manager, registry_service, wallet_registrar, compliance_service. is_paused zwraca false.

Kontrola: moduły stoją na koncie 0x4de5876d8a8e2be7af6af9f3ca94d9e4fafb24b5f4a5848078d8eb08f08e808a, które jest kontem-obiektem, ma zasób ObjectCore i sequence_number równy 0, czyli samo nigdy nie podpisało transakcji. Właścicielem tego obiektu jest 0x91840004a08dbf21c9ad96ee1c8ef40a6aca24fba6ff23b6ded5a8d17028977b, konto z jednym zasobem Account, bez zasobu multisig. Warstwa pośrednia jest, rozproszenia kontroli nie ma.

Ethereum nie jest największym wdrożeniem BUIDL

Podaże BUIDL na sprawdzonych sieciach, w jednostkach tokena: Solana 977 902 117,97; Avalanche 564 231 692,75; Ethereum 211 920 742,07 (odczyt 4 września 2026); Aptos 161 340 739,89. Razem 1 915 395 292,68 na czterech sieciach z dziewięciu. Solana jest od Ethereum 4,6 razy większa. Każde zdanie o tym produkcie oparte wyłącznie na odczycie z Ethereum opisuje jedenaście procent jego podaży. Włącznie z moimi wcześniejszymi.

Czego nie ustaliłem. Czy uprawnienie przymusowe zostało kiedykolwiek użyte na Avalanche, Solanie albo Aptosie, nie wiem. Na Avalanche publiczny węzeł limituje eth_getLogs do 2048 bloków, a od wdrożenia minęło 41 884 144 bloków, co daje 20 451 żądań na pełną historię; nie wykonałem tego. Na Solanie wymagałoby to skanu historii transakcji, na Aptosie indeksera, do którego nie miałem dostępu. Zero użyć jest potwierdzone wyłącznie dla Ethereum i wyłącznie na dzień 4 września 2026.

Trzy pytania, których nie zadaje żaden materiał marketingowy

Klucz prywatny w permissioned RWA nie wystarcza i to jest cecha konstrukcji, nie usterka: bez seize transfer agent nie wykonałby nakazu sądowego, a bez allow-listy fundusz nie wszedłby na publiczny łańcuch. Odczyt kodu pokazuje jednak coś, czego z tej konstrukcji nie da się wyprowadzić: sposób trzymania tych uprawnień nie skaluje się z wielkością emitenta. Skaluje się z tym, kiedy produkt zbudowano i po co. BlackRock i Securitize dostali architekturę zaprojektowaną wokół obowiązków transfer agenta, z jednym EOA jako właścicielem proxy. Ondo, młodsza firma crypto-native bez tych obowiązków, zbudowała trzy multisigi i nie napisała funkcji przejęcia. Franklin Templeton oddał compliance protokołowi i wyłączył master key konta, ale pozostawił clawback jednemu podpisowi z dziesięciu.

Z tego wynikają trzy pytania, na które odpowiada łańcuch, a nie dek. Pierwsze dotyczy tego, kto może zmienić reguły: EOA, multisig, multisig z timelockiem. Drugie dotyczy tego, kto może ruszyć saldo posiadacza bez jego zgody, czyli czy funkcja istnieje, czy ma uprawnionego, ilu ich jest. Trzecie dotyczy tego, czy tych uprawnień użyto, czyli ile zdarzeń w jakim okresie. Trzecie jest najłatwiejsze i najczęściej pomijane, a pierwsze jest najważniejsze, bo unieważnia odpowiedź na drugie: jeśli implementację można podmienić jedną transakcją, to „w kodzie nie ma seize" jest stanem, nie gwarancją.

Źródła

🟢 pierwotne · 🟡 wtórne wiarygodne · 🔴 trzeciorzędne (nie służą do cytowania liczb)

Odczyty on-chain — 4 września 2026 (🟢 pierwotne)

  • Ethereum mainnet przez eth.blockscout.com (API v2 dla kodu źródłowego i ABI, api/eth-rpc dla eth_call, eth_getStorageAt, eth_getLogs)
  • BUIDL proxy 0x7712c34205737192402172409a8F7ccef8aA2AEc — pełny kod kontraktu Proxy (40 linii), owner(), target(), sloty 0 i 1
  • BUIDL implementacja 0x603bB6909bE14F83282e03632280d91Be7Fb83B2 — DSToken v5, kod główny plus 36 plików zależnych (ComplianceServiceRegulated, ServiceConsumer, IDSTrustService, TokenLibrary i pozostałe)
  • BUIDL Trust Service 0x3a68756d0335e75c909ba1e8fefc1d4832c36c60 — zdekodowane zdarzenia DSTrustServiceRoleAdded / RoleRemoved / ProxyTargetSet / ProxyOwnerChanged (20 zdarzeń, komplet), getRole() dla 11 adresów
  • BUIDL ComplianceConfigurationService 0x1dc378568cefd4596c5f9f9a14256d8250b56369 — 40 getterów parametrów compliance; ComplianceServiceRegulated 0x07a1ebfb9a9a421249ddc71bddb8860cc077e3a9 — liczniki inwestorów
  • BUIDL — rejestr usług przez getDSService(uint256) dla 13 identyfikatorów; skan eth_getLogs po topic0 zdarzeń Seize, OmnibusSeize, Burn, OmnibusBurn, Pause, Unpause, Issue od bloku 19 343 277; daty bloków przez eth_getBlockByNumber
  • OUSG proxy 0x1B19C19393e2d034D8Ff31ff34c81252FCBbee92 (slot EIP-1967 implementacji i admina), implementacja 0x1CEB44b6E515aBf009E0CCb6ddaFD723886cf3Ff — pełny kod CashKYCSenderReceiver plus 22 pliki zależne
  • OUSG — komplet zdarzeń RoleGranted (28) i RoleRevoked (22) od bloku 16 234 210; weryfikacja przez hasRole() dla 5 ról × 6 adresów; ProxyAdmin 0xba80aa44cc25e85cc30359150dfb1c7d041cf6d5 → owner()
  • Safe 0xaed4caf2e535d964165b4392342f71bac77e8367 (getThreshold() = 4, 7 właścicieli), Safe 0x2e55b738f5969eea10fb67e326bee5e2fa15a2cc (getThreshold() = 1, 9 właścicieli), Safe 0x5ae21c99fc5f1584d8cb09a298cffd92b5d178ef (getThreshold() = 3, 5 właścicieli); OndoIDRegistryView 0x56a5d911052323d688c731d516530878557463e7 — ABI, zdarzenia ról, hasRole()
  • Pomiar gasUsed dla transfer(address,uint256): USDC 0xA0b86991…eB48 (n = 40), OUSG (n = 17), BUIDL (n = 46), przez eth_getLogs i eth_getTransactionReceipt
  • Stellar przez horizon.stellar.org: GET /accounts/GBHNGLLI…ZIW5 (home_domain, flags, thresholds, sygnatariusze z wagami), GET /assets?asset_code=BENJI&limit=20, GET /accounts/{issuer}/operations?order=desc&limit=200

Dokumentacja i specyfikacje (🟢 pierwotne)

  • Kod źródłowy DS Protocol — odczytany z łańcucha; licencja UNLICENSED, brak publicznego repozytorium
  • Stellar Developers — semantyka flag auth_required, auth_revocable, auth_clawback_enabled, auth_immutable; model wag i progów sygnatariuszy
  • Securitize, komunikat prasowy o uruchomieniu BUIDL — role BlackRock Financial Management, BNY Mellon, Securitize, PwC; podstawa prawna Rule 506(c) i Section 3(c)(7)
  • Stellar.org, case study Franklin Templeton — uzasadnienie wyboru sieci (kontrole na poziomie protokołu)

Źródła wtórne (🟡)

  • Etherscan — liczba posiadaczy OUSG (53) na 13 sierpnia 2026

  • Kaleido, Understanding ERC-3643 Tokenization on Ethereum; QuickNode Guides, What is ERC-3643? — architektura standardu i nazwy uprawnień administracyjnych, użyte wyłącznie do kontekstu porównawczego

  • Coinpaprika, BlackRock BUIDL Fund — rejestracja spółki BVI 18 września 2023, start produktu 20 marca 2024

  • Odczyt on-chain z 5 września 2026 🟢 — Avalanche C-Chain (eth_call, eth_getCode, eth_getStorageAt na slocie implementacji ERC-1967, skan selektorów w bytecode implementacji), Solana (getAccountInfo z parsowaniem rozszerzeń Token-2022, getTokenSupply, konta ProgramData obu programów), Aptos (/accounts/{addr}/resources, /accounts/{addr}/modules, /view dla is_paused). Surowe wyniki w pliku onchain_multichain_buidl.json

  • CoinGecko, endpoint /coins 🟡 — mapowanie adresów kontraktu na dziewięć platform, stan na 5 września 2026. Użyte wyłącznie do znalezienia adresów; każdy adres zweryfikowany następnie odczytem z docelowej sieci

  • Securitize/PR Newswire, komunikat o klasie udziałów na Solanie, 25 marca 2025 🟢 — adres tokena solanowego i opłata za zarządzanie 20 bps

Źródła trzeciorzędne (🔴)

  • eco.com, deep dive'y BUIDL / OUSG / BENJI — parametry operacyjne i mechanika whitelisty; nie użyte do żadnej liczby dotyczącej uprawnień

Wszystkie części serii „RWA: Past, Present and Future” →