Created
March 15, 2018 16:52
-
-
Save vincentchu/a4429de38ae15419f3b08c86c2bffd84 to your computer and use it in GitHub Desktop.
This file contains 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.19; | |
import './ERC721.sol'; | |
contract CryptoMarchMadness is ERC721, ERC721Metadata, ERC721Enumerable { | |
uint256 private constant MASK = 0x3f; | |
uint256 public basePoolFeeInWei; // Fee required to purchase a bracket | |
uint256 public collectorFeeInWei; // Flat fee reserved for the pool operator | |
uint256 public poolSizeInWei; // Funds reserved for the bracket pool | |
uint256 public collectorPoolSizeInWei; // Funds reserved for the pool operator | |
uint8 public currentRound; // Round 1-5 (1=Sweet 16, 5=Finals). | |
// Rounds 6 & 7 are special internal flags that | |
// indicate when people can buy brackets | |
// (6=half price, 7=full price) | |
uint256 public currentState; // Current bracket results | |
uint256 public totalPoints; // Total number of points (set by the pool owner) | |
address private _collector; | |
address private _delegateOwner; | |
uint256 public totalCount; // Total number of brackets (deeds) purchased | |
uint256[] public deeds; // Flat array of deeds created | |
mapping (uint256 => address) private _ownerOfMap; | |
mapping (uint256 => address) private _approvedMap; | |
mapping (uint256 => uint256) public priceMap; | |
// CryptoMarchMadness specific methods | |
function CryptoMarchMadness(uint256 _basePoolFeeInWei, uint256 _collectorFeeInWei, address collector) public { | |
totalCount = 0; | |
totalPoints = 0; | |
currentRound = 6; | |
currentState = 0; | |
_delegateOwner = msg.sender; | |
_collector = collector; | |
basePoolFeeInWei = _basePoolFeeInWei; | |
collectorFeeInWei = _collectorFeeInWei; | |
} | |
modifier mustBeValidDeed(uint256 _deedId) { | |
require(_ownerOfMap[_deedId] != address(0)); | |
_; | |
} | |
modifier mustBeAuthorized(uint256 _deedId) { | |
require(msg.sender == _ownerOfMap[_deedId] || msg.sender == _approvedMap[_deedId] || msg.sender == _delegateOwner); | |
_; | |
} | |
modifier mustBeDelegateOwner { | |
require(msg.sender == _delegateOwner); | |
_; | |
} | |
function buyIn(uint256 _deedId) external payable { | |
require(currentRound == 6 || currentRound == 7); | |
if (currentRound == 6) { | |
require(msg.value >= basePoolFeeInWei); | |
} else { | |
require(msg.value >= 2 * basePoolFeeInWei); | |
} | |
collectorPoolSizeInWei += collectorFeeInWei; | |
poolSizeInWei += (msg.value - collectorFeeInWei); | |
_ownerOfMap[_deedId] = msg.sender; | |
deeds.push(_deedId); | |
totalCount += 1; | |
} | |
function _scorePred(uint256 predicted) private view returns (uint8 _score) { | |
require(currentRound > 0 && currentRound <= 5); | |
uint8 startIdx = 0; | |
for (uint8 round = 0; round < currentRound; round++) { | |
uint8 len = uint8(2)**(4-round); | |
for (uint8 game = 0; game<len; game++) { | |
uint8 gameIdx = game + startIdx; | |
uint256 predGame = (predicted >> (gameIdx * 6)) & MASK; | |
uint256 actualGame = (currentState >> (gameIdx * 6)) & MASK; | |
if (predGame == actualGame) { | |
_score += uint8(2)**round; | |
} | |
} | |
startIdx += len; | |
} | |
} | |
function scoreDeed(uint256 deedId) external view mustBeValidDeed(deedId) returns (uint8 _score) { | |
_score = _scorePred(deedId); | |
} | |
function redeem(uint256 deedId) | |
external | |
mustBeValidDeed(deedId) | |
mustBeAuthorized(deedId) | |
{ | |
require(currentRound == 5); | |
uint8 score = _scorePred(deedId); | |
uint256 share = poolSizeInWei * score / totalPoints; | |
delete _ownerOfMap[deedId]; | |
delete _approvedMap[deedId]; | |
msg.sender.transfer(share); | |
} | |
function updateState(uint8 _currentRound, uint256 _currentState, uint256 _totalPoints) external mustBeDelegateOwner() { | |
currentRound = _currentRound; | |
currentState = _currentState; | |
totalPoints = _totalPoints; | |
} | |
function collectFee() external mustBeDelegateOwner() { | |
_delegateOwner.transfer(collectorPoolSizeInWei); | |
} | |
function quitquitquit() external mustBeDelegateOwner() { | |
selfdestruct(_collector); | |
} | |
function _approve(address _approved, uint256 _deedId, uint256 _price) | |
private | |
mustBeValidDeed(_deedId) | |
mustBeAuthorized(_deedId) | |
{ | |
_approvedMap[_deedId] = _approved; | |
if (_price > 0) { | |
priceMap[_deedId] = _price; | |
} | |
Approval(msg.sender, _approved, _deedId); | |
} | |
function approveWithPrice(address _approved, uint256 _deedId, uint256 _price) external { | |
_approve(_approved, _deedId, _price); | |
} | |
// ERC721 Implementation | |
function balanceOf(address _owner) external view returns (uint256 _balance) { | |
require(false); | |
} | |
function ownerOf(uint256 _deedId) | |
external | |
mustBeValidDeed(_deedId) | |
view | |
returns (address _owner) | |
{ | |
_owner = _ownerOfMap[_deedId]; | |
} | |
function transfer(address _to, uint256 _deedId) | |
external | |
mustBeValidDeed(_deedId) | |
mustBeAuthorized(_deedId) | |
payable | |
{ | |
address owner = _ownerOfMap[_deedId]; | |
uint256 sellingPrice = priceMap[_deedId]; | |
require(owner != _to); | |
require(msg.value >= sellingPrice); | |
_ownerOfMap[_deedId] = _to; | |
delete _approvedMap[_deedId]; | |
delete priceMap[_deedId]; | |
if (sellingPrice > 0) { | |
uint256 transferFee = sellingPrice * 5 / 100; | |
uint256 toTransfer = sellingPrice - transferFee; | |
collectorPoolSizeInWei += transferFee; | |
owner.transfer(toTransfer); | |
} | |
Transfer(owner, _to, _deedId); | |
} | |
function approve(address _approved, uint256 _deedId) external payable { | |
_approve(_approved, _deedId, 0); | |
} | |
function delegate(address _delegate) external mustBeDelegateOwner() { | |
if (_delegate != address(0)) { | |
_delegateOwner = _delegate; | |
} | |
Delegation(msg.sender, _delegate); | |
} | |
// ERC-721Metadata Implementation | |
function name() external pure returns (string _name) { | |
_name = "Crypto March Madness"; | |
} | |
function symbol() external pure returns (string _symbol) { | |
_symbol = "CMM"; | |
} | |
function deedUri(uint256 _deedId) external view returns (string _deedUri) { | |
_deedUri = "https://cryptofinalfour.com/brackets/deedIdHex"; | |
} | |
// ERC721Enumerable | |
function totalSupply() external view returns (uint256 _count) { | |
_count = totalCount; | |
} | |
function deedByIndex(uint256 _index) external view returns (uint256 _deedId) { | |
require(_index < deeds.length); | |
return deeds[_index]; | |
} | |
function countOfOwners() external view returns (uint256 _count) { | |
_count = 0; // We don't keep track of owners, so just return 0. Spec says "do not throw" | |
} | |
function ownerByIndex(uint256 _index) external view returns (address _owner) { | |
require(false); | |
} | |
function deedOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256 _deedId) { | |
require(false); | |
} | |
// ERC165 Implementation | |
function supportsInterface(bytes4 interfaceID) external view returns (bool) { | |
return false; | |
} | |
} |
This file contains 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.19; | |
interface ERC165 { | |
/// @notice Query if a contract implements an interface | |
/// @param interfaceID The interface identifier, as specified in ERC-165 | |
/// @dev Interface identification is specified in ERC-165. This function | |
/// use less than 30000 gas. | |
/// @return `true` if the contract implements `interfaceID` and | |
/// `interfaceID` is not 0xffffffff, `false` otherwise | |
function supportsInterface(bytes4 interfaceID) external view returns (bool); | |
} |
This file contains 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.19; | |
import "./ERC165.sol"; | |
/// @title Required part of ERC-721 Deed Standard | |
/// @author William Entriken (https://phor.net) | |
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
/// Note: the ERC-165 (DRAFT) identifier for this interface is 0xb3a99827 | |
// State: https://github.com/fulldecent/EIPs/commit/1a1295c903dfd2da18024c8c717054af394b847f | |
interface ERC721 /* is ERC165 */ { | |
/// @dev This emits when ownership of any deed changes by any mechanism. | |
/// This event emits when deeds are created (`from` == 0) and destroyed | |
/// (`to` == 0). Exception: during contract creation, any number of deeds | |
/// may be created and assigned without emitting Transfer. At the time of | |
/// any transfer, the "approved deed controller" is implicitly reset to the | |
/// zero address. | |
event Transfer(address indexed _from, address indexed _to, uint256 _deedId); | |
/// @dev This emits when the "approved deed controller" for a deed is | |
/// changed or reaffirmed. The zero address indicates there is no approved | |
/// deed controller. When a Transfer event emits, this also indicates the | |
/// approved deed controller (if any) is reset to none. | |
event Approval(address indexed _owner, address indexed _approved, uint256 _deedId); | |
/// @dev This emits when the "delegate operator" for an account is changed | |
/// or reaffirmed. The zero address indicates there is no delegate | |
/// operator. | |
event Delegation(address indexed _owner, address indexed _delegate); | |
/// @notice Count all deeds assigned to an owner | |
/// @dev Deeds assigned to zero address are considered invalid, and this | |
/// function throws for queries about the zero address. | |
/// @param _owner An address for whom to query the balance | |
/// @return The number of deeds owned by `_owner`, possibly zero | |
function balanceOf(address _owner) external view returns (uint256 _balance); | |
/// @notice Find the owner of a deed | |
/// @param _deedId The identifier for a deed we are inspecting | |
/// @dev Deeds assigned to zero address are considered invalid, and queries | |
/// about them do throw. | |
/// @return The address of the owner of the deed | |
function ownerOf(uint256 _deedId) external view returns (address _owner); | |
/// @notice Set a new owner for a deed | |
/// @dev Throws unless `msg.sender` is the current deed owner, the "delegate | |
/// operator" of the current deed owner, or the "approved deed controller". | |
/// Throws if `_to` currently owns the deed. Throws if `_to` is the zero | |
/// address. | |
/// @param _to The new owner for the deed | |
/// @param _deedId The deed to transfer | |
function transfer(address _to, uint256 _deedId) external payable; | |
/// @notice Set or reaffirm the "approved deed controller" for a deed | |
/// @dev The zero address indicates there is no approved deed controller. | |
/// @dev Throws unless `msg.sender` is the current deed owner, or the | |
/// "delegate operator" of the current deed owner. | |
/// @param _approved The new approved deed controller | |
/// @param _deedId The deed to approve | |
function approve(address _approved, uint256 _deedId) external payable; | |
/// @notice Set or reaffirm the "delegate operator" for this account | |
/// @dev The zero address indicates there is no delegate operator. | |
/// @param _delegate The new delegate operator | |
function delegate(address _delegate) external; | |
// CONFORMANCE TO ERC-165 (DRAFT) ////////////////////////////////////////// | |
/// @notice Query if this implements an interface | |
/// @param interfaceID The interface identifier, as specified in ERC-165 | |
/// @dev Interface identification is specified in ERC-165. This function | |
/// uses less than 30,000 gas. | |
/// @return `true` if the contract implements `interfaceID` and | |
/// `interfaceID` is not 0xffffffff, `false` otherwise | |
function supportsInterface(bytes4 interfaceID) external view returns (bool); | |
} | |
/// @title Optional metadata extension to ERC-721 Deed Standard | |
/// @author William Entriken (https://phor.net) | |
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
/// Note: the ERC-165 (DRAFT) identifier for this interface is 0x2a786f11 | |
interface ERC721Metadata /* is ERC721 */ { | |
/// @notice A descriptive name for a collection of deeds in this contract | |
function name() external pure returns (string _name); | |
/// @notice An abbreviated name for deeds in this contract | |
function symbol() external pure returns (string _symbol); | |
/// @notice A distinct Uniform Resource Identifier (URI) for a given deed. | |
/// @dev Throws if `_deedId` is not a valid deed. URIs are defined in RFC | |
/// 3986. The URI may point to a JSON file that conforms to the "ERC721 | |
/// Metadata JSON Schema". | |
function deedUri(uint256 _deedId) external view returns (string _deedUri); | |
} | |
/// @title Optional enumeration extension to ERC-721 Deed Standard | |
/// @author William Entriken (https://phor.net) | |
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
/// Note: the ERC-165 (DRAFT) identifier for this interface is 0x5576ab6a | |
interface ERC721Enumerable /* is ERC721 */ { | |
/// @notice Count deeds tracked by this contract | |
/// @return A count of valid deeds tracked by this contract, where each one of | |
/// them has an assigned and queryable owner not equal to the zero address | |
function totalSupply() external view returns (uint256 _count); | |
/// @notice Enumerate active deeds | |
/// @dev Throws if `_index` >= `countOfDeeds()`. | |
/// Otherwise must not throw. | |
/// @param _index A counter less than `countOfDeeds()` | |
/// @return The identifier for the `_index`th deed, (sort order not | |
/// specified) | |
function deedByIndex(uint256 _index) external view returns (uint256 _deedId); | |
/// @notice Count of owners which own at least one deed | |
/// Must not throw. | |
/// @return A count of the number of owners which own deeds | |
function countOfOwners() external view returns (uint256 _count); | |
/// @notice Enumerate owners | |
/// @dev Throws if `_index` >= `countOfOwners()` | |
/// Otherwise must not throw. | |
/// @param _index A counter less than `countOfOwners()` | |
/// @return The address of the `_index`th owner (sort order not specified) | |
function ownerByIndex(uint256 _index) external view returns (address _owner); | |
/// @notice Enumerate deeds assigned to an owner | |
/// @dev Throws if `_index` >= `countOfDeedsByOwner(_owner)` or if | |
/// `_owner` is the zero address, representing invalid deeds. | |
/// Otherwise this must not throw. | |
/// @param _owner An address where we are interested in deeds owned by them | |
/// @param _index A counter less than `countOfDeedsByOwner(_owner)` | |
/// @return The identifier for the `_index`th deed assigned to `_owner`, | |
/// (sort order not specified) | |
function deedOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256 _deedId); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment