【DAPP開發(fā)三】發(fā)布合約及實踐

4.1.1 語法介紹 block/msg/now

  • block 在調(diào)用某個方法的時候,solidity 會提供一個block 的變量,把當(dāng)前塊的信息返回。
    block.blockhash(uint blockNumber) returns (bytes32) 給定塊的哈希 - 僅適用于256個不包括當(dāng)前最新塊
    block.coinbase (address) 當(dāng)前塊礦工地址
    block.difficulty (uint) 當(dāng)前塊難度
    block.gaslimit (uint) 當(dāng)前塊gaslimit
    block.number (uint) 當(dāng)前數(shù)據(jù)塊號
    block.timestamp (uint) 當(dāng)前塊時間戳從unix紀(jì)元開始為秒
  • msg 在調(diào)用某個方法的時候,會給方法傳遞一個msg的屬性,用來傳遞消息
    msg.data (bytes) 完整的 calldata
    msg.gas (uint) 剩余gas
    msg.sender (address) 該消息(當(dāng)前呼叫)的發(fā)送者
    msg.sig (bytes4) 呼叫數(shù)據(jù)的前四個字節(jié)(即功能標(biāo)識符)
    msg.value (uint) 發(fā)送的消息的數(shù)量
  • now (uint) 當(dāng)前塊時間戳(block.timestamp的別名)

4.1.2 存儲 storage / memory

Storage 變量是指永久存儲在區(qū)塊鏈中的變量。 Memory 變量則是臨時的,當(dāng)外部函數(shù)對某合約調(diào)用完成時,
內(nèi)存型變量即被移除。 你可以把它想象成存儲在你電腦的硬盤或是RAM中數(shù)據(jù)的關(guān)系。大多數(shù)時候你都用不到這
些關(guān)鍵字,默認(rèn)情況下 Solidity 會自動處理它。 狀態(tài)變量(在函數(shù)之外聲明的變量)默認(rèn)為“存儲”形式,
并永久寫入?yún)^(qū)塊鏈;而在函數(shù)內(nèi)部聲明的變量是“內(nèi)存”型的,它們函數(shù)調(diào)用結(jié)束后消失。  

4.1.3 隨機(jī)數(shù)

生成一個0-100 之間的隨機(jī)數(shù)

function randomUtils() public view returns(uint) {
      //定義數(shù)字。
      uint random=1;
      //基于數(shù)字的基礎(chǔ)上生成隨機(jī)數(shù).
      //keccak256 生成數(shù).
      return uint(keccak256(now,msg.sender,random)) % 100;
}

4.1.4 require 關(guān)鍵字

     require(keccak256(_name) == keccak256("Vitalik"));
     require使得函數(shù)在執(zhí)行過程中,當(dāng)不滿足某些條件時拋出錯誤,并停止執(zhí)行:
     用來比較兩個字符串是否相等.
     function equals(string str, string str1) public pure returns (bool) {
          return (keccak256(str) == keccak256(str1));
    }

4.1.5 modify


pragma solidity^0.4.19;
contract ModifyContract {
     address owner;  
     //定義占位符,可以把需要判斷的條件共性的地方進(jìn)行抽取。          
     modifier onlyOwner() {
            require(owner == msg.sender);
            _;      
     }
     //在調(diào)用方法之前會先進(jìn)行檢查.
     function getRightToVote() public  onlyOwner {

     }
}

4.2發(fā)布合約

使用 Remix IDE,寫入代碼后,選擇 solc 版本,再進(jìn)行編譯。然后到 Run Tab頁,選擇好 環(huán)境,賬戶 等信息,設(shè)置 Gas Limit (一般 Remix 會自動設(shè)置一個值),點擊 Create 發(fā)布合約。發(fā)布合約需要花費(fèi) Gas。
合約發(fā)布之后,用戶可以點擊合約函數(shù),執(zhí)行函數(shù)。有一些函數(shù)需要 Gas,而有一些函數(shù)則不需要 Gas。

4.5調(diào)試

進(jìn)入 Debugger Tab 頁,可以進(jìn)行調(diào)試。

5 solidity 急行軍

案例1 轉(zhuǎn)賬給智能合約賬戶

當(dāng)一個智能合約運(yùn)行時,它運(yùn)行在以太坊上,任何人都可以調(diào)用函數(shù),向智能合約轉(zhuǎn)錢

pragma solidity^0.4.24;
contract Money {
     function Money(){
     }
     //向智能合約賬戶轉(zhuǎn)錢
     function paymoney () payable public{    
     }  
     function getBalance() public view returns (uint) {
            return address(this).balance;
     }   
}

案例2 從智能合約賬戶取錢

這個例子,展示如何從智能合約賬戶取錢,在這個例子里,取錢沒有任何條件,
只要合約賬戶中有錢,就可以取出這部分錢來

pragma solidity^0.4.19;

contract GetMoney {
      //合約發(fā)布者
      address owner;
      //發(fā)布合約的時候會調(diào)用構(gòu)造函數(shù).
      function GetMoney() public {
           owner = msg.sender;
      }
      //向合約賬戶轉(zhuǎn)錢。
      function payMoney() payable public {

      }
      //查看智能合約賬戶的余額  
      function getBalance() public view returns(uint) {
             return address(this).balance;
      }
      //誰調(diào)用就往誰的賬戶打錢。從智能轉(zhuǎn)化里面轉(zhuǎn)錢.
      function getMoney() public {
            address who = msg.sender;
            if(getBalance() > 2 ether) {
                 who.transfer(2 ether);
            }
      }
      //銷毀合約.
      function kill() public {
           //判斷操作,如果合約的發(fā)布者是調(diào)用著,則有權(quán)限銷毀合約.
           if(owner ==  msg.sender) {
                 selfdestruct(msg.sender);
           }
      }              
}

案例3 土豪發(fā)紅包

```JavaScript
pragma solidity^0.4.19;

contract RedPacket {
     //設(shè)置土豪.
     address tuhao;
     //初始化紅包的個數(shù).
     int number;
     //初始化相關(guān)數(shù)據(jù).
     function RedPacket(int _number) public payable{
          tuhao = msg.sender;
          number = _number;
     }
     //獲取合約的余額.
     function getBalance() public view returns(uint){
           return address(this).balance;  
     }
     //搶紅包
     function stakeMoney() public payable returns(bool) {
           address who = msg.sender;
           if(number > 0) {
               number --;
                uint random = uint(keccak256(now,msg.sender,10)) % 100;
               uint balance = getBalance();
               who.transfer(balance * random / 100);
               return true;
           }
           return false;
     }
     //destory contract
     function kill() public {
          if(tuhao == msg.sender) {
                selfdestruct(tuhao);
          }
     }
}
```

案例4 博彩賭大小.

pragma solidity^0.4.19;

contract Bet {

     address owner; //contract manager

     struct Player {
          address addr;
          uint money;
     }

     Player [] inbig;
     Player [] insmall;

     uint blockNumber;
     uint totalBig;
     uint totalSmall;

     function Bet() public {
          owner = msg.sender;
          blockNumber = block.number;
          totalBig = 0;
          totalSmall = 0;
     }

     function getBalance() public view returns(uint) {
          return address(this).balance;
     }

     function getBlockNumber() public view returns(uint,uint){
           return (blockNumber,block.number);
     }

     //押注 大小.
     function stake(bool flag) public view returns (bool){
           //先結(jié)構(gòu)化玩家.
           Player memory player  = Player(msg.sender,msg.value);
           //玩家是否帶錢過來.  
           if(player.money > 0){
                return false;
           }
           //押注大的
           if(flag){
                 inbig.push(player);
                 totalBig +=player.money;
           }else{ //押注小的.
                 insmall.push(player);
                 totalSmall +=player.money;
           }
           return true;
     }

     //開獎。
     function open()  payable public  returns (bool) {
            //設(shè)置開獎限制,必須最少得有兩個人押注.
            if(block.number < 2+blockNumber) {
                return false;
            }
            //押注大大金額以及押注小大金額大比例。
            if(totalSmall == 0 && totalBig == 0){
                return false;
            }
            //計算開大開小的規(guī)則,根據(jù)當(dāng)前塊的hash 值去定.
            uint hash =  uint(block.blockhash(block.number));
            uint points = hash % 18;     
            uint i=0;    
            uint count;  
            Player memory player;
            if(points>9) {  // big winer
                  count=inbig.length;
                  for(i=0;i<count;i++){
                         player = inbig[I];
                         player.addr.transfer(player.money+totalSmall*player.money/totalBig);
                  }
            }else { // small winer
                  count = insmall.length;
                  for(i=0;i<count;i++){
                       player = insmall[I];
                       player.addr.transfer(player.money+totalBig*player.money/totalSmall);
                  }
            }
            return true;
     }
     //銷毀合約
     function kill() public {
          if(msg.sender == owner){
              selfdestruct(owner);
          }
     }
}

案例5 社區(qū)投票

需求:
投票,委托代理人投票,給某個voter 賦予投票的權(quán)利
獲取到最高的選題Prososal的name

//合約名
contract Ballot {
    // 投票者結(jié)構(gòu)體
    struct Voter {
        uint weight; // 份額(既擁有多少票)
        bool voted;  // 是否已經(jīng)投票
        address delegate; // 委任誰進(jìn)行投票
        uint vote;   // 第幾個投票議案
    }

    // 議案機(jī)構(gòu)體
    struct Proposal {
        bytes32 name;   // 議案名(最多32字節(jié))
        uint voteCount; // 累計投票數(shù)
    }

    address public chairperson; //投票主持人

    // 投票者與其地址的映射
    mapping(address => Voter) public voters;

    // 提案指針
    Proposal[] public proposals;

    /// Ballot函數(shù),創(chuàng)建新投票,輸入多個議案名
    function Ballot(bytes32[] proposalNames) public {
        chairperson = msg.sender;
        voters[chairperson].weight = 1;

        for (uint i = 0; i < proposalNames.length; i++) {
            // `Proposal({...})` 創(chuàng)建一個臨時Proposal對象
            proposals.push(Proposal({
                name: proposalNames[I],
                voteCount: 0
            }));
        }
    }

    //輸入投票者地址,給予投票者投票權(quán)限
    function giveRightToVote(address voter) public {
        // require防止函數(shù)被錯誤調(diào)用,判斷為錯誤時終止調(diào)用
        // 并恢復(fù)到調(diào)用前的狀態(tài),但是注意會消耗gas
        require(
            (msg.sender == chairperson) &&
            !voters[voter].voted &&
            (voters[voter].weight == 0)
        );
        voters[voter].weight = 1;
    }

    /// 輸入他人地址,委任他人投票
    function delegate(address to) public {
        Voter storage sender = voters[msg.sender];
        require(!sender.voted);

        // 不允許委任自己
        require(to != msg.sender);

        // 循環(huán)委任直至被委任人不再委任他人,
        // 但注意這種循環(huán)是危險的,有可能耗盡gas來進(jìn)行計算。
        while (voters[to].delegate != address(0)) {
            to = voters[to].delegate;

            // 避免循環(huán)委任,形成委任環(huán)鏈
            require(to != msg.sender);
        }

        // 此處sender為voters[msg.sender]
        sender.voted = true;
        sender.delegate = to;
        Voter storage delegate_ = voters[to];
        if (delegate_.voted) {
            // 如果被委任人已經(jīng)投票,直接增加該議案票數(shù)
            proposals[delegate_.vote].voteCount += sender.weight;
        } else {
            // 如果被委任人未投票,增加被委任人持有票數(shù)
            delegate_.weight += sender.weight;
        }
    }
    /// 向議案投票
    function vote(uint proposal) public {
        Voter storage sender = voters[msg.sender];
        require(!sender.voted);
        sender.voted = true;
        sender.vote = proposal;

        // 提案超出數(shù)組范圍時自動中斷并恢復(fù)所以修改
        proposals[proposal].voteCount += sender.weight;
    }
    /// 返回獲得票數(shù)最高的議案索引
    function winningProposal() public view
            returns (uint winningProposal_)
    {
        uint winningVoteCount = 0;
        for (uint p = 0; p < proposals.length; p++) {
            if (proposals[p].voteCount > winningVoteCount) {
                winningVoteCount = proposals[p].voteCount;
                winningProposal_ = p;
            }
        }
    }
    // 返回獲得票數(shù)最高的議案名
    function winnerName() public view
            returns (bytes32 winnerName_)
    {
        winnerName_ = proposals[winningProposal()].name;
    }
}

案例6 競拍 (代碼)

contract SimpleAuction {
    
    address public beneficiary;
    //競拍開始
    uint public auctionStart;
    uint public biddingTime;

    //當(dāng)前的拍賣狀態(tài)
    address public highestBidder;
    uint public highestBid;

   //在結(jié)束時設(shè)置為true來拒絕任何改變
    bool ended;

   //當(dāng)改變時將會觸發(fā)的Event
    event HighestBidIncreased(address bidder, uint amount);
    event AuctionEnded(address winner, uint amount);

    //下面是一個叫做natspec的特殊注釋,
    //由3個連續(xù)的斜杠標(biāo)記,當(dāng)詢問用戶確認(rèn)交易事務(wù)時將顯示。

    ///創(chuàng)建一個簡單的合約使用`_biddingTime`表示的競拍時間,
   /// 地址`_beneficiary`.代表實際的拍賣者
    function SimpleAuction(uint _biddingTime,
                           address _beneficiary) {
        beneficiary = _beneficiary;
        auctionStart = now;
        biddingTime = _biddingTime;
    }

    ///對拍賣的競拍保證金會隨著交易事務(wù)一起發(fā)送,
   ///只有在競拍失敗的時候才會退回
    function bid() {

       //不需要任何參數(shù),所有的信息已經(jīng)是交易事務(wù)的一部分
        if (now > auctionStart + biddingTime)
           //當(dāng)競拍結(jié)束時撤銷此調(diào)用
            throw;
        if (msg.value <= highestBid)
           //如果出價不是最高的,發(fā)回競拍保證金。
            throw;
        if (highestBidder != 0)
            highestBidder.send(highestBid);
        highestBidder = msg.sender;
        highestBid = msg.value;
        HighestBidIncreased(msg.sender, msg.value);
    }

   ///拍賣結(jié)束后發(fā)送最高的競價到拍賣人
    function auctionEnd() {
        if (now >= auctionStart + biddingTime)
            throw; 
            //拍賣還沒有結(jié)束
        if (ended)
            throw; 
     //這個收款函數(shù)已經(jīng)被調(diào)用了
        AuctionEnded(highestBidder, highestBid);
        //發(fā)送合約擁有所有的錢,因為有一些保證金可能退回失敗了。

        beneficiary.send(this.balance);
        ended = true;
    }

    function () {
        //這個函數(shù)將會在發(fā)送到合約的交易事務(wù)包含無效數(shù)據(jù)
        //或無數(shù)據(jù)的時執(zhí)行,這里撤銷所有的發(fā)送,
        //所以沒有人會在使用合約時因為意外而丟錢。
        throw;
    }
}

博彩游戲

需求部分:

玩法規(guī)則

【缺圖】

合約需求
  • 押注
  • 開獎
  • 計算賠率
  • 領(lǐng)取獎勵

合約代碼實例

pragma solidity ^0.4.19;
contract LotteryBase {
    address public manager; // 彩票管理員
    string public name; // 彩票名稱
    uint public baseBlock; // 當(dāng)前售賣到的彩票期數(shù) 基準(zhǔn)區(qū)塊,也是彩票的期數(shù) 10
    uint public stopBlock; // 彩票從當(dāng)前塊數(shù)+到特定塊數(shù)這一期間為售賣期間 關(guān)閉彩票售賣通道區(qū)塊 100
    uint public openBlock; // 到了特定期間后再+到特定期間為開獎期間 開獎區(qū)塊 110
    //開獎期數(shù)號碼記錄,用于彩民備查
    struct OpenCode {
        uint block; // 等于 baseBlock
        uint8[] opencode; // 開獎號碼
    }
    // 所有開獎號碼集合
    OpenCode[] public allOpenCodes;
    // 獎金賬本,記錄每一個用戶的獎金
    mapping(address=>uint) public bonus; // 獎金
    // 所有中獎用戶的獎金綜合
    uint public totalBonus; // 總獎金金額,獎池金額 = 余額 - 獎金總金額

    function LotteryBase () public {
        manager = msg.sender;
    }

    modifier onlyManager () {
        require (manager == msg.sender);
        _;
    }

    // 兩個抽象接口
  //  function chipin(uint8[] number, uint8 multi) public payable;
    //function open() public;

    // 未分配獎池的獎金金額
    function getBonusPool() public view returns (uint) {
        return address(this).balance - totalBonus;
    }
}

contract KuaiSan is LotteryBase {

     //不同下注不同賠率列表
    uint8[19] public odds=[0,0,0,240,80,40,25,16,12,10,9,9,10,12,16,25,40,80,240];
    //定義下注方式的枚舉類型
    enum InjectionType {TypeSum, TypeSameThree,TypeSameThreeSingle,TypeSameTwo,TypeSameTwoSingle,TypeNoSameThree,TypeNoSameTwo,TypeThreeConsecutive }
    //購買彩票的結(jié)構(gòu)體
    struct Order {
        address player;
        uint8[] number; // 彩票號碼
        uint8 multi;
        InjectionType injectionType;//投注類型
        uint8 sumVal;//如果是和值類型,那么該值為下注的和值
    }
    // 訂單集合
    Order[] orders;

    // 彩票價格,大約2人民幣
    uint constant fee = 0.001 ether;
    uint constant stopInterval = 30; //設(shè)置停止間隔
    uint constant openInterval = 40; //設(shè)置開獎間隔
    uint constant codeAOffset = 33; //這只當(dāng)前區(qū)塊+33的hash值給A數(shù)
    uint constant codeBOffset = 34;//這只當(dāng)前區(qū)塊+33的hash值給B數(shù)
    uint constant codeCOffset = 35;//這只當(dāng)前區(qū)塊+33的hash值給C數(shù)

    function KuaiSan() public {  //構(gòu)造函數(shù),開始競猜
        // 開獎將基于 baseBlock + 33, baseBlock + 34, baseBlock + 35
        baseBlock = block.number; //將當(dāng)前區(qū)塊設(shè)置到baseBlock中
        stopBlock = baseBlock + stopInterval; //設(shè)置停止區(qū)塊為當(dāng)前區(qū)塊+開獎間隔 about 450 seconds
        openBlock = baseBlock + openInterval; //設(shè)置開獎區(qū)塊為當(dāng)前區(qū)塊+開獎區(qū)塊 about 150 seconds

        name = "中國福利彩票北京快三";
    }

    // 下注,玩家提供一個號碼和倍數(shù),記錄到訂單中
    // number是玩家購買的號碼,multi是玩家要購買的倍數(shù),injType為玩家下注方式,_sumVal是和值類型的和值數(shù)
    function chipin(uint8[] number, uint8 multi, InjectionType injType, uint8 _sumVal) public payable {
        require(msg.value >= fee * multi); //檢查下玩家投注的金額和倍數(shù)是不是一樣
        require(block.number <= stopBlock); //檢查當(dāng)前塊數(shù)是可以下注的塊數(shù)

        if(injType == InjectionType.TypeSum ){ //判斷玩家下注方式是不是和值類型
            require(_sumVal >= 3 && _sumVal <= 18); //檢查和值數(shù)不能小于3并且不能大于18
        }
        Order memory order = Order(msg.sender, number, multi, injType, _sumVal); //新建一個Order結(jié)構(gòu)體
        orders.push(order);//將Order結(jié)構(gòu)體存儲起來
    }
    //計算獎金函數(shù)-通過下注code信息計算獎金情況,返回獎金值
    //number是玩家購買的號碼,sumVal是值數(shù),multi是玩家要購買的倍數(shù),injType為玩家下注方式,openCode是開獎號碼
    function calcBonus(uint8[] number,uint8 sumval, uint8 multi, InjectionType injectionType,uint8[] opencode) public view returns (uint){

        //對于和值類型投注,下注金額不能小于1大于18

        //如果是和值類型,計算和值是否相等
        if(injectionType == InjectionType.TypeSum){ //如果玩家選擇的是和值類型
            uint injVal = opencode[0]+opencode[1]+opencode[2]; //開獎號碼總和
            if(sumval == injVal){ //如何玩家的sumval和開獎號碼和值相等的話
                return fee * odds[injVal] * multi / 2; //返回該獲得的獎金
            }
            return 0;
        }
        //三同號通選 要求三個號碼相同即可
        if(injectionType == InjectionType.TypeSameThree){
            if(opencode[0]  == opencode[2]){
               return fee * 40 * multi / 2;
            }
            return 0;
        }
        //三同號單選
        if(injectionType == InjectionType.TypeSameThreeSingle){
            if(opencode[0] == opencode[2]  && number[0] == opencode[0]){
                return fee * 240 * multi / 2;
            }
            return 0;
        }
        //二同號復(fù)選 只要任意兩個號碼相同即可
        if(injectionType == InjectionType.TypeSameTwo){
           if((opencode[0] == opencode[1] || opencode[1] == opencode[2]) && opencode[1] == number[0] ){
                return fee * 15 * multi / 2;
            }
            return 0;
        }
        //二同號單選 要求指定的對子和單都相同
        if(injectionType == InjectionType.TypeSameTwoSingle) {
            if(opencode[0] == opencode[1] || opencode[1] == opencode[2]) {
                if(opencode[0] == number[0] && opencode[1] == number[1] && opencode[2] == number[2]) {
                    return fee * 80 * multi / 2;
                }
            }
            return 0;
        }
        //三不同號 要求開獎號碼是三個不同的
        if(injectionType == InjectionType.TypeNoSameThree){
            if(opencode[0] == number[0] && opencode[1] == number[1] && opencode[2] == number[2]) {
                return fee * 40 * multi / 2;
            }
            return 0;
        }
        //二不同號 指定2個不同號碼和一個任意號碼
        if(injectionType == InjectionType.TypeNoSameTwo){
            if( (opencode[0] == number[0] && opencode[1] == number[1]) ||
            (opencode[1] == number[0] && opencode[2] == number[1]) ) {
                 return fee * 8 * multi / 2;
            }
            return 0;
        }
        //三連號 可能情況 123 234 345 456
        if(injectionType == InjectionType.TypeThreeConsecutive){
            if(opencode[1]-opencode[0] == 1 && opencode[2]-opencode[1] == 1){
                return fee * 10 * multi / 2;
            }
            return 0;
        }

        return 0;
    }
    //開盤函數(shù)
    function open() public {
        require(block.number > openBlock);//檢查一下當(dāng)前塊數(shù)大于設(shè)置的可開盤塊數(shù)

        uint8[] memory openCode; //openCode是存儲開獎號碼

        uint8 a = uint8(uint(block.blockhash(baseBlock + codeAOffset)) % 6 + 1); //將當(dāng)前區(qū)塊的hash值+codeAOffset,運(yùn)算出一個hash值與6取模并且+1
        uint8 b = uint8(uint(block.blockhash(baseBlock + codeBOffset)) % 6 + 1); //將當(dāng)前區(qū)塊的hash值+codeBOffset,運(yùn)算出一個hash值與6取模并且+1
        uint8 c = uint8(uint(block.blockhash(baseBlock + codeCOffset)) % 6 + 1); //將當(dāng)前區(qū)塊的hash值+codeCOffset,運(yùn)算出一個hash值與6取模并且+1
        uint8 t;
        //將開獎號碼排序
        if (a > b) {
            t = a;
            a = b;
            b = t;
        }
        if (b > c)
        {
            t = c;
            c = b;
            b = t;
        }
        if (a > b) {
            t = a;
            a = b;
            b = t;
        }
        OpenCode memory code = OpenCode(baseBlock, openCode); //新建一個代碼號碼記錄
        code.opencode[0] = a; //將記錄中的號碼賦值
        code.opencode[1] = b;
        code.opencode[2] = c;
        // 記錄中獎號碼
        allOpenCodes.push(code);
        //計算獎金
        uint i = 0;
        uint bonusMoney; //記錄該獲得的獎金
        for(i=0; i<orders.length; ++i) { //循環(huán)遍歷每一個競猜用戶
            Order memory o = orders[i]; //o是遍歷的orders寄存器
            //uint8[] number,uint8 sumval, uint8 multi, InjectionType injectionType,uint8[] opencode
            bonusMoney = calcBonus(o.number, o.sumVal, o.multi, o.injectionType, code.opencode); //調(diào)用calcBonus函數(shù)取得應(yīng)該獲得的獎金給bonusMoney
            if (bonusMoney > 0){
                bonus[o.player] += bonusMoney; //獎金映射,將獲得獎金映射到地址中
                totalBonus += bonusMoney; //增加總獎金金額
            }
        }
        uint bonusMoney = fee * 120;
        uint i = 0;
        for(i=0; i<orders.length; ++i) {
            Order memory o = orders[I];
            if(o.number[0] == code.opencode[0]
                && o.number[1] == code.opencode[1]
                && o.number[2] == code.opencode[2]) {

                bonus[o.player] += bonusMoney * o.multi;
                totalBonus += bonusMoney * o.multi;
            }
        }
        // 重置數(shù)據(jù),開始下一輪競猜
        delete orders;
        baseBlock = block.number;
        stopBlock = baseBlock + 30; // about 450 seconds
        openBlock = stopBlock + 10; // about 150 seconds

    }

    // 彩民獲取獎金
    function withdraw() public {
        uint money = bonus[msg.sender]; //獎金寄存器
        require(money > 0); //檢查money大于0

        delete bonus[msg.sender]; //清楚該地址映射
        totalBonus -= money; //總獎金金額減少
        msg.sender.transfer(money); //給該地址返還獎金
    }
}

