Skip to content

Instantly share code, notes, and snippets.

@hskang9
Last active July 7, 2018 08:19
Show Gist options
  • Save hskang9/62aa98913c0a0396806c0e6051db7e18 to your computer and use it in GitHub Desktop.
Save hskang9/62aa98913c0a0396806c0e6051db7e18 to your computer and use it in GitHub Desktop.
TokenStorage.sol
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