Skip to content

Latest commit

 

History

History
138 lines (109 loc) · 7.84 KB

04_OrnekUygulama.md

File metadata and controls

138 lines (109 loc) · 7.84 KB

Projenin amacı

kickstarter.com gibi centralized bir uygulamayı peer to peer hale getirerek decentralized bir uygulama haline dönüştürmeyi amaçlamaktır.

Yapılacaklar Listesi

  • Kontratımız deploy edilirken kontrat sahibini, deploy eden adres olarak belirlemek
  • Kontrat deploy edilirken projenin adını, açıklamasını ve minimum bağış miktarını belirlemek
  • Kaç kişinin bağış yaptığını görebilmek
  • Toplam bağış miktarını görebilmek
  • Projeye bağış yapabilmek
  • Verilen adresin bağış yapıp yapmadığını sorgulayabileceğimiz bir logic eklemek
  • Harcama isteği oluşturmak
  • Oluşturulan harcama isteğine, sadece bağışçıların oy verebilmesi için bir logic oluşturmak
  • Yeni oluşturulacak isteği sadece kontratı deploy eden adresin oluşturabilmesini sağlayacak kontrol mekanizması eklemek
  • Sadece bağış yapan kişilerin oy vermesini sağlayacak kontrol mekanizması eklemek
  • Eğer onay sayısı toplam bağışçı sayısının yarısı veya daha fazlası ise bu harcama isteğini kabul edecek fonksiyonu oluşturmak

Kaynak Kod

Projenin kaynak koduna examples/Campaign.sol adresinden erişebilirsiniz.

Campaign.sol

// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.0; // Hangi versiyonu kullandığımızı belirtiyoruz.

// Kontratımızı tanımlıyoruz
contract ProjectFunding{
        
    address public owner; // Projenin sahibinin adresini tutan değişken
    
    uint public minContribution; // Projenin minimum bağış miktarını tutan değişken
    string public name; // Projenin adını tutan değişken
    string public description; // Projenin açıklamasını tutan değişken
    uint public contribution = 0;     // Projenin toplam bağış miktarını tutan değişken
    uint public contributorCount = 0; // Projenin toplam bağış yapan yatırımcı sayısını tutan değişken
    mapping (address => bool) public contributor; // Projeye hangi adreslerin bağış yaptığını sorgulayabilmemiz için gerekli olan mapping    

    // Proje harcama isteklerinin bilgilerini tutacak olan struct
    struct Request{
        string description; // Harcama isteğinin açıklamasını tutan değişken
        uint value; // Harcama isteğinin miktarını tutan değişken
        address recipient; // Harcama isteğinin alıcısını tutan değişken
        bool completed; // Harcama isteğinin tamamlanıp tamamlanmadığını tutan değişken
        uint approversCount; // Harcama isteğinin onaylanma sayısını tutan değişken
        mapping(address => bool) approvers; // Harcama isteğini onaylayan ve onaylamayan yatırımcılarını tutan mapping
          
    }
    
    // Tüm harcama isteklerini tutacak olan array
    Request[] public requests;

    // Kontrat deploy edildiği anda çalışacak olan ve gerekli değerleri initialize edecek olan constructor
    constructor(uint _minContribution, string memory _name, string memory _description) {
        owner = msg.sender; // Proje sahibini kontratın kurucusu olarak atıyoruz
        name = _name; // Projenin adını atıyoruz
        description = _description; // Projenin açıklamasını atıyoruz
        minContribution = _minContribution; // Projenin minimum bağış miktarını atıyoruz
    }

    // Projenin sahibi olup olmadığını kontrol eden modifier  
    modifier onlyOwner(){
        require(owner == msg.sender,'You are not the owner!');
        _; // hangi fonksiyon çağırıyorsa o fonksiyondaki işleme devam et demektir.
    }
    
    // Projeye bağış yapılmasını sağlayacak olan fonksiyon
    function Contribute() public payable{
        require(msg.value >= minContribution,"You cannot send a value lover than minimum amount!");
                 
        // Toplam bağış miktarını arttırmak için contribution değişkenini kullanıyoruz 
        // ve her contribute fonksiyonu çağırıldığında yapılan bağış miktarını bir önceki değere ekliyoruz.
        contribution += msg.value;
        
        // Array kullanmak yerine, mapping kullanmak daha mantıklıdır.
        // Çünkü ilerde hangi bağışçının yatırım yapıp yapmadığını mapping ile daha kolay sorgulayabiliriz
        
        // Mappingde ilgili adresin value değerini true yapıyoruz. 
        // Bu sayede sadece addresi sorgulayarak bu adresin bağış yapıp yapmadığını söyleyebiliriz.
        // İlerleyen süreçte sadece bu mappingte true olan adreslerin harcama isteklerine onay vermesine izin verilecektir.
        contributor[msg.sender] = true;
      
        // TEğer aynı yatırımcı daha önce bağış yapmamışsa, toplam bağışçı sayısını 1 arttırıyoruz
        if (contributor[msg.sender] == true){
            contributorCount++;
        }
    }


    // Proje için gerekli olan harcama isteklerini açmak için kullanılacak olan fonksiyon
    // Bu fonksiyonu sadece kontratı deploy eden kişi çağırabilir. Bunu da onlyOwnner modifierı ile kontrol ediyoruz.
    function createRequest(string calldata _description, uint _value, address _recipient) public onlyOwner{
       // Yeni bir harcama isteği oluşturmak için, requests arrayının sonuna yeni bir eleman ekliyoruz.
       Request storage newReq = requests.push(); 

       // Yeni harcama isteği için gerekli olan değerleri initialize ediyoruz.
       newReq.description = _description; // Harcama isteğinin açıklamasını atıyoruz
       newReq.value = _value; // Harcama isteğinin miktarını atıyoruz
       newReq.recipient = _recipient; // Harcama isteğinin alıcısını atıyoruz
       newReq.completed = false; // Harcama isteğinin tamamlanıp tamamlanmadığını atıyoruz
    }  


    // Proje için gerekli olan harcama isteklerini onaylamak için kullanılacak olan fonksiyon
    function approveRequest (uint _index) public{
        // Bu fonksiyonu çağırabilmek için daha önce projeye bağış yapmış olmak gerekmektedir. Bunu da require modifier ile kontrol ediyoruz.
        require(contributor[msg.sender] == true,"You have to contribute first to approve a request");
        // Bu fonksiyonu çağırırken harcama isteği indexi gönderilmeli. Bu indexi kontrol ediyoruz.
        Request storage request = requests[_index];
        // İkinci require modifierı ise aynı bağışçının birden fazla onay vermesine izin verilmemesi için daha önce onaylama yapılıp yapılmadığını kontrol ediyor.
        require(request.approvers[msg.sender]==false,"Already approved");
        // Bu isteğe onay veren kullanıcının adresinin value değerini true yapıyoruz.
        request.approvers[msg.sender] = true;
        // Bu isteğe onay veren kullanıcı sayısını bir arttırıyoruz.
        request.approversCount ++;
    }

    // Proje için gerekli olan harcama isteklerini tamamlamak için kullanılacak olan fonksiyon
    // Bu fonksiyonu sadece kontratı deploy eden kişi çağırabilir. Bunu da onlyOwnner modifierı ile kontrol ediyoruz.
    function finalizeRequest(uint _index) public onlyOwner{
        // Bu fonksiyonu çağırırken harcama isteği indexi gönderilmeli. Bu indexi kontrol ediyoruz.
        Request storage finalRequest = requests[_index];
        // Bu isteğin tamamlanıp tamamlanmadığını kontrol ediyoruz.
        require(!finalRequest.completed,"Already completed");
        // Bu istek için gerekli olan onay sayısına ulaşılp ulaşılmadığını kontrol ediyoruz.
        require(finalRequest.approversCount > contributorCount/2,"Not enough approve");


        // Bu isteğin tamamlanması için gerekli olan değerleri initialize ediyoruz.
        finalRequest.completed = true;
        // Transfer fonksiyonu ile isteğin alıcısına harcama miktarını gönderiyoruz.
        payable(finalRequest.recipient).transfer(finalRequest.value);

    }

}