Solidity로 도박 게임 이야기를 만들었어요.

성과물


아무튼 라이트 사일에서 쉽게 공개할 수 있습니다.
Metamask를 넣으면 랩텐 네트워크를 선택하여 게임을 진행할 수 있습니다!!
메인 네트워크에서 놀 수 없습니다.
이제 꺼졌어!
http://13.113.175.211:3000/

개요


개길이의 훈아가 되고 싶어요.
이더넷을 사용합니다.
완성형태는 사용자 로그인과 사용자가 보유한 돈(GTP)의 양을 관리하는 것에 불과하다.
Rails 쪽에서 랜덤으로 생성해서 승부를 결정합니다.
승부로 프레임을 두드리는 함수에 따라 지갑과 연결된 사용자를 이동하는 GTTIP!
이런 코디.

기술 수준


Rails(학습)
Solidity(좀비 놀았다)
Html/CSS
예쁜 코드는 아니지만 학습의 궤적으로 남겨두세요!

웹 페이지 출처


https://github.com/tokai-son/Gambreum_web
정리가 안 됐어요.JS 파일로 자세히 분리하려면...

Solidity 섹션


GambreumPlayer.sol
pragma solidity ^0.4.24;

import "./GambreumTip.sol";
import "../node_modules/zeppelin-solidity/contracts/token/ERC20/StandardToken.sol";
import "../node_modules/zeppelin-solidity/contracts/ownership/Ownable.sol";

contract GambreumPlayer is GambreumTip {

    struct PlayerInfo {
        string username;
        uint winrate;
        bool locked;
    }

    event PlayerCreated(string username);

    mapping (address => PlayerInfo) public addressToPlayerInfo;
    mapping (address => uint) public addressToBalance;

    function createPlayer(string _name) public {
        emit PlayerCreated(_name);
        require(keccak256(_name) != keccak256("username"));
        string memory player_name = addressToPlayerInfo[msg.sender].username;
        require(bytes(player_name).length == 0);
        addressToPlayerInfo[msg.sender] = PlayerInfo(_name, 0, false);
        balances[msg.sender] += 100; //初期配布分の100GTIP
    }

    function viewPlayerInfo() public view returns (string username, uint winrate, bool locked) {
        PlayerInfo memory player_info = addressToPlayerInfo[msg.sender];
        return (player_info.username, player_info.winrate, player_info.locked);
    }

    function publishTokenToPlayer(uint value, address to) public onlyOwner {
        balances[to] += value;
    }

    function returnToken(uint value, address player_address) public onlyOwner {
        balances[player_address] -= value;
    }
}
처음 할 일부터 탈선 w
그리고 나중에야 "ERC20 아니어도 되겠죠?"
그러나truffle를 사용하는 일련의 개발 프로그램은 이미 배웠다.
"쓰기, 디버깅(이거 다음에 읽자), 컴파일, 테스트, 디버깅"
이번에는 이렇게 했습니다.
클라이언트 ->Local Rails->infura->Contractin Ropten
가장 힘든 일은 서버로부터 거래를 하는 것이다.
서버의 설정 소유자 계정
onlyOwner 속성의 함수를 두드려야 합니다.
고객 으로부터 구조 를 세우다
인터넷 3과 메타마스크 모두 열심히 한다.
API를 통해 서버에서 트랜잭션 두드리기...
API에 "조직자 소유자의 서명이 있는 Raw Transaction을 만들어야 함"
코드를 보면 알 것 같아요.
우여곡절
포인트는 Hex.데이터 섹션은 이더 eum ABI 형식에 부합해야 합니다.
간단히 말하다
1 함수 이름 (매개 변수 형식에 공간이 없고 이름은 생략됨) 256 산열
그 최초의 4Byte만 사용합니다.
16진법 형식으로 2진법 매개 변수로 된 데이터를 전달하다.단, 32Byte 길이에 도달하기 위해 0으로 채웁니다
(매개변수가 가변 길이인 경우 추가 정보가 필요합니다. 자세한 내용은 4여기 봐! 참조)
마지막으로 이 녀석들을 모두 연결해서 처음에'0x'를 붙이면 완성된다.
RawTransaction을 제작 중입니다.(Etherm.rb 사용)

  def exeRewardProc(amount, user_wallet, is_earn)
   # Create instanse from my private key whose is Gambrerum Owner.
   key = Eth::Key.new priv: "<秘密鍵 MetamaskからExportした>"

   # Get transaction count
   response = getMyTransactionCount()
   string_response = response.body
   json_response = JSON.parse(string_response)
   my_nonce = json_response["result"]

   # Create hex_data as a payload on this tx.
   if(is_earn == true)
     selector = Digest::SHA3.hexdigest("publishTokenToPlayer(uint256,address)", 256).slice(0..7) # 最初の4Byteを使う
   else
     selector = Digest::SHA3.hexdigest("returnToken(uint256,address)", 256).slice(0..7) # 最初の4Byteを使う
   end
   amount = amount.to_s(16) # 0xへ
   arg1_uint = amount.rjust(64, "0") #FIX: 10進数だから16に直す!
   arg2_address = user_wallet.slice(2..-1)
   arg2_address = arg2_address.rjust(64, "0")
   hex_data = "0x" + selector + arg1_uint + arg2_address

   tx = Eth::Tx.new({
     data: hex_data,
     gas_limit: DEFAULT_GAS_LIMIT,
     gas_price: DEFAULT_GAS_PRICE,
     nonce: my_nonce.hex,
     from: "0x6CaFf8d3958dB8EF53b1Abbe10622c26DBFa4778",
     to: CONTRACT_ADDRESS,
     value: 0
   })

   # Sign this transaction by the key
   tx.sign key

   transaction_response = sendMyRawTransaction(tx.hex)
   transaction_response_string = transaction_response.body
   logger.debug(transaction_response_string)
   transaction_response_json = JSON.parse(transaction_response_string)
   return transaction_response_json["result"]
 end
