Dalam dunia kripto, satu klik yang salah dapat memicu “bencana digital”. Salah satu mimpi buruk yang paling umum adalah mengirim aset ke blockchain yang salah. Misalnya, awalnya ingin mengirim ETH ke alamat di jaringan testnet Sepolia Ethereum, tetapi tanpa sengaja mengirimnya ke alamat di jaringan utama Ethereum. Dalam situasi ini, apakah masih memungkinkan untuk menarik kembali dana yang salah transfer dari jaringan utama Ethereum? Apakah aset tersebut bisa dipulihkan, tergantung pada jenis alamat penerima. Artikel ini akan menganalisis berdasarkan berbagai situasi.
1. Skenario 1: Alamat penerima adalah EOA
EOA (Externally Owned Account) adalah dompet biasa yang kita sebutkan, yang dikendalikan langsung oleh kunci pribadi atau frase mnemonic.
Prasyarat untuk memulihkan aset:
Anda telah mentransfer aset ke alamat EOA.
Anda memiliki kunci pribadi atau frase mnemonic dari alamat EOA target tersebut. (Biasanya merupakan alamat dompet Anda sendiri, atau alamat teman yang bersedia bekerja sama).
Chain target adalah chain yang kompatibel dengan EVM.
Cara memulihkan aset:
Pemilik kunci pribadi dari alamat EOA penerima dapat langsung menarik dana di chain target.
2. Skenario 2: Alamat penerima adalah kontrak
Ini adalah salah satu skenario paling putus asa. Karena alamat kontrak pintar tidak dihasilkan oleh kunci pribadi, tidak ada yang memiliki kunci pribadi kontrak pintar tersebut, sehingga tidak bisa mengendalikan kontrak seperti mengendalikan EOA. Jika kontrak tersebut tidak memiliki fungsi penanganan “transfer salah” yang sudah diprogram sebelumnya, maka dana yang salah transfer bisa terkunci secara permanen di kontrak, dan tidak bisa diambil kembali.
Namun, dalam beberapa kasus, masih ada peluang. Berikut ini, kita akan membangun skenario di mana ETH terkunci di jaringan utama Ethereum, lalu menjelaskan bagaimana cara menyelamatkan dana tersebut.
2.1. Penjelasan Skenario
Secara ringkas, skenario ini adalah pengguna awalnya ingin memanggil kontrak di testnet Sepolia, mentransfer ETH ke kontrak tersebut untuk melakukan mint token, tetapi saat melakukan transaksi, secara tidak sengaja terhubung ke jaringan utama, sehingga ETH terkunci di kontrak di jaringan utama. Rincian prosesnya sebagai berikut:
1.Di jaringan testnet Sepolia Ethereum, pihak proyek (EOA) telah men-deploy kontrak implementasi, misalnya kontrak tersebut berfungsi utama untuk menerima ETH dari pengguna dan melakukan mint AToken, dengan kode utama seperti fungsi mintTokens. Alamat deploy-nya adalah A. Perlu dicatat bahwa, di A tidak ada fungsi yang bisa langsung menarik ETH.
2.Di jaringan testnet Sepolia Ethereum, pihak proyek (EOA) juga telah men-deploy kontrak pabrik (factory contract), yang berfungsi untuk, berdasarkan alamat kontrak implementasi dan salt, melakukan deploy kontrak proxy minimal (Clones) yang menunjuk ke kontrak implementasi tersebut (seperti fungsi deployProxyByImplementation). Alamat deploy-nya adalah B. Di sini, kita menggunakan fungsi deployProxyByImplementation untuk meng-deploy kontrak proxy yang menunjuk ke kontrak A, dengan alamat C.
3.Pengguna ingin melakukan mint AToken di testnet Sepolia dengan mentransfer ETH ke kontrak proxy C, sehingga pengguna memanggil kontrak proxy C. Secara normal, kontrak proxy C akan memanggil fungsi mintTokens di kontrak implementasi A untuk menyelesaikan transaksi. Tetapi, saat pengguna melakukan panggilan, mereka secara tidak sengaja terhubung ke jaringan utama Ethereum. Akibatnya, ETH langsung dikirim ke alamat C di jaringan utama. Saat ini, di alamat C jaringan utama, tidak ada kontrak yang ter-deploy, dan tidak ada yang memiliki kunci pribadi alamat C tersebut, sehingga dana pengguna saat ini terkunci di alamat C jaringan utama.
2.2. Poin Kunci
Sebelum memperkenalkan solusi penyelamatan secara spesifik, mari kita bahas poin-poin dasar yang diperlukan untuk melakukan penyelamatan.
2.2.1. create & create2
create dan create2 adalah dua metode umum untuk men-deploy kontrak di Solidity.
create saat men-deploy kontrak, alamat kontrak ditentukan oleh alamat pengirim transaksi dan nonce dari pengirim tersebut, tanpa bergantung pada isi kontrak.
create2 saat men-deploy kontrak, alamat kontrak dihitung berdasarkan empat parameter berikut, dan tidak bergantung pada nonce pengirim:
0xff
Alamat kontrak yang akan dibuat (address))
Nilai salt yang digunakan sebagai parameter (salt)
Minimal proxy contract, juga dikenal sebagai kontrak klon (Clones), adalah metode untuk men-deploy kontrak proxy dengan biaya gas yang sangat rendah, yang menunjuk ke kontrak implementasi tertentu. Dalam kontrak Clones, dapat digunakan fungsi create atau create2 untuk men-deploy kontrak proxy, misalnya melalui fungsi cloneDeterministic yang menggunakan create2.
Dalam fungsi cloneDeterministic, bytecode kontrak proxy yang dibuat sangat singkat, formatnya adalah: 0x363d3d373d3d3d363d735af43d82803e903d91602b57fd5bf3, yang secara langsung meng-hardcode alamat kontrak implementasi ke bytecode, dan semua panggilan ke kontrak proxy akan delegatecall ke kontrak implementasi tersebut.
Dari fungsi cloneDeterministic, terlihat bahwa kontrak proxy yang dibuat menggunakan metode create2, dan alamat kontrak proxy yang dibuat bergantung pada alamat pembuat kontrak, salt, dan alamat kontrak implementasi, tetapi tidak bergantung pada bytecode kontrak implementasi.
2.3. Solusi Penyelamatan
Selanjutnya, kita akan bahas bagaimana menyelamatkan ETH di alamat C di jaringan utama. Ide utamanya adalah, di alamat C jaringan utama, kita men-deploy kode kontrak yang akan mengambil alih alamat tersebut dan mengekstrak ETH yang terkunci. Langkah-langkahnya sebagai berikut:
1. Men-deploy kontrak pabrik di jaringan utama dengan alamat yang sama dengan alamat B di testnet. Alasan harus menggunakan alamat kontrak pabrik yang sama adalah karena saat melakukan panggilan ke fungsi cloneDeterministic untuk men-deploy kontrak proxy, alamat kontrak proxy dihitung berdasarkan alamat kontrak pabrik. Dengan melihat transaksi deploy kontrak pabrik di testnet Sepolia, kita dapat memperoleh nonce dari deployer (alamat pihak proyek). Di jaringan utama, kita tingkatkan nonce dari alamat deployer ke nonce sebelum transaksi deploy kontrak pabrik di testnet, sehingga saat men-deploy kontrak pabrik di jaringan utama, alamatnya juga akan sama dengan B.
2. Men-deploy kontrak implementasi di jaringan utama dengan alamat yang sama dengan A di testnet. Dalam bagian #最小代理合约(Clones)#, disebutkan bahwa fungsi cloneDeterministic dari kontrak Clones digunakan untuk men-deploy kontrak proxy, dan alamat proxy bergantung pada salt dan alamat kontrak implementasi, tetapi tidak bergantung pada bytecode kontrak implementasi. Jadi, kita cukup men-deploy kontrak di alamat A yang sama, tanpa perlu memperhatikan isi kontrak tersebut, karena itu tidak mempengaruhi perhitungan alamat proxy. Kita bisa men-deploy kontrak yang memiliki fungsi untuk menarik ETH di alamat A, seperti kode berikut.
Di testnet, kontrak A di-deploy oleh pihak proyek (EOA), sehingga alamat kontrak A hanya bergantung pada transaksi pengirim dan nonce-nya. Oleh karena itu, dengan melihat transaksi deploy kontrak A di testnet dan menemukan nonce terkait, kita dapat meningkatkan nonce dari alamat EOA di jaringan utama ke nonce yang sama, lalu men-deploy kontrak A di jaringan utama.
3. Men-deploy kontrak proxy di alamat C di jaringan utama, sama seperti di testnet. Dengan melihat transaksi deploy kontrak proxy C di testnet, kita dapat memperoleh salt, lalu memanggil fungsi deployProxyByImplementation dari kontrak pabrik B, dengan parameter alamat kontrak A dan salt, sehingga kontrak proxy di alamat C di jaringan utama akan ter-deploy.
4. Memanggil kontrak proxy C di jaringan utama untuk melakukan penarikan ETH. Pihak proyek (EOA) memanggil fungsi withdraw dari kontrak proxy C, dan menentukan penerima dana, sehingga ETH yang terkunci di kontrak proxy C dapat diambil dan dikembalikan ke pengguna terkait.
2.4. Ringkasan
Dari solusi penyelamatan di atas, dapat dilihat bahwa dana dapat diselamatkan jika memenuhi beberapa kondisi, seperti deployer kontrak di chain target belum menggunakan nonce tertentu, kontrak yang mengunci dana memiliki fungsi penarikan, atau dapat melakukan deploy kontrak yang memiliki fungsi penarikan (misalnya kontrak yang dapat diupgrade atau menggunakan proxy seperti Clones).
Oleh karena itu, saat melakukan transaksi, sangat penting untuk berhati-hati dan memeriksa setiap transaksi secara teliti. Sebelum berinteraksi dengan kontrak, Anda juga dapat menggunakan alat pemindaian kerentanan AI SCAN yang disediakan ZAN untuk memeriksa keamanan kontrak. Jika secara tidak sengaja dana terkunci, jangan panik, Anda dapat menghubungi tim audit keamanan kontrak ZAN untuk membantu proses penyelamatan dana.
Artikel ini ditulis oleh ZANTeam (@zan_team) & AntChain OpenLabs (@AntChainOpenLab) bersama Cara (@Cara6289).
Halaman ini mungkin berisi konten pihak ketiga, yang disediakan untuk tujuan informasi saja (bukan pernyataan/jaminan) dan tidak boleh dianggap sebagai dukungan terhadap pandangannya oleh Gate, atau sebagai nasihat keuangan atau profesional. Lihat Penafian untuk detailnya.
Seri Keamanan Web3: Apakah Dana yang Salah Transfer ke Chain Lain Masih Bisa Diselamatkan?
Dalam dunia kripto, satu klik yang salah dapat memicu “bencana digital”. Salah satu mimpi buruk yang paling umum adalah mengirim aset ke blockchain yang salah. Misalnya, awalnya ingin mengirim ETH ke alamat di jaringan testnet Sepolia Ethereum, tetapi tanpa sengaja mengirimnya ke alamat di jaringan utama Ethereum. Dalam situasi ini, apakah masih memungkinkan untuk menarik kembali dana yang salah transfer dari jaringan utama Ethereum? Apakah aset tersebut bisa dipulihkan, tergantung pada jenis alamat penerima. Artikel ini akan menganalisis berdasarkan berbagai situasi.
1. Skenario 1: Alamat penerima adalah EOA
EOA (Externally Owned Account) adalah dompet biasa yang kita sebutkan, yang dikendalikan langsung oleh kunci pribadi atau frase mnemonic.
Prasyarat untuk memulihkan aset:
Cara memulihkan aset:
Pemilik kunci pribadi dari alamat EOA penerima dapat langsung menarik dana di chain target.
2. Skenario 2: Alamat penerima adalah kontrak
Ini adalah salah satu skenario paling putus asa. Karena alamat kontrak pintar tidak dihasilkan oleh kunci pribadi, tidak ada yang memiliki kunci pribadi kontrak pintar tersebut, sehingga tidak bisa mengendalikan kontrak seperti mengendalikan EOA. Jika kontrak tersebut tidak memiliki fungsi penanganan “transfer salah” yang sudah diprogram sebelumnya, maka dana yang salah transfer bisa terkunci secara permanen di kontrak, dan tidak bisa diambil kembali.
Namun, dalam beberapa kasus, masih ada peluang. Berikut ini, kita akan membangun skenario di mana ETH terkunci di jaringan utama Ethereum, lalu menjelaskan bagaimana cara menyelamatkan dana tersebut.
2.1. Penjelasan Skenario
Secara ringkas, skenario ini adalah pengguna awalnya ingin memanggil kontrak di testnet Sepolia, mentransfer ETH ke kontrak tersebut untuk melakukan mint token, tetapi saat melakukan transaksi, secara tidak sengaja terhubung ke jaringan utama, sehingga ETH terkunci di kontrak di jaringan utama. Rincian prosesnya sebagai berikut:
1. Di jaringan testnet Sepolia Ethereum, pihak proyek (EOA) telah men-deploy kontrak implementasi, misalnya kontrak tersebut berfungsi utama untuk menerima ETH dari pengguna dan melakukan mint AToken, dengan kode utama seperti fungsi mintTokens. Alamat deploy-nya adalah A. Perlu dicatat bahwa, di A tidak ada fungsi yang bisa langsung menarik ETH.
2. Di jaringan testnet Sepolia Ethereum, pihak proyek (EOA) juga telah men-deploy kontrak pabrik (factory contract), yang berfungsi untuk, berdasarkan alamat kontrak implementasi dan salt, melakukan deploy kontrak proxy minimal (Clones) yang menunjuk ke kontrak implementasi tersebut (seperti fungsi deployProxyByImplementation). Alamat deploy-nya adalah B. Di sini, kita menggunakan fungsi deployProxyByImplementation untuk meng-deploy kontrak proxy yang menunjuk ke kontrak A, dengan alamat C.
3. Pengguna ingin melakukan mint AToken di testnet Sepolia dengan mentransfer ETH ke kontrak proxy C, sehingga pengguna memanggil kontrak proxy C. Secara normal, kontrak proxy C akan memanggil fungsi mintTokens di kontrak implementasi A untuk menyelesaikan transaksi. Tetapi, saat pengguna melakukan panggilan, mereka secara tidak sengaja terhubung ke jaringan utama Ethereum. Akibatnya, ETH langsung dikirim ke alamat C di jaringan utama. Saat ini, di alamat C jaringan utama, tidak ada kontrak yang ter-deploy, dan tidak ada yang memiliki kunci pribadi alamat C tersebut, sehingga dana pengguna saat ini terkunci di alamat C jaringan utama.
2.2. Poin Kunci
Sebelum memperkenalkan solusi penyelamatan secara spesifik, mari kita bahas poin-poin dasar yang diperlukan untuk melakukan penyelamatan.
2.2.1. create & create2
create dan create2 adalah dua metode umum untuk men-deploy kontrak di Solidity.
create saat men-deploy kontrak, alamat kontrak ditentukan oleh alamat pengirim transaksi dan nonce dari pengirim tersebut, tanpa bergantung pada isi kontrak.
create2 saat men-deploy kontrak, alamat kontrak dihitung berdasarkan empat parameter berikut, dan tidak bergantung pada nonce pengirim:
2.2.2. Minimal Proxy Contract (Clones)
Minimal proxy contract, juga dikenal sebagai kontrak klon (Clones), adalah metode untuk men-deploy kontrak proxy dengan biaya gas yang sangat rendah, yang menunjuk ke kontrak implementasi tertentu. Dalam kontrak Clones, dapat digunakan fungsi create atau create2 untuk men-deploy kontrak proxy, misalnya melalui fungsi cloneDeterministic yang menggunakan create2.
Dalam fungsi cloneDeterministic, bytecode kontrak proxy yang dibuat sangat singkat, formatnya adalah: 0x363d3d373d3d3d363d735af43d82803e903d91602b57fd5bf3, yang secara langsung meng-hardcode alamat kontrak implementasi ke bytecode, dan semua panggilan ke kontrak proxy akan delegatecall ke kontrak implementasi tersebut.
Dari fungsi cloneDeterministic, terlihat bahwa kontrak proxy yang dibuat menggunakan metode create2, dan alamat kontrak proxy yang dibuat bergantung pada alamat pembuat kontrak, salt, dan alamat kontrak implementasi, tetapi tidak bergantung pada bytecode kontrak implementasi.
2.3. Solusi Penyelamatan
Selanjutnya, kita akan bahas bagaimana menyelamatkan ETH di alamat C di jaringan utama. Ide utamanya adalah, di alamat C jaringan utama, kita men-deploy kode kontrak yang akan mengambil alih alamat tersebut dan mengekstrak ETH yang terkunci. Langkah-langkahnya sebagai berikut:
1. Men-deploy kontrak pabrik di jaringan utama dengan alamat yang sama dengan alamat B di testnet. Alasan harus menggunakan alamat kontrak pabrik yang sama adalah karena saat melakukan panggilan ke fungsi cloneDeterministic untuk men-deploy kontrak proxy, alamat kontrak proxy dihitung berdasarkan alamat kontrak pabrik. Dengan melihat transaksi deploy kontrak pabrik di testnet Sepolia, kita dapat memperoleh nonce dari deployer (alamat pihak proyek). Di jaringan utama, kita tingkatkan nonce dari alamat deployer ke nonce sebelum transaksi deploy kontrak pabrik di testnet, sehingga saat men-deploy kontrak pabrik di jaringan utama, alamatnya juga akan sama dengan B.
2. Men-deploy kontrak implementasi di jaringan utama dengan alamat yang sama dengan A di testnet. Dalam bagian #最小代理合约(Clones)#, disebutkan bahwa fungsi cloneDeterministic dari kontrak Clones digunakan untuk men-deploy kontrak proxy, dan alamat proxy bergantung pada salt dan alamat kontrak implementasi, tetapi tidak bergantung pada bytecode kontrak implementasi. Jadi, kita cukup men-deploy kontrak di alamat A yang sama, tanpa perlu memperhatikan isi kontrak tersebut, karena itu tidak mempengaruhi perhitungan alamat proxy. Kita bisa men-deploy kontrak yang memiliki fungsi untuk menarik ETH di alamat A, seperti kode berikut.
Di testnet, kontrak A di-deploy oleh pihak proyek (EOA), sehingga alamat kontrak A hanya bergantung pada transaksi pengirim dan nonce-nya. Oleh karena itu, dengan melihat transaksi deploy kontrak A di testnet dan menemukan nonce terkait, kita dapat meningkatkan nonce dari alamat EOA di jaringan utama ke nonce yang sama, lalu men-deploy kontrak A di jaringan utama.
3. Men-deploy kontrak proxy di alamat C di jaringan utama, sama seperti di testnet. Dengan melihat transaksi deploy kontrak proxy C di testnet, kita dapat memperoleh salt, lalu memanggil fungsi deployProxyByImplementation dari kontrak pabrik B, dengan parameter alamat kontrak A dan salt, sehingga kontrak proxy di alamat C di jaringan utama akan ter-deploy.
4. Memanggil kontrak proxy C di jaringan utama untuk melakukan penarikan ETH. Pihak proyek (EOA) memanggil fungsi withdraw dari kontrak proxy C, dan menentukan penerima dana, sehingga ETH yang terkunci di kontrak proxy C dapat diambil dan dikembalikan ke pengguna terkait.
2.4. Ringkasan
Dari solusi penyelamatan di atas, dapat dilihat bahwa dana dapat diselamatkan jika memenuhi beberapa kondisi, seperti deployer kontrak di chain target belum menggunakan nonce tertentu, kontrak yang mengunci dana memiliki fungsi penarikan, atau dapat melakukan deploy kontrak yang memiliki fungsi penarikan (misalnya kontrak yang dapat diupgrade atau menggunakan proxy seperti Clones).
Oleh karena itu, saat melakukan transaksi, sangat penting untuk berhati-hati dan memeriksa setiap transaksi secara teliti. Sebelum berinteraksi dengan kontrak, Anda juga dapat menggunakan alat pemindaian kerentanan AI SCAN yang disediakan ZAN untuk memeriksa keamanan kontrak. Jika secara tidak sengaja dana terkunci, jangan panik, Anda dapat menghubungi tim audit keamanan kontrak ZAN untuk membantu proses penyelamatan dana.
Artikel ini ditulis oleh ZANTeam (@zan_team) & AntChain OpenLabs (@AntChainOpenLab) bersama Cara (@Cara6289).