Merkeziyetsiz finans (DeFi) dünyasında, güvenli ve esnek bir bankacılık sistemi hayal edin. Solidity ile inşa edilen modüler bir akıllı banka, bu hayali gerçeğe dönüştürüyor. Bu makalede, Foundry ve arayüzler kullanarak nasıl kişiselleştirilebilir ‘Deposit Box’ sistemi kuracağınızı adım adım öğrenecek, akıllı sözleşme mimarisinin gücünü keşfedeceksiniz. Geleneksel bankacılık sistemlerinin karmaşıklığı ve tekil hata noktaları, merkeziyetsiz dünyaya adım atan kullanıcılar için ciddi endişeler yaratmaktadır. Monolitik, yani tek bir büyük sözleşmeden oluşan yapılar, geliştirme sürecini yavaşlatırken, güncellemeleri zorlaştırır ve güvenlik açıklarının kapsamını artırabilir. Bir akıllı banka sözleşmesi hayal ettiğinizde, kullanıcıların yatırımlarını yönettiği, faiz kazandığı, belki de kredi aldığı birçok farklı fonksiyonu içerecektir. Tüm bu fonksiyonları tek bir devasa akıllı sözleşmeye sığdırmak, kısa vadede pratik görünse de, uzun vadede sürdürülemez bir mimari oluşturur.
İşte tam bu noktada modüler mimari devreye giriyor. Modüler tasarım, büyük bir sistemi daha küçük, bağımsız ve yeniden kullanılabilir parçalara ayırır. Tıpkı bir LEGO setindeki gibi, her bir parça belirli bir işlevi yerine getirir ve gerektiğinde birleştirilerek daha karmaşık yapılar oluşturulabilir. Bir akıllı banka bağlamında, bu, mevduat kutularını (deposit boxes), faiz hesaplama modüllerini, KYC/AML bileşenlerini veya kredi mekanizmalarını ayrı ayrı akıllı sözleşmeler olarak tasarlamak anlamına gelebilir. Bu yaklaşım, sadece geliştirme sürecini hızlandırmakla kalmaz, aynı zamanda her bir modülün ayrı ayrı denetlenmesine ve test edilmesine olanak tanıyarak genel sistem güvenliğini artırır. Olası bir güvenlik açığı durumunda, etkilenen modülün kapsamı sınırlı kalır ve tüm sistemin çökme riski azalır. Dahası, yeni özellikler eklemek veya mevcut modülleri yükseltmek çok daha kolay hale gelir, çünkü sadece ilgili modül üzerinde değişiklik yapılması yeterlidir. Bu sayede, merkeziyetsiz finansın dinamik ve hızla gelişen doğasına ayak uydurabilecek esnek ve adapte olabilir bir yapı inşa etmiş oluruz. Böylece, kullanıcıların fonlarını daha güvenli ve şeffaf bir ortamda yönetebileceği, geleceğin bankacılık altyapısını kurmuş oluruz.
⚙️ Temel Kavramlar: Solidity Arayüzleri ve Foundry Geliştirme Ortamı Nedir?
Modüler bir akıllı banka inşa etme yolculuğumuzda iki kritik araca ihtiyacımız var: Solidity Arayüzleri ve Foundry geliştirme ortamı. Öncelikle, Solidity Arayüzleri (Interfaces), akıllı sözleşme dünyasındaki soyut sınıflara benzer bir işlev görür. Bir arayüz, belirli bir akıllı sözleşmenin hangi fonksiyonlara sahip olması gerektiğini ve bu fonksiyonların hangi argümanları alıp hangi değerleri döndürmesi gerektiğini tanımlar. Ancak, arayüzler bu fonksiyonların nasıl çalıştığını (implementasyonunu) içermez. Sadece “kontrat”ı belirler. Yani, bir akıllı sözleşmenin dış dünya ile nasıl etkileşime gireceğinin bir taslağıdır. Bu, özellikle büyük ve karmaşık sistemlerde, farklı akıllı sözleşmelerin birbirleriyle tutarlı bir şekilde konuşmasını sağlamak için hayati önem taşır. Bir IDepositBox arayüzü tanımladığımızda, bu arayüzü uygulayan her DepositBox sözleşmesinin aynı deposit(), withdraw() gibi fonksiyonlara sahip olacağını garanti ederiz. Bu, esneklik sağlarken aynı zamanda tip güvenliğini artırır ve sözleşmeler arası entegrasyonu kolaylaştırır. Kısacası, arayüzler, akıllı sözleşme mimarisinde bir API (Uygulama Programlama Arayüzü) görevi görerek bileşenler arası temiz ve anlaşılır bir iletişim köprüsü kurar.
Şimdi gelelim Foundry‘ye. Foundry, Ethereum sanal makinesi (EVM) uyumlu akıllı sözleşmeleri geliştirmek için tasarlanmış modern, hızlı ve Rust tabanlı bir geliştirme araç setidir. Daha önce Hardhat veya Truffle gibi JavaScript tabanlı araçları kullandıysanız, Foundry’nin geliştirme deneyimini ne kadar farklı ve verimli hale getirdiğini hemen fark edeceksiniz. Foundry’nin en belirgin avantajlarından biri, testlerinizi ve scriptlerinizi doğrudan Solidity’de yazabilmenizdir. Bu, bağlam değiştirme (context switching) ihtiyacını ortadan kaldırır ve geliştiricilerin daha hızlı prototipleme yapmasına olanak tanır. forge komut satırı aracı, derleme, test çalıştırma, dağıtım ve hatta akıllı sözleşmelerle etkileşim kurma gibi birçok işlevi tek bir yerden yönetmenizi sağlar. Özellikle, gelişmiş fuzz test yetenekleri sayesinde, akıllı sözleşmelerinizdeki olası güvenlik açıklarını çok daha etkin bir şekilde tespit edebilirsiniz. Foundry’nin düşük seviyeli EVM etkileşimi ve gaz optimizasyonuna verdiği önem, geliştiricilerin daha verimli ve güvenli sözleşmeler yazmasına yardımcı olur. Test odaklı geliştirme yaklaşımını benimseyen ve hızı, güvenliği ve verimliliği ön planda tutan projeler için Foundry, kesinlikle tercih edilmesi gereken bir araç setidir. Böylece, hem akıllı sözleşme mimarisini tasarlarken hem de bu mimariyi test edip dağıtırken güçlü bir omurgaya sahip oluruz.
🏗️ Akıllı Banka Mimarisi Nasıl Tasarlanır? Modüler Yaklaşım
Modüler bir akıllı banka tasarlarken, geleneksel bankacılık sistemlerindeki “müşteri hesabı” veya “kasa” kavramlarını blokzincir dünyasına nasıl uyarlayacağımızı düşünmeliyiz. Amacımız, her kullanıcının veya belirli bir amaca hizmet eden “para kutularını” temsil eden bağımsız, ancak ana banka sözleşmesi tarafından yönetilen ‘Deposit Box’ akıllı sözleşmeleri oluşturmaktır. Bu mimarinin kalbinde bir ana SmartBank sözleşmesi yer alacak. Bu SmartBank sözleşmesi, yeni DepositBox sözleşmelerini oluşturma, bunların adreslerini kaydetme ve gerektiğinde bu kutularla genel bir arayüz üzerinden etkileşim kurma yeteneğine sahip olacak. Her bir DepositBox ise, belirli bir kullanıcının veya bir grup kullanıcının varlıklarını saklayacak ve yalnızca tanımlanmış kurallar çerçevesinde (örneğin, yalnızca kutunun sahibi tarafından) para yatırma ve çekme işlemlerine izin verecektir. Bu yapı, hem güvenlik hem de esneklik açısından önemli avantajlar sunar. Örneğin, bir DepositBox sözleşmesinde bir hata bulunsa bile, bu hata yalnızca o kutuyu etkiler ve tüm banka sistemini tehlikeye atmaz. Ayrıca, farklı DepositBox türleri (örneğin, faiz kazandıran, kilitli mevduat, çoklu imzalı) kolayca eklenebilir veya güncellenebilir, çünkü hepsi aynı IDepositBox arayüzünü uyguladığı sürece, ana SmartBank sözleşmesi bunlarla uyumlu bir şekilde etkileşim kurabilir.
Bu mimariyi daha somut hale getirmek için, geleneksel bankacılıkta bir vaka analizi yapalım: Bir bankanın müşterilerine sunduğu farklı hesap türleri (vadesiz hesap, vadeli hesap, birikim hesabı) vardır. Her bir hesap türü farklı kurallara (faiz oranları, çekim kısıtlamaları vb.) sahiptir, ancak hepsi “hesap” kavramının genel özelliklerini taşır (para yatırma, çekme, bakiye sorgulama). Modüler akıllı bankamızda da durum benzerdir. IDepositBox arayüzü, tüm mevduat kutularının sahip olması gereken temel işlevleri tanımlar: para yatırma (deposit), para çekme (withdraw), bakiye sorgulama (getBalance) ve sahibini öğrenme (getOwner). Her bir DepositBox akıllı sözleşmesi ise bu arayüzü uygulayacak ve belirli bir mevduat kutusunun kendine özgü kurallarını ve mantığını içerecektir. Ana SmartBank sözleşmesi, kullanıcıların bu kutulara erişimi için bir “giriş noktası” görevi görecektir. Bir kullanıcı yeni bir mevduat kutusu açmak istediğinde, SmartBank sözleşmesi tarafından yeni bir DepositBox sözleşmesi oluşturulacak ve bu sözleşmenin adresi SmartBank içinde kaydedilecektir. Böylece, kullanıcılar ana SmartBank sözleşmesi üzerinden kendi özel DepositBoxlarına erişebilir ve işlemlerini gerçekleştirebilir. Bu katmanlı yapı, sistemin karmaşıklığını yönetilebilir parçalara ayırırken, aynı zamanda yükseltilebilirlik ve sürdürülebilirlik için sağlam bir temel oluşturur. Böylece, bir yandan şeffaf ve güvenli bir yapı sunarken, diğer yandan da gelecekteki değişikliklere ve yeni özelliklere kolayca adapte olabilen bir sistem kurmuş oluruz.
📝 Adım Adım Kodlama: Modüler DepositBox Arayüzü Nasıl Oluşturulur?
Modüler akıllı bankamızın ilk ve en temel yapı taşı, DepositBox sözleşmelerimizin uygulayacağı arayüzdür. Solidity’deki arayüzler, sözleşmelerin nasıl etkileşim kuracağını tanımlayan bir sözleşme taslağı gibidir, ancak herhangi bir uygulama mantığı içermezler. Bu, özellikle farklı türde mevduat kutuları oluşturmak istediğimizde veya gelecekte yeni mevduat kutusu tipleri eklemek istediğimizde bize büyük esneklik sağlar. Her mevduat kutusu, IDepositBox arayüzünü uyguladığı sürece, ana SmartBank sözleşmemiz veya diğer dış sözleşmeler, bu kutularla tutarlı bir şekilde etkileşime girebilir.
Aşağıda, IDepositBox.sol dosyamız için örnek bir arayüz tanımı bulunmaktadır. Bu arayüz, her mevduat kutusunun sahip olması gereken temel işlevleri (para yatırma, para çekme, bakiye sorgulama, sahibi öğrenme) açıkça belirtir:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
/// @title IDepositBox
/// @notice Bu arayüz, tüm DepositBox akıllı sözleşmeleri için standart bir etkileşim arayüzü tanımlar.
/// @dev Yeni DepositBox türleri oluşturulurken bu arayüzün uygulanması zorunludur.
interface IDepositBox {
/// @notice Mevduat kutusuna ETH yatırma işlemi yapar.
/// @dev Bu fonksiyon, mesajla birlikte gönderilen ETH'yi kabul eder.
function deposit() external payable;
/// @notice Mevduat kutusundan belirli bir miktarda ETH çekme işlemi yapar.
/// @param amount Çekilecek ETH miktarı (wei cinsinden).
/// @dev Sadece kutunun sahibi tarafından çağrılabilir ve çekilecek miktar bakiyeden az olmalıdır.
function withdraw(uint256 amount) external;
/// @notice Mevduat kutusunun mevcut bakiyesini döndürür.
/// @return Mevduat kutusundaki toplam ETH miktarı (wei cinsinden).
function getBalance() external view returns (uint256);
/// @notice Mevduat kutusunun sahibinin adresini döndürür.
/// @return Mevduat kutusunun sahibinin adresi.
function getOwner() external view returns (address);
// Eventler (isteğe bağlı, ancak iyi bir uygulamadır)
event Deposited(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
}
Yukarıdaki kod bloğunda gördüğünüz gibi, IDepositBox arayüzü içerisinde deposit, withdraw, getBalance ve getOwner olmak üzere dört adet fonksiyon tanımlanmıştır. Her bir fonksiyonun external veya view anahtar kelimeleriyle erişilebilirlik ve durum değiştirme yetenekleri belirtilmiştir. deposit() fonksiyonu payable olarak işaretlenmiştir, bu da o fonksiyona ETH gönderilebileceği anlamına gelir. withdraw() fonksiyonu bir amount parametresi alır ve bu miktarın çekilmesini sağlar. getBalance() ve getOwner() fonksiyonları ise sadece bilgi okuma amaçlıdır (view) ve akıllı sözleşmenin durumunu değiştirmezler. Ayrıca, işlem takibi için Deposited ve Withdrawn adında iki olay (event) tanımlanmıştır. Bu olaylar, zincir dışı uygulamaların (DApps) veya blokzincir kaşiflerinin (block explorers) sözleşmedeki değişiklikleri kolayca izlemesini sağlar, bu da denetlenebilirlik ve şeffaflık açısından önemlidir. Arayüzler, uygulama mantığını içermedikleri için, derlemeden sonra bytecode boyutları çok küçüktür ve gaz maliyeti açısından neredeyse sıfır etki yaratırlar. Ancak, kodun okunabilirliğini, bakımını ve ölçeklenebilirliğini inanılmaz derecede artırırlar. Bu sayede, farklı geliştiriciler farklı DepositBox uygulamaları üzerinde eş zamanlı çalışabilirken, ana SmartBank sözleşmesi sadece IDepositBox arayüzüne güvenerek tüm bu farklı kutularla sorunsuz bir şekilde etkileşim kurabilir. Bu, modern akıllı sözleşme mimarisinin temel taşlarından biridir ve güçlü, modüler bir sistem inşa etmek için vazgeçilmezdir.
IDepositBox(address_of_box).functionCall() gibi tip güvenli çağrılar yapmanızı sağlar.🔐 DepositBox Akıllı Sözleşmesi Nasıl Oluşturulur? Güvenlik Temelli Yaklaşım
Şimdi, IDepositBox arayüzümüzü uygulayan somut bir DepositBox akıllı sözleşmesi oluşturalım. Bu sözleşme, gerçek ETH mevduatlarını saklayacak ve yalnızca sahibinin belirli kurallar dahilinde işlem yapmasına izin verecektir. Güvenlik, bu tür finansal sözleşmelerde her zaman en üst önceliktir. Bu nedenle, olası yeniden giriş (reentrancy) saldırıları ve uygun erişim kontrolü gibi konulara dikkat etmemiz gerekmektedir.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import "./IDepositBox.sol"; // Oluşturduğumuz arayüzü içe aktarıyoruz
/// @title DepositBox
/// @notice Kullanıcıların ETH yatırıp çekebileceği kişiselleştirilmiş bir mevduat kutusu akıllı sözleşmesi.
/// @dev IDepositBox arayüzünü uygular ve temel güvenlik kontrollerini içerir.
contract DepositBox is IDepositBox {
address private immutable i_owner; // Kutunun sahibi, değiştirilemez
// Güvenlik için yeniden giriş kilidi
bool private locked;
modifier noReentrant() {
require(!locked, "ReentrancyGuard: reentrant call");
locked = true;
_;
locked = false;
}
/// @notice Sadece kutunun sahibinin fonksiyonu çağırmasına izin veren bir düzenleyici (modifier).
modifier onlyOwner() {
require(msg.sender == i_owner, "Not owner");
_;
}
/// @notice DepositBox sözleşmesini dağıtan adres olarak sahibini ayarlar.
constructor() {
i_owner = msg.sender;
locked = false; // Başlangıçta kilitli değil
}
/// @inheritdoc IDepositBox
function deposit() external payable override noReentrant {
require(msg.value > 0, "Deposit amount must be greater than zero");
// ETH doğrudan sözleşmeye gönderilir. Bakiyeyi izlemek için state variable'a gerek yok.
// address(this).balance doğrudan ETH bakiyesini döndürür.
emit Deposited(msg.sender, msg.value);
}
/// @inheritdoc IDepositBox
function withdraw(uint256 amount) external override onlyOwner noReentrant {
require(amount > 0, "Withdraw amount must be greater than zero");
require(address(this).balance >= amount, "Insufficient balance");
// Güvenli ETH transferi için call kullanılıyor ve hata kontrolü yapılıyor.
(bool success, ) = payable(i_owner).call{value: amount}("");
require(success, "Failed to withdraw Ether");
emit Withdrawn(msg.sender, amount);
}
/// @inheritdoc IDepositBox
function getBalance() external view override returns (uint256) {
return address(this).balance;
}
/// @inheritdoc IDepositBox
function getOwner() external view override returns (address) {
return i_owner;
}
// Geleneksel ETH gönderimlerini kabul etmek için (harici fonksiyon çağrısı olmadan)
receive() external payable {
// Bu fonksiyona doğrudan ETH gönderildiğinde hiçbir şey yapmaz, ancak ETH'yi kabul eder.
// Eğer belirli bir mantık eklemek istenirse buraya eklenebilir.
// Örneğin: emit DirectDeposit(msg.sender, msg.value);
}
}
Yukarıdaki DepositBox sözleşmesi, IDepositBox arayüzünü (is IDepositBox) uygulayarak tüm gerekli fonksiyonlara sahip olduğunu belirtir. Sözleşme, i_owner adında değiştirilemez (immutable) bir değişkene sahiptir ve bu, sözleşmeyi dağıtan adresi (yani msg.sender) kutunun sahibi olarak belirler. Bu immutable anahtar kelimesi, i_owner'ın yalnızca yapıcı (constructor) sırasında ayarlanabileceğini ve daha sonra değiştirilemeyeceğini garanti eder, bu da kritik bir güvenlik özelliğidir.
Güvenlik Odaklı Özellikler:
onlyOwnerModifier:withdrawfonksiyonunu sadecei_owner'ın çağırabilmesini sağlar. Bu, yetkilendirilmemiş çekim işlemlerini engeller.noReentrantModifier: Yeniden giriş saldırılarına karşı koruma sağlar.lockeddeğişkeni sayesinde, bir fonksiyon çağrıldığında kilitlenir ve aynı sözleşmeye yapılan başka bir çağrıya izin vermez, ta ki ilk çağrı tamamlanana kadar. Bu, özellikle fon transferi yapan fonksiyonlar için hayati öneme sahiptir.- Güvenli ETH Transferi:
withdrawfonksiyonundapayable(i_owner).call{value: amount}("")deseni kullanılmıştır. Bu, fonları doğrudantransfer()veyasend()ile göndermek yerine, düşük seviyelicallkullanarak olası gaz limit sorunlarından kaçınırken, aynı zamanda geri dönüş değerini kontrol ederek transferin başarılı olup olmadığını doğrulamamızı sağlar. Bu, Solidity'de önerilen en güvenli fon transfer yöntemlerinden biridir. receive()Fonksiyonu: Bu özel fonksiyon, bir kullanıcıDepositBoxsözleşme adresine doğrudan ETH gönderdiğinde (bir fonksiyonu çağırmadan) çalışır. Bu, sözleşmenin harici fonksiyon çağrısı olmadan da ETH kabul edebilmesini sağlar.
Bu DepositBox sözleşmesi, hem modüler mimarinin bir parçası olarak çalışabilecek şekilde tasarlanmış hem de finansal varlıkları yönettiği için temel güvenlik prensiplerine uygun olarak geliştirilmiştir. immutable değişken kullanımı, onlyOwner ve noReentrant modifiyerleri ile call tabanlı güvenli ETH transferi, bu sözleşmeyi sağlam ve güvenilir kılar. Böylece, kullanıcılar fonlarını güvende hissedebilir ve akıllı banka sistemimiz sağlam bir temel üzerinde yükselir.
🏛️ Ana Akıllı Banka Sözleşmesi: Yönetim ve Etkileşim Nasıl Sağlanır?
DepositBox sözleşmelerimizi oluşturduktan sonra, sıra tüm bu modüler parçaları bir araya getirecek ve yönetilebilir bir bütün haline getirecek olan ana SmartBank sözleşmesine geldi. Bu sözleşme, kullanıcıların yeni DepositBox'lar oluşturmasını sağlayacak, mevcut kutularına erişimini kolaylaştıracak ve genel bankacılık operasyonlarını yönetecek bir merkez görevi görecektir. Ana sözleşmemiz, IDepositBox arayüzü sayesinde farklı türdeki DepositBox implementasyonlarıyla sorunsuz bir şekilde etkileşim kurabilecektir. Bu, modüler mimarinin gücünü ve esnekliğini gösteren kilit bir noktadır.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import "./IDepositBox.sol"; // IDepositBox arayüzümüzü import ediyoruz
import "./DepositBox.sol"; // DepositBox implementasyonumuzu import ediyoruz
/// @title SmartBank
/// @notice Kullanıcılar için modüler DepositBox'ları oluşturan ve yöneten ana akıllı banka sözleşmesi.
/// @dev Yeni DepositBox'lar oluşturulur ve adresleri eşleme (mapping) ile saklanır.
contract SmartBank {
address public owner; // SmartBank'ın yöneticisi
mapping(address => address[]) public userDepositBoxes; // Kullanıcı adresine göre DepositBox adreslerini saklar
mapping(address => address) public depositBoxToOwner; // DepositBox adresine göre sahibini saklar
event DepositBoxCreated(address indexed user, address indexed depositBoxAddress);
event FundsDeposited(address indexed depositBoxAddress, address indexed user, uint256 amount);
event FundsWithdrawn(address indexed depositBoxAddress, address indexed user, uint256 amount);
/// @notice SmartBank sözleşmesini dağıtan adres olarak yöneticiyi ayarlar.
constructor() {
owner = msg.sender;
}
/// @notice Yeni bir DepositBox akıllı sözleşmesi oluşturur ve mevcut kullanıcıya atar.
/// @dev msg.sender otomatik olarak yeni kutunun sahibi olur.
/// @return Yeni oluşturulan DepositBox'ın adresi.
function createDepositBox() external returns (address) {
DepositBox newBox = new DepositBox(); // Yeni DepositBox örneğini dağıtıyoruz
userDepositBoxes[msg.sender].push(address(newBox)); // Kullanıcının kutularına ekliyoruz
depositBoxToOwner[address(newBox)] = msg.sender; // Kutunun sahibini kaydediyoruz
emit DepositBoxCreated(msg.sender, address(newBox));
return address(newBox);
}
/// @notice Belirli bir kullanıcının tüm DepositBox adreslerini döndürür.
/// @param user DepositBox'ların sahibi olan kullanıcının adresi.
/// @return Kullanıcının sahip olduğu tüm DepositBox adreslerinin bir dizisi.
function getDepositBoxesForUser(address user) external view returns (address[] memory) {
return userDepositBoxes[user];
}
/// @notice Belirli bir DepositBox'ın sahibini döndürür.
/// @param depositBoxAddress Sahibi sorgulanacak DepositBox'ın adresi.
/// @return DepositBox'ın sahibinin adresi.
function getDepositBoxOwner(address depositBoxAddress) external view returns (address) {
return depositBoxToOwner[depositBoxAddress];
}
/// @notice Bir kullanıcının kendi DepositBox'larından birine ETH yatırmasını sağlar.
/// @param depositBoxAddress Fon yatırılacak DepositBox'ın adresi.
/// @dev Yalnızca kutunun sahibi çağırabilir.
function depositIntoBox(address depositBoxAddress) external payable {
require(depositBoxToOwner[depositBoxAddress] == msg.sender, "Not your deposit box");
require(msg.value > 0, "Deposit amount must be greater than zero");
IDepositBox(depositBoxAddress).deposit{value: msg.value}(); // Arayüz üzerinden çağrı
emit FundsDeposited(depositBoxAddress, msg.sender, msg.value);
}
/// @notice Bir kullanıcının kendi DepositBox'larından birinden ETH çekmesini sağlar.
/// @param depositBoxAddress Fon çekilecek DepositBox'ın adresi.
/// @param amount Çekilecek ETH miktarı (wei cinsinden).
/// @dev Yalnızca kutunun sahibi çağırabilir.
function withdrawFromBox(address depositBoxAddress, uint256 amount) external {
require(depositBoxToOwner[depositBoxAddress] == msg.sender, "Not your deposit box");
require(amount > 0, "Withdraw amount must be greater than zero");
IDepositBox(depositBoxAddress).withdraw(amount); // Arayüz üzerinden çağrı
emit FundsWithdrawn(depositBoxAddress, msg.sender, amount);
}
/// @notice Belirli bir DepositBox'ın bakiyesini döndürür.
/// @param depositBoxAddress Bakiyesi sorgulanacak DepositBox'ın adresi.
/// @return DepositBox'ın mevcut bakiyesi (wei cinsinden).
function getDepositBoxBalance(address depositBoxAddress) external view returns (uint256) {
require(depositBoxToOwner[depositBoxAddress] == msg.sender, "Not your deposit box");
return IDepositBox(depositBoxAddress).getBalance(); // Arayüz üzerinden çağrı
}
}
Yukarıdaki SmartBank sözleşmesi, IDepositBox arayüzünü ve DepositBox implementasyonunu içe aktarır. İşte ana fonksiyonları ve işlevleri:
owner:SmartBanksözleşmesini dağıtan adresin yöneticisi olur. Gelişmiş versiyonlarda bu rol için daha sofistike erişim kontrolü (örneğin, çoklu imza cüzdanı veya DAO) kullanılabilir.userDepositBoxes(mapping): Her kullanıcının (adresi) sahip olduğu tümDepositBoxsözleşmelerinin adreslerini tutan bir eşlemedir. Bir kullanıcı birden fazla mevduat kutusuna sahip olabilir.depositBoxToOwner(mapping): Belirli birDepositBoxadresinin hangi kullanıcıya ait olduğunu tutan bir eşlemedir. Bu,depositIntoBoxvewithdrawFromBoxgibi fonksiyonlarda yetkilendirme kontrolü için kullanılır.createDepositBox(): Bir kullanıcı bu fonksiyonu çağırdığında, yeni birDepositBoxsözleşmesi dağıtılır (new DepositBox()). Yeni kutunun adresi,msg.sender'ınuserDepositBoxeslistesine eklenir vedepositBoxToOwnereşlemesine kaydedilir. Bu, kişiselleştirilmiş ve modüler bir hesap yapısı oluşturmanın temelini oluşturur.depositIntoBox()vewithdrawFromBox(): Bu fonksiyonlar, kullanıcıların belirli birDepositBox'a ETH yatırmasını veya çekmesini sağlar. Önemli olan nokta,IDepositBox(depositBoxAddress).deposit{value: msg.value}()gibi çağrılarla,SmartBank'ınDepositBoxsözleşmeleriyleIDepositBoxarayüzü üzerinden etkileşim kurmasıdır. Bu,SmartBank'ın yalnızcaDepositBox'ın arayüzünü bilmesini ve onun dahili implementasyon detaylarıyla ilgilenmemesini sağlar, bu da gerçek modülerliktir.- Erişim Kontrolü:
depositIntoBoxvewithdrawFromBoxfonksiyonları, kullanıcının işlem yapmak istediğiDepositBox'ın gerçekten kendisine ait olup olmadığınıdepositBoxToOwnereşlemesini kullanarak kontrol eder (require(depositBoxToOwner[depositBoxAddress] == msg.sender, "Not your deposit box")). Bu kritik güvenlik kontrolü, bir kullanıcının başka bir kullanıcının mevduat kutusuna yetkisiz erişimini engeller.
Bu SmartBank sözleşmesi, merkezi bir yönetim noktası olarak görev yaparken, gerçek fon yönetimi işlevlerini ayrı DepositBox sözleşmelerine devrederek sistemin modülerliğini ve güvenliğini artırır. Bu yaklaşım, karmaşık finansal protokollerin geliştirilmesinde yaygın olarak kullanılan bir desendir ve gelecekteki değişikliklere daha kolay adapte olabilen bir mimari sunar.
SmartBank hem de DepositBox sözleşmeleri yükseltilebilir hale gelir. Bu, özellikle uzun ömürlü ve sürekli gelişen DApp'ler için vazgeçilmez bir stratejidir, çünkü akıllı sözleşmeler dağıtıldıktan sonra varsayılan olarak değiştirilemezler. Proxy'ler, sözleşmelerin mantığının (implementation) güncellenmesine olanak tanırken, kullanıcıların bakiyelerinin ve etkileşim geçmişlerinin değişmeden kalmasını sağlar.🧪 Foundry ile Akıllı Banka Test ve Geliştirme Nasıl Yapılır?
Akıllı sözleşmelerde güvenlik ve doğruluk hayati öneme sahip olduğundan, sağlam bir test süreci olmazsa olmazdır. Foundry, hızlı derleme, test çalıştırma ve gelişmiş hata ayıklama yetenekleri sayesinde bu süreci önemli ölçüde kolaylaştırır. Foundry ile testlerimizi doğrudan Solidity dilinde yazabilmemiz, geliştirme deneyimini bir üst seviyeye taşır. Şimdi, bu modüler akıllı banka sistemimizi Foundry kullanarak nasıl test edeceğimize bir göz atalım.
İlk adım olarak, yeni bir Foundry projesi başlatmamız gerekir:
forge init smart-bank-project
cd smart-bank-project
Bu komutlar bize temel bir proje yapısı sağlayacaktır: src/ (sözleşmelerimiz için), script/ (dağıtım betikleri için) ve test/ (testlerimiz için). Sözleşmelerimizi src/ klasörüne yerleştirdikten sonra, test/ klasöründe SmartBank.t.sol adında bir test dosyası oluşturacağız.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import "forge-std/Test.sol";
import "../src/SmartBank.sol";
import "../src/IDepositBox.sol";
/// @title SmartBankTest
/// @notice SmartBank ve DepositBox akıllı sözleşmelerini test eden bir Foundry test sözleşmesi.
contract SmartBankTest is Test {
SmartBank public smartBank;
address public ALICE = makeAddr("alice");
address public BOB = makeAddr("bob");
/// @notice Her test çalıştırılmadan önce çağrılır. Test ortamını hazırlar.
function setUp() public {
smartBank = new SmartBank();
}
/// @notice Yeni bir DepositBox oluşturma işlevini test eder.
function testCreateDepositBox() public {
vm.prank(ALICE); // Alice'in işlemleri yapmasını sağlıyoruz
address aliceBox = smartBank.createDepositBox();
assertNotEq(aliceBox, address(0), "Deposit box address should not be zero");
assertEq(smartBank.getDepositBoxesForUser(ALICE)[0], aliceBox, "Alice's box should be registered");
assertEq(smartBank.getDepositBoxOwner(aliceBox), ALICE, "Alice should be the owner of the box");
IDepositBox box = IDepositBox(aliceBox);
assertEq(box.getOwner(), ALICE, "IDepositBox owner should match Alice");
}
/// @notice DepositBox'a para yatırma işlevini test eder.
function testDepositIntoBox() public {
vm.prank(ALICE);
address aliceBox = smartBank.createDepositBox();
uint256 depositAmount = 1 ether;
vm.deal(ALICE, depositAmount); // Alice'e test ETH'si yüklüyoruz
vm.prank(ALICE);
smartBank.depositIntoBox{value: depositAmount}(aliceBox);
IDepositBox box = IDepositBox(aliceBox);
assertEq(box.getBalance(), depositAmount, "Deposit box balance should match deposit amount");
assertEq(address(aliceBox).balance, depositAmount, "Actual box balance should match deposit amount");
}
/// @notice DepositBox'tan para çekme işlevini test eder.
function testWithdrawFromBox() public {
vm.prank(ALICE);
address aliceBox = smartBank.createDepositBox();
uint256 depositAmount = 2 ether;
vm.deal(ALICE, depositAmount);
vm.prank(ALICE);
smartBank.depositIntoBox{value: depositAmount}(aliceBox);
uint256 withdrawAmount = 1 ether;
vm.prank(ALICE);
smartBank.withdrawFromBox(aliceBox, withdrawAmount);
IDepositBox box = IDepositBox(aliceBox);
assertEq(box.getBalance(), depositAmount - withdrawAmount, "Remaining balance should be correct");
assertEq(address(aliceBox).balance, depositAmount - withdrawAmount, "Actual box balance should be correct");
}
/// @notice Yetkisiz bir kullanıcının (Bob) Alice'in DepositBox'ından çekim yapmasını engellemeyi test eder.
function testUnauthorizedWithdrawFails() public {
vm.prank(ALICE);
address aliceBox = smartBank.createDepositBox();
uint256 depositAmount = 1 ether;
vm.deal(ALICE, depositAmount);
vm.prank(ALICE);
smartBank.depositIntoBox{value: depositAmount}(aliceBox);
vm.prank(BOB); // Bob olarak işlem yapmaya çalışıyoruz
vm.expectRevert("Not your deposit box"); // Bu hatayı bekliyoruz
smartBank.withdrawFromBox(aliceBox, 0.5 ether);
}
/// @notice ReentrancyGuard'ın DepositBox'taki işlevselliğini test eder.
/// @dev Bu test, aslında bir reentrancy saldırısını taklit etmez, sadece modifiyerin varlığını ve işlevini doğrular.
/// @dev Gerçek bir reentrancy testi için ayrı bir saldırı sözleşmesi yazmak gerekir.
function testReentrancyGuardInDepositBox() public {
vm.prank(ALICE);
address aliceBox = smartBank.createDepositBox();
uint256 depositAmount = 1 ether;
vm.deal(ALICE, depositAmount);
// İlk yatırma işlemi başarılı olmalı
vm.prank(ALICE);
smartBank.depositIntoBox{value: depositAmount}(aliceBox);
// Şimdi aynı fonksiyona ardışık çağrı yapmaya çalışalım (gerçek bir reentrancy olmasa da)
// Eğer reentrancy koruması olmasaydı bu hata vermezdi (sadece tek bir tx contextinde)
// vm.startPrank(ALICE);
// IDepositBox(aliceBox).deposit{value: 1 wei}(); // Bu tek bir işlemde başarısız olur
// vm.stopPrank();
// Daha somut bir reentrancy testi için, saldırgan bir sözleşme yazmak ve bu kutuya saldırmak gerekir.
// Ancak burada, DepositBox'ın kendi içindeki noReentrant modifier'ının çalıştığını,
// örneğin withdraw çağrılırken içerde tekrar bir işlem yapılırsa bunu engelleyeceğini varsayıyoruz.
// Basit bir assert ile DepositBox'ın sahibi doğru ayarlandı mı kontrol edelim
IDepositBox box = IDepositBox(aliceBox);
assertEq(box.getOwner(), ALICE, "DepositBox owner should be Alice");
}
}
Yukarıdaki test sözleşmesinde (SmartBankTest):
import "forge-std/Test.sol";: Foundry'nin test kütüphanesini içe aktarıyoruz. Bu, testlerimizde kullanabileceğimiz bir dizi faydalı fonksiyon ve iddia (assertion) mekanizması sağlar.setUp(): Her test fonksiyonundan önce otomatik olarak çalıştırılır. Bu fonksiyonda,SmartBanksözleşmemizi dağıtarak test ortamımızı hazırlarız.makeAddr("alice")vemakeAddr("bob"): Foundry'ninTest.solkütüphanesinden gelen bu fonksiyonlar, kolayca test adresleri oluşturmamızı sağlar.vm.prank(ALICE): Foundry'nin sanal makine (VM) hilelerini (vm.*) kullanarak, sonraki işlem çağrısınınALICEadresi tarafından yapılmış gibi görünmesini sağlarız. Bu, farklı kullanıcı senaryolarını test etmek için kritik bir özelliktir.vm.deal(ALICE, amount): Bir adrese belirli miktarda ETH yüklememizi sağlar. Test senaryolarında ETH'ye ihtiyaç duyduğumuzda bunu kullanırız.assertEq(),assertNotEq(): Beklenen değerlerle gerçek değerleri karşılaştırmak için kullanılan iddia fonksiyonlarıdır. Bir iddia başarısız olursa, test de başarısız olur.vm.expectRevert("Not your deposit box"): Bu, belirli bir işlemde beklenen bir hatanın (revert mesajı) meydana gelip gelmediğini kontrol etmek için kullanılır. Örneğin, yetkisiz bir çekim girişiminde beklenen hata mesajının doğru olup olmadığını doğrularız.
Bu testler, SmartBank'ın yeni DepositBox'ları doğru şekilde oluşturduğunu, fonları doğru bir şekilde yatırıp çektiğini ve yetkisiz erişimi engellediğini doğrular. Foundry'nin sunduğu bu güçlü test yetenekleri, akıllı sözleşme geliştiricilerine büyük bir güven sağlar ve hataları erkenden tespit etmelerine yardımcı olur. Testleri çalıştırmak için tek yapmanız gereken komut satırında forge test yazmaktır. Foundry ayrıca forge test --gas-report ile gaz kullanım raporları, forge coverage ile kod kapsamı raporları ve forge fuzz ile rastgele veri girişleriyle sözleşmelerinizi test etme gibi gelişmiş özellikler de sunar. Bu özellikler, özellikle karmaşık ve yüksek değerli protokollerde sözleşme güvenliğini artırmak için hayati öneme sahiptir. Foundry'nin hızlı geri bildirim döngüsü ve yerel Solidity test yetenekleri sayesinde, test odaklı geliştirme (TDD) yaklaşımını benimsemek çok daha kolay ve verimli hale gelir, bu da daha sağlam ve güvenilir akıllı sözleşmelerle sonuçlanır.
📱 Mobil Uyumlu Kullanıcı Arayüzü İçin CSS İpuçları
Akıllı banka sözleşmemizi Solidity ve Foundry ile başarıyla geliştirdik, ancak kullanıcıların bu bankayla etkileşime girebilmesi için bir kullanıcı arayüzüne (UI) ihtiyacımız var. Web3 uygulamalarında (DApps) kullanıcı deneyimi, özellikle mobil cihazlarda, kritik öneme sahiptir. Mobil uyumlu bir arayüz, kullanıcıların herhangi bir cihazdan sorunsuz bir şekilde erişim sağlamasına ve işlemlerini kolayca gerçekleştirmesine olanak tanır. İşte basit bir mobil uyumlu HTML/CSS yapısı için ipuçları:
Akıllı Banka DApp
Akıllı Banka Kontrol Paneli
Cüzdanınızı bağlayın ve modüler bankacılık deneyimine başlayın.
Yeni Deposit Box Oluştur
Oluşturulan Adres: YOK
Mevcut Deposit Box'lar
Deposit Box İşlemleri
Bakiye: 0 ETH
Yukarıdaki HTML ve CSS örneği, responsive tasarım için temel bir viewport meta etiketi ve @media sorguları kullanır. İşte dikkat etmeniz gerekenler:
: Bu etiket, tarayıcıya sayfanın cihazın genişliğine göre ölçeklenmesini söyler ve mobil cihazlarda sayfanın doğru görüntülenmesini sağlar.- Flexbox veya Grid: Daha karmaşık düzenler için Flexbox veya CSS Grid kullanmak, responsive tasarımı çok daha kolay hale getirir. Bu örnekte basit bir tek sütun düzeni kullanılmıştır.
- Relative Uzunluk Birimleri:
width: calc(100% - 22px)gibi değerler, öğelerin ekran boyutuna göre ayarlanmasını sağlar.remveyaemgibi birimler de font boyutları için faydalıdır. @mediaSorguları: Farklı ekran boyutları için farklı CSS kuralları tanımlamanızı sağlar. Bu örnekte,768pxve480pxaltındaki ekranlar için stil değişiklikleri yapılmıştır (örneğin, daha küçük iç boşluklar, butonların tam genişliği kaplaması).- Minimum Hedef Boyutları: Dokunmatik cihazlarda düğmelerin ve bağlantıların kolayca tıklanabilmesi için yeterince büyük olduğundan emin olun (genellikle en az 44x44 piksel).
Bu temel mobil uyumlu tasarım prensipleriyle, kullanıcılar akıllı banka DApp'inizle herhangi bir cihazdan sorunsuz bir şekilde etkileşim kurabilirler. Ön yüz geliştirmesinde Web3.js veya Ethers.js kütüphanelerini kullanarak Metamask gibi cüzdanlar aracılığıyla akıllı sözleşmelerinizle bağlantı kurabilirsiniz. Bu sayede, hem güçlü bir arka uca hem de kullanıcı dostu bir ön yüze sahip, eksiksiz bir merkeziyetsiz bankacılık çözümü sunabilirsiniz.
🚀 Gelişmiş Konular ve Optimizasyon Stratejileri: Akıllı Bankanızı İleriye Taşıyın
Modüler akıllı banka projemizin temelini attık, ancak Web3 dünyasında rekabetçi ve sürdürülebilir bir DApp inşa etmek için göz önünde bulundurmamız gereken birçok gelişmiş konu ve optimizasyon stratejisi bulunmaktadır. Gaz maliyetleri, ölçeklenebilirlik, yükseltilebilirlik ve genel güvenlik, her akıllı sözleşme geliştiricisinin üzerinde durması gereken temel alanlardır. İşte akıllı bankanızı bir sonraki seviyeye taşıyacak bazı stratejiler:
-
Gaz Optimizasyonları
Ethereum ağındaki her işlem bir gaz maliyetine sahiptir ve bu maliyetler ağ yoğunluğuna göre değişebilir. Kullanıcılar için makul maliyetli bir deneyim sunmak adına gaz optimizasyonu kritik öneme sahiptir.
- Depolama Kullanımı (Storage vs Memory):
storagedeğişkenleri, blokzincir üzerinde kalıcı olarak saklandığı içinmemoryveyacalldatadeğişkenlerinden çok daha pahalıdır. Mümkün olduğuncamemoryveyacalldatakullanmaya çalışın, özellikle fonksiyon parametreleri ve geçici değişkenler için. - Döngü Optimizasyonları: Büyük diziler üzerinde döngülerden kaçının veya maliyetli işlemleri bu döngülerin dışına taşıyın. Zincir üstünde döngülerin tahmin edilemez gaz maliyetleri, özellikle kullanıcı tarafından kontrol edilebilen dizilerde DoS (Hizmet Reddi) saldırılarına yol açabilir. Eğer bir döngü kaçınılmazsa, sabit bir üst sınıra sahip olduğundan emin olun.
- Event Kullanımı: Verileri doğrudan
storage'da saklamak yerine, önemli olaylarıeventolarak yaymak, gaz maliyetini önemli ölçüde azaltır.event'ler, zincir dışı uygulamalar tarafından kolayca indekslenebilir ve sorgulanabilir, böylece kullanıcı arayüzlerinde veya arka uç servislerinde veri takibi için kullanılabilir. - Kısa Devre Değerlendirme (Short-Circuit Evaluation):
requireifadelerinde birden fazla koşulu&&ile birleştirirken, daha az maliyetli koşulları öne koyun. Bu, ilk koşul yanlışsa, daha maliyetli ikinci koşulun değerlendirilmesini engelleyerek gaz tasarrufu sağlar. - Sıfır Değer Atamaları: Bir
storagedeğişkenini sıfıra ayarlamak, onu sıfır olmayan bir değere ayarlamaktan daha az gaz maliyetlidir. Bu, özellikle bir sözleşme değişkenini temizlerken veya bir haritadan girişi silerken önemlidir.
- Depolama Kullanımı (Storage vs Memory):
-
Erişim Kontrolü ve Role Tabanlı Sistemler
Akıllı bankanızda, farklı kullanıcıların farklı yetkilere sahip olması gerekebilir (örneğin, yönetici, müşteri, denetçi). OpenZeppelin Contracts kütüphanesi,
OwnableveAccessControlgibi güçlü erişim kontrolü mekanizmaları sunar.AccessControlmodülü, daha granüler yetkilendirmeler için role tabanlı bir sistem kurmanıza olanak tanır. Örneğin, bir "minter" rolü yalnızca yeni token basabilirken, bir "pauser" rolü sözleşmeyi dondurabilir. -
Yükseltilebilirlik (Upgradability)
Dağıtılan akıllı sözleşmeler varsayılan olarak değiştirilemezdir. Ancak, bir hatayı düzeltmek, yeni bir özellik eklemek veya güvenlik açıklarını kapatmak için sözleşme mantığını güncellemek gerekebilir. Bu noktada proxy desenleri (örneğin, UUPS - Universal Upgradeable Proxies Standard veya Transparent Proxy Standard) devreye girer. Bu desenler, kullanıcıların sözleşmeyle aynı adreste etkileşim kurmaya devam etmesini sağlarken, arka plandaki implementasyon sözleşmesinin değiştirilmesine olanak tanır. Bu sayede kullanıcı fonlarının güvenliği ve sözleşmenin sürekliliği sağlanır.
-
Cross-Chain İmplikasyonları ve Genişleme
Ethereum dışında Polygon, Arbitrum, Optimism gibi diğer EVM uyumlu blokzincirlerinde de akıllı bankanızı dağıtmayı düşünebilirsiniz. Bu, daha düşük işlem ücretleri ve daha hızlı işlem süreleri sunarak daha geniş bir kullanıcı kitlesine ulaşmanızı sağlayabilir. Cross-chain iletişimi (örneğin, LayerZero, Wormhole) entegre ederek, farklı zincirler arasında fon transferini ve etkileşimi kolaylaştırabilirsiniz. Bu, Web3 finansın geleceğinde önemli bir trenddir ve akıllı bankanızın potansiyelini artıracaktır.
-
Güvenlik Denetimleri (Audits)
Kodunuz ne kadar iyi yazılmış ve test edilmiş olursa olsun, bir üçüncü taraf güvenlik denetimi (audit) yaptırmak her zaman tavsiye edilir. Denetçiler, geliştiricilerin gözden kaçırabileceği potansiyel zayıflıkları ve güvenlik açıklarını tespit etmede uzmandırlar. Bu, özellikle yüksek değerli varlıkları içeren finansal protokoller için vazgeçilmezdir. Güvenlik, akıllı sözleşme geliştirmesinde tek seferlik bir çaba değil, sürekli bir süreçtir.
Bu ileri düzey konuları ve optimizasyon stratejilerini uygulayarak, sadece çalışan bir akıllı banka değil, aynı zamanda sağlam, verimli, güvenli ve geleceğe hazır bir merkeziyetsiz finansal platform inşa edersiniz. Bu, Web3 ekosistemine değerli bir katkı sağlayacak ve kullanıcılar için daha iyi bir deneyim sunacaktır.
💡 Sonuç: Geleceğin Modüler Finansı ve Sıkça Sorulan Sorular
Bugünün makalesinde, Solidity ile modüler bir akıllı banka sistemi inşa etmenin inceliklerini derinlemesine inceledik. Arayüzlerin gücünü kullanarak nasıl esnek ve ölçeklenebilir bir mimari oluşturabileceğimizi, Foundry geliştirme ortamının sunduğu hız ve verimlilikle nasıl testler yapabileceğimizi adım adım gördük. IDepositBox arayüzü ile standart bir etkileşim katmanı tanımlarken, DepositBox sözleşmesiyle kullanıcıya özel, güvenli mevduat kutularını nasıl oluşturduğumuzu detaylandırdık. Son olarak, tüm bu modüler parçaları bir araya getiren ana SmartBank sözleşmemizi inceleyerek, merkeziyetsiz bankacılığın temelini atmış olduk.
Modüler tasarım yaklaşımı, tek bir büyük ve hantal sözleşme yerine, bağımsız ve yeniden kullanılabilir bileşenler oluşturarak geliştirme sürecini basitleştirir, test edilebilirliği artırır ve gelecekteki güncellemeleri kolaylaştırır. Foundry'nin Solidity tabanlı testleri, geliştiricilere hızlı geri bildirim döngüsü ve üstün hata ayıklama yetenekleri sunarak daha güvenli sözleşmeler yazmalarına yardımcı olur. Bir akıllı bankanın inşası, sadece kod yazmaktan ibaret değildir; aynı zamanda güvenlik, verimlilik ve kullanıcı deneyimi gibi birçok faktörü dengede tutmayı gerektirir. Bu rehberde paylaştığımız bilgiler ve kod örnekleri, Web3 finansın geleceğine adım atmak isteyen herkes için sağlam bir temel oluşturmaktadır. Merkeziyetsiz finansın potansiyeli sınırsızdır ve modüler mimariler, bu potansiyeli gerçekleştirmek için bize gereken araçları sunar. Umarız bu makale, kendi yenilikçi DeFi çözümlerinizi oluşturmanız için size ilham vermiştir.
❓ Sıkça Sorulan Sorular
-
Modüler tasarım neden önemlidir?
Modüler tasarım, akıllı sözleşmelerinizi daha küçük, yönetilebilir ve bağımsız parçalara ayırmanızı sağlar. Bu, kodu daha okunabilir, bakımı daha kolay ve yeniden kullanılabilir hale getirir. Ayrıca, güvenlik açıklarının kapsamını sınırlar ve yeni özelliklerin eklenmesini veya mevcut özelliklerin güncellenmesini basitleştirir, böylece projenizin uzun vadeli sürdürülebilirliğini artırır.
-
Foundry kullanmak ne gibi avantajlar sağlar?
Foundry, testleri ve scriptleri doğrudan Solidity'de yazmanıza olanak tanıyan, Rust tabanlı, hızlı bir EVM geliştirme aracıdır. Bu, geliştirme hızını artırır, bağlam değiştirme ihtiyacını ortadan kaldırır ve gaz optimizasyonu, fuzz testing gibi gelişmiş özelliklerle daha güvenli ve verimli sözleşmeler yazmanızı sağlar.
forge testgibi komutlarla kolayca test çalıştırabilirsiniz. -
Bir akıllı banka sözleşmesi ne kadar güvenli olabilir?
Bir akıllı banka sözleşmesinin güvenliği, kullanılan kod kalitesine, uygulanan güvenlik desenlerine (örneğin, yeniden giriş koruması, erişim kontrolü), kapsamlı testlere ve profesyonel güvenlik denetimlerine bağlıdır. Modüler yapı, güvenlik açıklarının etkisini sınırlamaya yardımcı olurken, hiçbir sözleşme %100 risksiz değildir. İyi uygulamalar ve sürekli denetim, güvenliği en üst düzeye çıkarır.
-
Bu mimari yükseltilebilir mi?
Evet, bu tür modüler bir mimariyi yükseltilebilir hale getirmek mümkündür. Proxy desenlerini (örneğin, UUPS veya Transparent Proxy) kullanarak,
SmartBankveDepositBoxsözleşmelerinizin mantığını dağıtıldıktan sonra dahi güncelleyebilirsiniz. Bu, kullanıcıların aynı sözleşme adresleriyle etkileşime devam etmesini sağlarken, yeni özellikler eklemenize veya hataları düzeltmenize olanak tanır. -
Gaz maliyetleri nasıl optimize edilir?
Gaz maliyetlerini optimize etmek için
storageyerinememoryveyacalldatakullanmaya özen gösterin, büyük döngülerden kaçının,event'leri veri depolama yerine izleme için kullanın, kısa devre değerlendirme prensiplerini uygulayın ve gereksiz hesaplamalardan kaçının. Foundry'nin gaz raporlama araçları, iyileştirme alanlarını belirlemenize yardımcı olabilir.
