135.002 智能合約設計-——多員工薪酬系統

@(135- Block Chain| 區塊鏈)c++

Introduciton

可調整地址和薪水的單員工系統數組

  • address neo -> address employee
  • funtion updateEmployee

Goal——多員工系統
Solution—— 數組+結構體安全

  • Employee[] employees
  • funtion addEmployee
  • funtion removeEmployee

1 錯誤檢測

代碼風格——方便簡潔less

  • assert(bool) //程序運行時——確認ide

  • require(bool)//程序輸入時——要求區塊鏈

    require(msg.sender == owner);
      // if(msg.sender != employee){//瞭解調用者信息
      //     revert();
      // }
      assert(nextPayday < now);
      // if( nextPayday > now){
      //     revert();

2 Data Location | Solidity數據存儲

  • storage
    永久存儲在區塊鏈上
  • memory

臨時空間,在function結束後釋放ui

  • calldata
    與memory相似

2.1強制類型

狀態變量:storage
function 輸入變量:calldatathis

2.2 默認類型

function 返回類型:memory
本地變量:storagecode

2.3 變量本質

類比c++的地址
指向 EVM中的一塊內存區域內存

2.4 規則

  • 相同的存儲空間變量賦值
    • 傳遞reference(EVM上的內存地址)
  • 不一樣存儲空間變量賦值
    • 拷貝

3 Code in Remix (Solidity IDE)

pragma solidity ^0.4.0;

contract Payroll{
    
    
    struct Employee{
        address id;
        uint salary;
        uint lastPayday;
    }
    
    
  // uint constant payDuration = 30 days;
   uint constant payDuration = 10 seconds;//for test:10 seconds
   
   address owner;
   Employee[] employees;//dynamic array 
     function Payroll(){//construction function
    
    owner = msg.sender;
        
    }
    function _partialPaid(Employee employee) private{
            uint payment = employee.salary * (now - employee.lastPayday) /payDuration;//if exist , calculate payment注意整除
            employee.id.transfer(payment);
    }
    
    function _findEmloyee(address employeeId) private returns (Employee,uint){//Encapsulation 封裝 
        for (uint i=0;i<employees.length;i++)//avoid needless duplication (repeat)
        {
            if (employees[i].id == employeeId){
                return (employees[i],i);
            } 
        }
    
    }
    function addEmployee(address employeeId,uint salary){
        require(msg.sender == owner);//whether is onwner

        var (employee,index ) = _findEmloyee(employeeId); //var - any type
        assert(employee.id == 0x0);//confirm that exist
        
        employees.push(Employee(employeeId,salary,now));
    }
    
    function removeEmployee(address employeeId){
         require(msg.sender == owner);//whether is onwner
         var (employee,index) = _findEmloyee(employeeId); 
         assert(employee.id != 0x0);//confirm that exist
        _partialPaid(employees[index]);
        delete employees[index];//left with a blank in the array,wasteful
        employees[index] = employees[employees.length - 1];//fill the blank
        employees.length -= 1;
      

    
}
    
    function updateEmployee(address employeeId,uint salary) {
        require(msg.sender == owner);
        //Equivalently 等效 
        // if (msg.sender != owner){//avoid employee cheating
        //     revert();
        // }
        
         var (employee,index) = _findEmloyee(employeeId); 
         assert(employee.id != 0x0);//confirm that exist
        _partialPaid(employee);
        employees[index].salary = salary;
        employees[index].lastPayday = now;     
         

    }
    
    function addFund() payable returns(uint){
        return this.balance;//address.balance
    }
    
    
    function calculateRunway()returns(uint)
    { //how many times to pay
        uint totalSalary = 0;
        for (uint i=0;i<employees.length;i++)
         {
             totalSalary += employees[i].salary; 
         } 

        return this.balance / totalSalary; 
    }
    function hasEnoughFund() returns(bool){
        // return this.balance >=salary;
        //return this.calculateRunway() > 0; //this方法 使用的gas 較多,不推薦
        return calculateRunway() > 0; //vm jump 操做,使用gas較少,推薦
    }
    function getPaid (){
         var (employee,index) = _findEmloyee(msg.sender); 
         assert(employee.id != 0x0);//confirm that exist
        uint nextPayday = employee.lastPayday + payDuration;
         //每一次運算都是真金白銀~
         //原則:不重複運算!——省gas
        assert(nextPayday < now);
        // if( nextPayday > now){
        //     revert();
              //throw or revert
            //throw: 全部的gas 均會被消耗殆盡
            //revert:回滾,return沒有消耗的gas
           
        // }
        
            employees[index].lastPayday = nextPayday;//原則:先修改內部變量,再給錢——》以後會講,安全問題
            employee.id.transfer(employee.salary);

    }
}

參考閱讀:老董-以太坊智能合約全棧開發

相關文章
相關標籤/搜索