다음은 API를 통해 Transaction을 보냅니다.
  def sendMyRawTransaction(signed_pay_load)
   uri = URI.parse(ROPSTEN_URL)
   request = Net::HTTP::Post.new(uri)
   request.content_type = "application/json"
   request.body = JSON.dump({
     "jsonrpc" => "2.0",
     "method" => "eth_sendRawTransaction",
     "params" => [
       signed_pay_load
     ],
     "id" => 1
   })

   req_options = {
     use_ssl: uri.scheme == "https",
   }

   response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
     http.request(request)
   end

   return response
 end
어쨌든 주사위를 굴려 승부를 결정한다
거래를 발행하는 TIP가 움직인다!라는 뜻이다.
다만, 개선할 여지가 있다.
1 모바일 TIP의 거래는 승인될 때까지 기다려야 한다
당연하지, 사실 이미 TIP가 없어, 다음 경기!
뭐든지 할 수 있어요.
해결 방안: 거래 발행 후 계좌 잠금
서버측 DB 준비 및 트랜잭션 모니터링
2가 마이너스가 되면 너무 힘들어요.
다음 수동 데이터베이스 변수를 사용하여 TIP 관리
  zeppelin-solidity/contracts/token/ERC20/BasicToken.sol
 
  〜 uint256...이게 마이너스가 나오면 세상이 반전돼요.
해결 방법: 도박을 줄이지 않는 건강한 도박을 주세요. 
        and
SafeMath 사용(좀비에게 배웠던...)
3Metamask로 테스트망 이외의 상황 탐지
알고 보니..
고객 측에서'웹3.eth.net.getNetworkType'이라고 판단하면 됩니다!
BasicToken.sol

pragma solidity ^0.4.24;


import "./ERC20Basic.sol";
import "../../math/SafeMath.sol";


/**
* @title Basic token
* @dev Basic version of StandardToken, with no allowances.
*/
contract BasicToken is ERC20Basic {
 using SafeMath for uint256;

 mapping(address => uint256) internal balances;

~ snip ~
뜻대로 되지는 않았지만 대체로 놀 수 있는 형태로 이뤄졌다.
역시 1부터 시작해서 어렵지만 즐겁네요.
앞으로...
· Rspec을 사용해 보세요
・HTTPS를 통해 액세스 가능
• 이 환경을 Docker의 이미지로 설정
이 근처를 시험해 보고 싶어요.

좋은 웹페이지 즐겨찾기