中心服務(wù)器部分

node.js 服務(wù)器 安裝初始化
npm init  
安裝web3.js到項目中:
npm install web3 --save  
在服務(wù)器使用web3.js
在web3test目錄下新建index.js文件,在其中輸入以下代碼:
 var Web3 = require("web3");  
 var web3 = new Web3();  
 var web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"));  
獲取已部署的智能合約實例
    var abi = /*編譯器生成的abi代碼*/;
    var contractAddress = '/*這里是合約的地址*/';  
    var hello = new web3.eth.Contract(abi,address);
調(diào)用節(jié)點
  • 查看節(jié)點所有賬戶
var faq = web3.eth.getAccounts(function(error,result){
    if(!error)
    resp.send(result);
});
console.log(faq);
  • 創(chuàng)建用戶
var daq=web3.eth.personal.newAccount("1234",function(error,result){
    if(!error)
    resp.send(result);
});
  • 解鎖
var faq=web3.eth.personal.unlockAccount("0xc40b465e28a386c56806058571d0baf303af079c","123",function(error,result){
    if(!error)
    resp.send(result);
});
    console.log(faq);
  • 調(diào)用合約
    函數(shù)下面是調(diào)用一個只讀函數(shù),后面參數(shù)call是表明此調(diào)用不會產(chǎn)生數(shù)據(jù)更改,只會在一個節(jié)點上處理數(shù)據(jù),也不會消耗gas,function是回調(diào)函數(shù),回調(diào)函數(shù)的返回值就是函數(shù)的返回值。
    下面是調(diào)用一個只讀函數(shù),后面參數(shù)call是表明此調(diào)用不會產(chǎn)生數(shù)據(jù)更改,只會在一個節(jié)點上處理數(shù)據(jù),也不會消耗gas,function是回調(diào)函數(shù),回調(diào)函數(shù)的返回值就是函數(shù)的返回值。
hello.methods.helloworld().call(function(error,result){
        if(!error)
        resp.send(result);
});
下面的是一個調(diào)用接受轉(zhuǎn)賬的函數(shù),from是轉(zhuǎn)賬的賬戶,value是轉(zhuǎn)賬的數(shù)額,單位是wei,gas就是設(shè)定的gas,function是后面接的回調(diào)函數(shù),回調(diào)函數(shù)的返回值是交易地址,還沒有找到如何去查看函數(shù)的返回值。
hello.methods.hellomoney().send({from:"0xc40b465e28a386c56806058571d0baf303af079c",value: 200000000,gas:3000000},function(error,result){
        if(!error)
        resp.send(result);
});

hello.methods.helloPDJ().send({from:"0xc40b465e28a386c56806058571d0baf303af079c",gas:3000000},function(error,result){
if(!error)
resp.send(result);
})
上面調(diào)用會變更數(shù)據(jù),但不接受轉(zhuǎn)賬的函數(shù),from是發(fā)送調(diào)用的地址,
function是回調(diào)函數(shù),回調(diào)函數(shù)的返回值是交易地址,還沒有找到如何去查看函數(shù)的返回值。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容