Last active
July 7, 2018 08:19
-
-
Save hskang9/62aa98913c0a0396806c0e6051db7e18 to your computer and use it in GitHub Desktop.
TokenStorage.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.17; | |
import './StandardERC223Token.sol'; | |
/** | |
* @title Pausable | |
* @dev Base contract which allows children to implement an emergency stop mechanism. | |
*/ | |
contract Pausable is Ownable { | |
event Pause(); | |
event Unpause(); | |
bool public paused = false; | |
/** | |
* @dev Modifier to make a function callable only when the contract is not paused. | |
*/ | |
modifier whenNotPaused() { | |
require(!paused); | |
_; | |
} | |
/** | |
* @dev Modifier to make a function callable only when the contract is paused. | |
*/ | |
modifier whenPaused() { | |
require(paused); | |
_; | |
} | |
/** | |
* @dev called by the owner to pause, triggers stopped state | |
*/ | |
function pause() onlyOwner whenNotPaused public { | |
paused = true; | |
emit Pause(); | |
} | |
/** | |
* @dev called by the owner to unpause, returns to normal state | |
*/ | |
function unpause() onlyOwner whenPaused public { | |
paused = false; | |
emit Unpause(); | |
} | |
} | |
contract Team { | |
string public name; | |
string public uri = ""; | |
uint public rank = 0; | |
uint public wins = 0; | |
uint public looses = 0; | |
uint public ties = 0; | |
event TeamStat(uint256 _time, string _name, string _uri, uint _rank, uint _wins, uint _looses, uint _ties); | |
constructor(string _name, string _uri, uint _rank) public { | |
name = _name; | |
uri = _uri; | |
rank = _rank; | |
emit TeamStat(now, name, uri, rank, wins, looses, ties); | |
} | |
function increaseWins() public { | |
wins++; | |
emit TeamStat(now, name, uri, rank, wins, looses, ties); | |
} | |
function increaseLooses() public { | |
looses++; | |
emit TeamStat(now, name, uri, rank, wins, looses, ties); | |
} | |
function increaseTies() public { | |
ties++; | |
emit TeamStat(now, name, uri, rank, wins, looses, ties); | |
} | |
} | |
library itMaps { | |
/*********************** | |
* Iterable maps: | |
* itmapUintUint for uint=>uint maps | |
* itmapAddressUint for address=>uint maps | |
* itmapUintAddress for uint=>address maps | |
* Use: | |
* import "./itmaps.sol" | |
* // Use itmap for all functions on the struct | |
* using itmap for itmap.itmapUintUint; | |
* using itmap for itmap.itmapAddressUint; | |
* using itmap for itmap.itmapUintAddress; | |
* | |
* // Declare an iterable mapping | |
* itmap.itmapUintUint im_myUintUintMap; | |
* itmap.itmapAddressUint im_myAddressUintMap; | |
* itmap.itmapUintAddress im_myUintAddress; | |
* | |
* im_myUintUintMap.insert( <uint key>, <uint value>); | |
* im_myUintUintMap.get(<uint key>); // returns item uint value by item key | |
* im_myUintUintMap.contains(<uint key); // returns bool true if key is in mapping | |
* im_myUintUintMap.size(); // returns uint size of the map ( for iterating) | |
* im_myUintUintMap.getKeyByIndex(<uint idx>); // returns item key by mapping index (for iterating) | |
* im_myUintUintMap.getValueByIndex(<uint idx>); //returns item value by mapping index ( for iterating) | |
* im_myUintUintMap.remove(<uint key>); // removes an item from map | |
* | |
* *********************/ | |
/* itmapUintUint mapping | |
KeyIndex uint => Value uint | |
*/ | |
struct entryUintUint { | |
// Equal to the index of the key of this item in keys, plus 1. | |
uint keyIndex; | |
uint value; | |
} | |
struct itmapUintUint { | |
mapping(uint => entryUintUint) data; | |
uint[] keys; | |
} | |
function insert(itmapUintUint storage self, uint key, uint value) internal returns (bool replaced) { | |
entryUintUint storage e = self.data[key]; | |
e.value = value; | |
if (e.keyIndex > 0) { | |
return true; | |
} else { | |
e.keyIndex = ++self.keys.length; | |
self.keys[e.keyIndex - 1] = key; | |
return false; | |
} | |
} | |
function remove(itmapUintUint storage self, uint key) internal returns (bool success) { | |
entryUintUint storage e = self.data[key]; | |
if (e.keyIndex == 0) | |
return false; | |
if (e.keyIndex < self.keys.length) { | |
// Move an existing element into the vacated key slot. | |
self.data[self.keys[self.keys.length - 1]].keyIndex = e.keyIndex; | |
self.keys[e.keyIndex - 1] = self.keys[self.keys.length - 1]; | |
self.keys.length -= 1; | |
delete self.data[key]; | |
return true; | |
} | |
} | |
function contains(itmapUintUint storage self, uint key) internal constant returns (bool exists) { | |
return self.data[key].keyIndex > 0; | |
} | |
function size(itmapUintUint storage self) internal constant returns (uint) { | |
return self.keys.length; | |
} | |
function get(itmapUintUint storage self, uint key) internal constant returns (uint) { | |
return self.data[key].value; | |
} | |
function getKey(itmapUintUint storage self, uint idx) internal constant returns (uint) { | |
/* Decrepated, use getKeyByIndex. This kept for backward compatilibity */ | |
return self.keys[idx]; | |
} | |
function getKeyByIndex(itmapUintUint storage self, uint idx) internal constant returns (uint) { | |
/* Same as decrepated getKey. getKeyByIndex was introduced to be less ambiguous */ | |
return self.keys[idx]; | |
} | |
function getValueByIndex(itmapUintUint storage self, uint idx) internal constant returns (uint) { | |
return self.data[self.keys[idx]].value; | |
} | |
/* itmapAddressUint | |
address => Uint | |
*/ | |
struct entryAddressUint { | |
// Equal to the index of the key of this item in keys, plus 1. | |
uint keyIndex; | |
uint value; | |
} | |
struct itmapAddressUint { | |
mapping(address => entryAddressUint) data; | |
address[] keys; | |
} | |
function insert(itmapAddressUint storage self, address key, uint value) internal returns (bool replaced) { | |
entryAddressUint storage e = self.data[key]; | |
e.value = value; | |
if (e.keyIndex > 0) { | |
return true; | |
} else { | |
e.keyIndex = ++self.keys.length; | |
self.keys[e.keyIndex - 1] = key; | |
return false; | |
} | |
} | |
function remove(itmapAddressUint storage self, address key) internal returns (bool success) { | |
entryAddressUint storage e = self.data[key]; | |
if (e.keyIndex == 0) | |
return false; | |
if (e.keyIndex < self.keys.length) { | |
// Move an existing element into the vacated key slot. | |
self.data[self.keys[self.keys.length - 1]].keyIndex = e.keyIndex; | |
self.keys[e.keyIndex - 1] = self.keys[self.keys.length - 1]; | |
self.keys.length -= 1; | |
delete self.data[key]; | |
return true; | |
} | |
} | |
function contains(itmapAddressUint storage self, address key) internal constant returns (bool exists) { | |
return self.data[key].keyIndex > 0; | |
} | |
function size(itmapAddressUint storage self) internal constant returns (uint) { | |
return self.keys.length; | |
} | |
function get(itmapAddressUint storage self, address key) internal constant returns (uint) { | |
return self.data[key].value; | |
} | |
function getKeyByIndex(itmapAddressUint storage self, uint idx) internal constant returns (address) { | |
return self.keys[idx]; | |
} | |
function getValueByIndex(itmapAddressUint storage self, uint idx) internal constant returns (uint) { | |
return self.data[self.keys[idx]].value; | |
} | |
/* itmapUintAddress | |
Uint => Address | |
*/ | |
struct entryUintAddress { | |
// Equal to the index of the key of this item in keys, plus 1. | |
uint keyIndex; | |
address value; | |
} | |
struct itmapUintAddress { | |
mapping(uint => entryUintAddress) data; | |
uint[] keys; | |
} | |
function insert(itmapUintAddress storage self, uint key, address value) internal returns (bool replaced) { | |
entryUintAddress storage e = self.data[key]; | |
e.value = value; | |
if (e.keyIndex > 0) { | |
return true; | |
} else { | |
e.keyIndex = ++self.keys.length; | |
self.keys[e.keyIndex - 1] = key; | |
return false; | |
} | |
} | |
function remove(itmapUintAddress storage self, uint key) internal returns (bool success) { | |
entryUintAddress storage e = self.data[key]; | |
if (e.keyIndex == 0) | |
return false; | |
if (e.keyIndex < self.keys.length) { | |
// Move an existing element into the vacated key slot. | |
self.data[self.keys[self.keys.length - 1]].keyIndex = e.keyIndex; | |
self.keys[e.keyIndex - 1] = self.keys[self.keys.length - 1]; | |
self.keys.length -= 1; | |
delete self.data[key]; | |
return true; | |
} | |
} | |
function contains(itmapUintAddress storage self, uint key) internal constant returns (bool exists) { | |
return self.data[key].keyIndex > 0; | |
} | |
function size(itmapUintAddress storage self) internal constant returns (uint) { | |
return self.keys.length; | |
} | |
function get(itmapUintAddress storage self, uint key) internal constant returns (address) { | |
return self.data[key].value; | |
} | |
function getKeyByIndex(itmapUintAddress storage self, uint idx) internal constant returns (uint) { | |
return self.keys[idx]; | |
} | |
function getValueByIndex(itmapUintAddress storage self, uint idx) internal constant returns (address) { | |
return self.data[self.keys[idx]].value; | |
} | |
} | |
contract TokenStorage is ERC223ReceivingContract, Ownable, Pausable { | |
using SafeMath for uint256; | |
using itMaps for itMaps.itmapAddressUint; | |
// Connected contracts | |
StandardERC223Token public token; | |
// Addresses | |
address public tokenAddress; | |
address public teamAddressHome; | |
address public teamAddressAway; | |
address public teamAddressTie; | |
// Contract Variable | |
uint8 constant TEAMHOME = 0; | |
uint8 constant TEAMAWAY = 1; | |
uint8 constant TEAMTIE = 2; | |
uint256 totalTeamBalance = 0; | |
uint256 public deadline; | |
struct TeamData { | |
itMaps.itmapAddressUint betting; | |
uint256 totalBalance; | |
} | |
mapping(address => TeamData) mapTeamData; | |
Team public homeTeam; | |
Team public awayTeam; | |
Team public tieTeam; | |
event Bet(uint256 _time, address _player, address _team, uint256 _numOfTokens); | |
event Distribute(uint256 _time, address[] _users, uint[] _rewards); | |
constructor() public { | |
tokenAddress = address(0); | |
teamAddressHome = address(0); | |
teamAddressAway = address(0); | |
teamAddressTie = address(0); | |
token = StandardERC223Token(tokenAddress); | |
homeTeam = Team(teamAddressHome); | |
awayTeam = Team(teamAddressAway); | |
tieTeam = Team(teamAddressTie); | |
} | |
//Setters | |
function setTokenAddress(address _tokenAddress) external { | |
tokenAddress = _tokenAddress; | |
} | |
function setTeamAddressHome(address _teamAddressHome) external { | |
teamAddressHome = _teamAddressHome; | |
} | |
function setTeamAddressAway(address _teamAddressAway) external { | |
teamAddressAway = _teamAddressAway; | |
} | |
function setTeamAddressTie(address _teamAddressTie) external { | |
teamAddressTie = _teamAddressTie; | |
} | |
function bet(address _player, address _team, uint256 _numOfTokens) public { | |
require(msg.sender == _player); | |
token.approve(address(this), _numOfTokens); | |
token.transferFrom(_player,address(this), _numOfTokens); | |
uint tokens = 0; | |
TeamData storage teamData = mapTeamData[_team]; | |
if(teamData.betting.contains(_player)) { | |
tokens = _numOfTokens.add(teamData.betting.get(_player)); | |
} else { | |
tokens = _numOfTokens; | |
} | |
teamData.betting.insert(_player, tokens); | |
teamData.totalBalance = _numOfTokens.add(teamData.totalBalance); | |
emit Bet(now, _player, _team, _numOfTokens); | |
} | |
function getTeamPercentage(address team) public constant returns (uint256) { | |
TeamData storage teamDataHome = mapTeamData[homeTeam]; | |
TeamData storage teamDataAway = mapTeamData[awayTeam]; | |
TeamData storage teamDataTie = mapTeamData[tieTeam]; | |
uint temp = teamDataHome.totalBalance; | |
uint totalBalanceTeam = temp.add(teamDataAway.totalBalance); | |
totalBalanceTeam = totalBalanceTeam.add(teamDataTie.totalBalance); | |
TeamData storage teamDataCur = mapTeamData[team]; | |
temp = teamDataCur.totalBalance; | |
uint teamRate = temp.mul(100); | |
return teamRate.div(totalBalanceTeam); | |
} | |
function getRewardPercentage(address player, address team) public constant returns (uint256) { | |
TeamData storage teamData = mapTeamData[team]; | |
uint playerTokens =teamData.betting.get(player).mul(100); | |
return playerTokens.div(teamData.totalBalance); | |
} | |
function getReward(address player, address team) public constant returns (uint256) { | |
TeamData storage teamDataHome = mapTeamData[homeTeam]; | |
TeamData storage teamDataAway = mapTeamData[awayTeam]; | |
TeamData storage teamDataTie = mapTeamData[tieTeam]; | |
uint temp = teamDataHome.totalBalance; | |
uint totalBalanceTeam = temp.add(teamDataAway.totalBalance); | |
totalBalanceTeam = totalBalanceTeam.add(teamDataTie.totalBalance); | |
TeamData storage teamDataCur = mapTeamData[team]; | |
uint totalTokens = totalBalanceTeam.mul(teamDataCur.betting.get(player)); | |
return totalTokens.div(teamDataCur.totalBalance); | |
} | |
function getDistribution(address team) public returns (address[], uint[]) { | |
TeamData storage teamDataCur = mapTeamData[team]; | |
uint len = teamDataCur.betting.size(); | |
address[] memory _winUsers = new address[](len); | |
uint[] memory _winTokens = new uint[](len); | |
for(uint i = 0; i < len; i++) { | |
_winUsers[i] = teamDataCur.betting.getKeyByIndex(i); | |
_winTokens[i] = getReward(_winUsers[i], team); | |
} | |
emit Distribute(now, _winUsers, _winTokens); | |
if (Team(team) == homeTeam) { | |
Team(homeTeam).increaseWins(); | |
Team(awayTeam).increaseLooses(); | |
} else if (Team(team) == awayTeam) { | |
Team(homeTeam).increaseLooses(); | |
Team(awayTeam).increaseWins(); | |
} else { | |
Team(homeTeam).increaseTies(); | |
Team(awayTeam).increaseTies(); | |
} | |
return (_winUsers, _winTokens); | |
} | |
function distribute(address _team) external onlyOwner returns (bool success) { | |
address[] memory Users; | |
uint256[] memory Tokens; | |
(Users, Tokens) = getDistribution(_team); | |
token.multiTransfer(Users, Tokens); | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment