Skip to content

Instantly share code, notes, and snippets.

@MidnightLightning
Last active June 26, 2018 20:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MidnightLightning/00bc71c4a78f7aa661ab1d2b97a8e90a to your computer and use it in GitHub Desktop.
Save MidnightLightning/00bc71c4a78f7aa661ab1d2b97a8e90a to your computer and use it in GitHub Desktop.
CardboardUnicorns
pragma solidity ^0.4.11;
contract CardboardUnicorns {
address public owner;
function mint(address who, uint value);
function changeOwner(address _newOwner);
function withdraw();
function withdrawForeignTokens(address _tokenContract);
}
contract RealUnicornCongress {
uint public priceOfAUnicornInFinney;
}
contract ForeignToken {
function balanceOf(address _owner) constant returns (uint256);
function transfer(address _to, uint256 _value) returns (bool);
}
contract CardboardUnicornAssembler {
address public cardboardUnicornTokenAddress;
address public realUnicornAddress = 0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359;
address public owner = msg.sender;
uint public pricePerUnicorn = 1 finney;
uint public lastPriceSetDate = 0;
event PriceUpdate(uint newPrice, address updater);
modifier onlyOwner {
require(msg.sender == owner);
_;
}
/**
* Change ownership of the assembler
*/
function changeOwner(address _newOwner) onlyOwner {
owner = _newOwner;
}
function changeTokenOwner(address _newOwner) onlyOwner {
CardboardUnicorns cu = CardboardUnicorns(cardboardUnicornTokenAddress);
cu.changeOwner(_newOwner);
}
/**
* Change the CardboardUnicorns token contract managed by this contract
*/
function changeCardboardUnicornTokenAddress(address _newTokenAddress) onlyOwner {
CardboardUnicorns cu = CardboardUnicorns(_newTokenAddress);
require(cu.owner() == address(this)); // We must be the owner of the token
cardboardUnicornTokenAddress = _newTokenAddress;
}
/**
* Change the real unicorn contract location.
* This contract is used as a price reference; should the Ethereum Foundation
* re-deploy their contract, this should be called to update the reference.
*/
function changeRealUnicornAddress(address _newUnicornAddress) onlyOwner {
realUnicornAddress = _newUnicornAddress;
}
function withdraw(bool _includeToken) onlyOwner {
if (_includeToken) {
// First have the token contract send all its funds to its owner (which is us)
CardboardUnicorns cu = CardboardUnicorns(cardboardUnicornTokenAddress);
cu.withdraw();
}
// Then send that whole total to our owner
owner.transfer(this.balance);
}
function withdrawForeignTokens(address _tokenContract, bool _includeToken) onlyOwner {
ForeignToken token = ForeignToken(_tokenContract);
if (_includeToken) {
// First have the token contract send its tokens to its owner (which is us)
CardboardUnicorns cu = CardboardUnicorns(cardboardUnicornTokenAddress);
cu.withdrawForeignTokens(_tokenContract);
}
// Then send that whole total to our owner
uint256 amount = token.balanceOf(address(this));
token.transfer(owner, amount);
}
/**
* Update the price of a CardboardUnicorn to be 1/1000 a real Unicorn's price
*/
function updatePriceFromRealUnicornPrice() {
require(block.timestamp > lastPriceSetDate + 7 days); // If owner set the price, cannot sync right after
RealUnicornCongress congress = RealUnicornCongress(realUnicornAddress);
pricePerUnicorn = (congress.priceOfAUnicornInFinney() * 1 finney) / 1000;
PriceUpdate(pricePerUnicorn, msg.sender);
}
/**
* Set a specific price for a CardboardUnicorn
*/
function setPrice(uint _newPrice) onlyOwner {
pricePerUnicorn = _newPrice;
lastPriceSetDate = block.timestamp;
PriceUpdate(pricePerUnicorn, msg.sender);
}
/**
* Strap a horn to a horse!
*/
function assembleUnicorn() payable {
if (msg.value >= pricePerUnicorn) {
CardboardUnicorns cu = CardboardUnicorns(cardboardUnicornTokenAddress);
cu.mint(msg.sender, msg.value / pricePerUnicorn);
owner.transfer(msg.value);
}
}
function() payable {
assembleUnicorn();
}
}
pragma solidity ^0.4.11;
contract ForeignToken {
function balanceOf(address _owner) constant returns (uint256);
function transfer(address _to, uint256 _value) returns (bool);
}
/**
* Math operations with safety checks
*/
library SafeMath {
function mul(uint a, uint b) internal returns (uint) {
uint c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint a, uint b) internal returns (uint) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint a, uint b) internal returns (uint) {
assert(b <= a);
return a - b;
}
function add(uint a, uint b) internal returns (uint) {
uint c = a + b;
assert(c >= a);
return c;
}
function max64(uint64 a, uint64 b) internal constant returns (uint64) {
return a >= b ? a : b;
}
function min64(uint64 a, uint64 b) internal constant returns (uint64) {
return a < b ? a : b;
}
function max256(uint256 a, uint256 b) internal constant returns (uint256) {
return a >= b ? a : b;
}
function min256(uint256 a, uint256 b) internal constant returns (uint256) {
return a < b ? a : b;
}
function assert(bool assertion) internal {
if (!assertion) {
throw;
}
}
}
contract CardboardUnicorns {
using SafeMath for uint;
string public name = "HorseWithACheapCardboardHorn";
string public symbol = "HWACCH";
uint public decimals = 0;
uint public totalSupply = 0;
mapping(address => uint) balances;
mapping (address => mapping (address => uint)) allowed;
address public owner = msg.sender;
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
event Minted(address indexed owner, uint value);
/**
* Fix for the ERC20 short address attack.
*/
modifier onlyPayloadSize(uint size) {
if(msg.data.length < size + 4) {
throw;
}
_;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
/**
* Change ownership of the token
*/
function changeOwner(address _newOwner) onlyOwner {
owner = _newOwner;
}
function withdraw() onlyOwner {
owner.transfer(this.balance);
}
function withdrawForeignTokens(address _tokenContract) onlyOwner {
ForeignToken token = ForeignToken(_tokenContract);
uint256 amount = token.balanceOf(address(this));
token.transfer(owner, amount);
}
/**
* Generate new tokens.
* Can only be done by the owner of the contract
*/
function mint(address _who, uint _value) onlyOwner {
balances[_who] = balances[_who].add(_value);
totalSupply = totalSupply.add(_value);
Minted(_who, _value);
}
/**
* Get the token balance of the specified address
*/
function balanceOf(address _who) constant returns (uint balance) {
return balances[_who];
}
/**
* Transfer token to another address
*/
function transfer(address _to, uint _value) onlyPayloadSize(2 * 32) {
require(_to != address(this)); // Don't send tokens back to the contract!
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
Transfer(msg.sender, _to, _value);
}
/**
* Transfer tokens from an different address to another address.
* Need to have been granted an allowance to do this before triggering.
*/
function transferFrom(address _from, address _to, uint _value) onlyPayloadSize(3 * 32) {
var _allowance = allowed[_from][msg.sender];
// Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
// if (_value > _allowance) throw;
balances[_to] = balances[_to].add(_value);
balances[_from] = balances[_from].sub(_value);
allowed[_from][msg.sender] = _allowance.sub(_value);
Transfer(_from, _to, _value);
}
/**
* Approve the indicated address to spend the specified amount of tokens on the sender's behalf
*/
function approve(address _spender, uint _value) {
// Ensure allowance is zero if attempting to set to a non-zero number
// This helps manage an edge-case race condition better: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw;
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
}
/**
* Check how many tokens the indicated address can spend on behalf of the owner
*/
function allowance(address _owner, address _spender) constant returns (uint remaining) {
return allowed[_owner][_spender];
}
}
pragma solidity ^0.4.11;
contract ERC20Token {
function balanceOf(address _who) constant returns (uint balance);
function allowance(address _owner, address _spender) constant returns (uint remaining);
function transferFrom(address _from, address _to, uint _value);
function transfer(address _to, uint _value);
}
contract GroveAPI {
function insert(bytes32 indexName, bytes32 id, int value) public;
}
/**
* Math operations with safety checks
*/
library SafeMath {
function mul(uint a, uint b) internal returns (uint) {
uint c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint a, uint b) internal returns (uint) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint a, uint b) internal returns (uint) {
assert(b <= a);
return a - b;
}
function add(uint a, uint b) internal returns (uint) {
uint c = a + b;
assert(c >= a);
return c;
}
function max64(uint64 a, uint64 b) internal constant returns (uint64) {
return a >= b ? a : b;
}
function min64(uint64 a, uint64 b) internal constant returns (uint64) {
return a < b ? a : b;
}
function max256(uint256 a, uint256 b) internal constant returns (uint256) {
return a >= b ? a : b;
}
function min256(uint256 a, uint256 b) internal constant returns (uint256) {
return a < b ? a : b;
}
}
contract UnicornRanch {
using SafeMath for uint;
enum VisitType { Spa, Afternoon, Day, Overnight, Week, Extended }
enum VisitState { InProgress, Completed, Repossessed }
struct Visit {
uint unicornCount;
VisitType t;
uint startBlock;
uint expiresBlock;
VisitState state;
uint completedBlock;
uint completedCount;
}
struct VisitMeta {
address owner;
uint index;
}
address public cardboardUnicornTokenAddress;
address public groveAddress;
address public owner = msg.sender;
mapping (address => Visit[]) bookings;
mapping (bytes32 => VisitMeta) public bookingMetadataForKey;
mapping (uint8 => uint) public visitLength;
mapping (uint8 => uint) public visitCost;
uint public visitingUnicorns = 0;
uint public repossessionBlocks = 43200;
uint8 public repossessionBountyPerTen = 2;
uint8 public repossessionBountyPerHundred = 25;
uint public birthBlockThreshold = 43860;
uint8 public birthPerTen = 1;
uint8 public birthPerHundred = 15;
event NewBooking(address indexed _who, uint indexed _index, VisitType indexed _type, uint _unicornCount);
event BookingUpdate(address indexed _who, uint indexed _index, VisitState indexed _newState, uint _unicornCount);
event RepossessionBounty(address indexed _who, uint _unicornCount);
event DonationReceived(address indexed _who, uint _unicornCount);
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function UnicornRanch() {
visitLength[uint8(VisitType.Spa)] = 720;
visitLength[uint8(VisitType.Afternoon)] = 1440;
visitLength[uint8(VisitType.Day)] = 2880;
visitLength[uint8(VisitType.Overnight)] = 8640;
visitLength[uint8(VisitType.Week)] = 60480;
visitLength[uint8(VisitType.Extended)] = 120960;
visitCost[uint8(VisitType.Spa)] = 0;
visitCost[uint8(VisitType.Afternoon)] = 0;
visitCost[uint8(VisitType.Day)] = 10 szabo;
visitCost[uint8(VisitType.Overnight)] = 30 szabo;
visitCost[uint8(VisitType.Week)] = 50 szabo;
visitCost[uint8(VisitType.Extended)] = 70 szabo;
}
function getBookingCount(address _who) constant returns (uint count) {
return bookings[_who].length;
}
function getBooking(address _who, uint _index) constant returns (uint _unicornCount, VisitType _type, uint _startBlock, uint _expiresBlock, VisitState _state, uint _completedBlock, uint _completedCount) {
Visit storage v = bookings[_who][_index];
return (v.unicornCount, v.t, v.startBlock, v.expiresBlock, v.state, v.completedBlock, v.completedCount);
}
function bookSpaVisit(uint _unicornCount) payable {
return addBooking(VisitType.Spa, _unicornCount);
}
function bookAfternoonVisit(uint _unicornCount) payable {
return addBooking(VisitType.Afternoon, _unicornCount);
}
function bookDayVisit(uint _unicornCount) payable {
return addBooking(VisitType.Day, _unicornCount);
}
function bookOvernightVisit(uint _unicornCount) payable {
return addBooking(VisitType.Overnight, _unicornCount);
}
function bookWeekVisit(uint _unicornCount) payable {
return addBooking(VisitType.Week, _unicornCount);
}
function bookExtendedVisit(uint _unicornCount) payable {
return addBooking(VisitType.Extended, _unicornCount);
}
function addBooking(VisitType _type, uint _unicornCount) payable {
if (_type == VisitType.Afternoon) {
return donateUnicorns(availableBalance(msg.sender));
}
require(msg.value >= visitCost[uint8(_type)].mul(_unicornCount)); // Must be paying proper amount
ERC20Token cardboardUnicorns = ERC20Token(cardboardUnicornTokenAddress);
cardboardUnicorns.transferFrom(msg.sender, address(this), _unicornCount); // Transfer the actual asset
visitingUnicorns = visitingUnicorns.add(_unicornCount);
uint expiresBlock = block.number.add(visitLength[uint8(_type)]); // Calculate when this booking will be done
// Add the booking to the ledger
bookings[msg.sender].push(Visit(
_unicornCount,
_type,
block.number,
expiresBlock,
VisitState.InProgress,
0,
0
));
uint newIndex = bookings[msg.sender].length - 1;
bytes32 uniqueKey = keccak256(msg.sender, newIndex); // Create a unique key for this booking
// Add a reference for that key, to find the metadata about it later
bookingMetadataForKey[uniqueKey] = VisitMeta(
msg.sender,
newIndex
);
if (groveAddress > 0) {
// Insert into Grove index for applications to query
GroveAPI g = GroveAPI(groveAddress);
g.insert("bookingExpiration", uniqueKey, int(expiresBlock));
}
// Send event about this new booking
NewBooking(msg.sender, newIndex, _type, _unicornCount);
}
function completeBooking(uint _index) {
require(bookings[msg.sender].length > _index); // Sender must have at least this many bookings
Visit storage v = bookings[msg.sender][_index];
require(block.number >= v.expiresBlock); // Expired time must be past
require(v.state == VisitState.InProgress); // Visit must not be complete or repossessed
uint unicornsToReturn = v.unicornCount;
ERC20Token cardboardUnicorns = ERC20Token(cardboardUnicornTokenAddress);
// Determine if any births occurred
uint birthCount = 0;
if (SafeMath.sub(block.number, v.startBlock) >= birthBlockThreshold) {
if (v.unicornCount >= 100) {
birthCount = uint(birthPerHundred).mul(v.unicornCount / 100);
} else if (v.unicornCount >= 10) {
birthCount = uint(birthPerTen).mul(v.unicornCount / 10);
}
}
if (birthCount > 0) {
uint availableUnicorns = cardboardUnicorns.balanceOf(address(this)) - visitingUnicorns;
if (availableUnicorns < birthCount) {
birthCount = availableUnicorns;
}
unicornsToReturn = unicornsToReturn.add(birthCount);
}
// Update the status of the Visit
v.state = VisitState.Completed;
v.completedBlock = block.number;
v.completedCount = unicornsToReturn;
bookings[msg.sender][_index] = v;
// Transfer the asset back to the owner
visitingUnicorns = visitingUnicorns.sub(v.unicornCount);
cardboardUnicorns.transfer(msg.sender, unicornsToReturn);
// Send event about this update
BookingUpdate(msg.sender, _index, VisitState.Completed, unicornsToReturn);
}
function repossessBooking(address _who, uint _index) {
require(bookings[_who].length > _index); // Address in question must have at least this many bookings
Visit storage v = bookings[_who][_index];
require(block.number > v.expiresBlock.add(repossessionBlocks)); // Repossession time must be past
require(v.state == VisitState.InProgress); // Visit must not be complete or repossessed
visitingUnicorns = visitingUnicorns.sub(v.unicornCount);
// Send event about this update
BookingUpdate(_who, _index, VisitState.Repossessed, v.unicornCount);
// Calculate Bounty amount
uint bountyCount = 1;
if (v.unicornCount >= 100) {
bountyCount = uint(repossessionBountyPerHundred).mul(v.unicornCount / 100);
} else if (v.unicornCount >= 10) {
bountyCount = uint(repossessionBountyPerTen).mul(v.unicornCount / 10);
}
// Send bounty to bounty hunter
ERC20Token cardboardUnicorns = ERC20Token(cardboardUnicornTokenAddress);
cardboardUnicorns.transfer(msg.sender, bountyCount);
// Send event about the bounty payout
RepossessionBounty(msg.sender, bountyCount);
// Update the status of the Visit
v.state = VisitState.Repossessed;
v.completedBlock = block.number;
v.completedCount = v.unicornCount - bountyCount;
bookings[_who][_index] = v;
}
function availableBalance(address _who) internal returns (uint) {
ERC20Token cardboardUnicorns = ERC20Token(cardboardUnicornTokenAddress);
uint count = cardboardUnicorns.allowance(_who, address(this));
if (count == 0) {
return 0;
}
uint balance = cardboardUnicorns.balanceOf(_who);
if (balance < count) {
return balance;
}
return count;
}
function() payable {
if (cardboardUnicornTokenAddress == 0) {
return;
}
return donateUnicorns(availableBalance(msg.sender));
}
function donateUnicorns(uint _unicornCount) payable {
if (_unicornCount == 0) {
return;
}
ERC20Token cardboardUnicorns = ERC20Token(cardboardUnicornTokenAddress);
cardboardUnicorns.transferFrom(msg.sender, address(this), _unicornCount);
DonationReceived(msg.sender, _unicornCount);
}
/**
* Change ownership of the Ranch
*/
function changeOwner(address _newOwner) onlyOwner {
owner = _newOwner;
}
/**
* Change the outside contracts used by this contract
*/
function changeCardboardUnicornTokenAddress(address _newTokenAddress) onlyOwner {
cardboardUnicornTokenAddress = _newTokenAddress;
}
function changeGroveAddress(address _newAddress) onlyOwner {
groveAddress = _newAddress;
}
/**
* Update block durations for various types of visits
*/
function changeVisitLengths(uint _spa, uint _afternoon, uint _day, uint _overnight, uint _week, uint _extended) onlyOwner {
visitLength[uint8(VisitType.Spa)] = _spa;
visitLength[uint8(VisitType.Afternoon)] = _afternoon;
visitLength[uint8(VisitType.Day)] = _day;
visitLength[uint8(VisitType.Overnight)] = _overnight;
visitLength[uint8(VisitType.Week)] = _week;
visitLength[uint8(VisitType.Extended)] = _extended;
}
/**
* Update ether costs for various types of visits
*/
function changeVisitCosts(uint _spa, uint _afternoon, uint _day, uint _overnight, uint _week, uint _extended) onlyOwner {
visitCost[uint8(VisitType.Spa)] = _spa;
visitCost[uint8(VisitType.Afternoon)] = _afternoon;
visitCost[uint8(VisitType.Day)] = _day;
visitCost[uint8(VisitType.Overnight)] = _overnight;
visitCost[uint8(VisitType.Week)] = _week;
visitCost[uint8(VisitType.Extended)] = _extended;
}
/**
* Update bounty reward settings
*/
function changeRepoSettings(uint _repoBlocks, uint8 _repoPerTen, uint8 _repoPerHundred) onlyOwner {
repossessionBlocks = _repoBlocks;
repossessionBountyPerTen = _repoPerTen;
repossessionBountyPerHundred = _repoPerHundred;
}
/**
* Update birth event settings
*/
function changeBirthSettings(uint _birthBlocks, uint8 _birthPerTen, uint8 _birthPerHundred) onlyOwner {
birthBlockThreshold = _birthBlocks;
birthPerTen = _birthPerTen;
birthPerHundred = _birthPerHundred;
}
function withdraw() onlyOwner {
owner.transfer(this.balance); // Send all ether in this contract to this contract's owner
}
function withdrawForeignTokens(address _tokenContract) onlyOwner {
ERC20Token token = ERC20Token(_tokenContract);
token.transfer(owner, token.balanceOf(address(this))); // Send all owned tokens to this contract's owner
}
}
pragma solidity ^0.4.11;
contract ERC20Token {
function balanceOf(address _who) constant returns (uint balance);
function transferFrom(address _from, address _to, uint _value);
function transfer(address _to, uint _value);
}
contract UnicornRanch {
enum VisitType { Spa, Afternoon, Day, Overnight, Week, Extended }
enum VisitState { InProgress, Completed, Repossessed }
function getBooking(address _who, uint _index) constant returns (uint _unicornCount, VisitType _type, uint _startBlock, uint _expiresBlock, VisitState _state, uint _completedBlock, uint _completedCount);
}
/**
* Math operations with safety checks
*/
library SafeMath {
function mul(uint a, uint b) internal returns (uint) {
uint c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint a, uint b) internal returns (uint) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint a, uint b) internal returns (uint) {
assert(b <= a);
return a - b;
}
function add(uint a, uint b) internal returns (uint) {
uint c = a + b;
assert(c >= a);
return c;
}
function max64(uint64 a, uint64 b) internal constant returns (uint64) {
return a >= b ? a : b;
}
function min64(uint64 a, uint64 b) internal constant returns (uint64) {
return a < b ? a : b;
}
function max256(uint256 a, uint256 b) internal constant returns (uint256) {
return a >= b ? a : b;
}
function min256(uint256 a, uint256 b) internal constant returns (uint256) {
return a < b ? a : b;
}
}
contract UnicornRefunds {
using SafeMath for uint;
address public cardboardUnicornTokenAddress;
address public unicornRanchAddress;
address public owner = msg.sender;
uint public pricePerUnicorn = 1 finney;
uint public rewardUnicornAmount = 100;
mapping(address => uint) allowedAmounts;
mapping(address => bool) rewardClaimed;
event RewardClaimed(address indexed _who, uint _bookingIndex);
event UnicornsSold(address indexed _who, uint _unicornCount, uint _unicornCost, uint _paymentTotal);
event DonationReceived(address indexed _who, uint _amount, uint _allowanceEarned);
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function getAllowedAmount(address _who) constant returns (uint _amount) {
return allowedAmounts[_who];
}
function claimReward(uint _bookingIndex) {
UnicornRanch ranch = UnicornRanch(unicornRanchAddress);
var (unicornCount, visitType, , , state, , completedCount) = ranch.getBooking(msg.sender, _bookingIndex);
require(state == UnicornRanch.VisitState.Completed); // Must be a visit that's completed (not in progress or repossessed)
require(visitType != UnicornRanch.VisitType.Spa); // Must be longer than a Spa visit
require(completedCount > unicornCount); // Must have triggered the "birth" conditions so the user went home with more than what they send in
require(rewardClaimed[msg.sender] == false); // Must not have already claimed the reward
rewardClaimed[msg.sender] = true;
allowedAmounts[msg.sender] = allowedAmounts[msg.sender].add(rewardUnicornAmount);
RewardClaimed(msg.sender, _bookingIndex);
}
/**
* Sell back a number of unicorn tokens, in exchange for ether.
*/
function sell(uint _unicornCount) {
require(_unicornCount > 0);
allowedAmounts[msg.sender] = allowedAmounts[msg.sender].sub(_unicornCount);
ERC20Token cardboardUnicorns = ERC20Token(cardboardUnicornTokenAddress);
cardboardUnicorns.transferFrom(msg.sender, owner, _unicornCount); // Transfer the actual asset
uint total = pricePerUnicorn.mul(_unicornCount);
msg.sender.transfer(total);
UnicornsSold(msg.sender, _unicornCount, pricePerUnicorn, total);
}
function() payable {
uint count = (msg.value).div(pricePerUnicorn);
allowedAmounts[msg.sender] = allowedAmounts[msg.sender].add(count);
DonationReceived(msg.sender, msg.value, count);
}
/**
* Change ownership
*/
function changeOwner(address _newOwner) onlyOwner {
owner = _newOwner;
}
/**
* Change the outside contracts used by this contract
*/
function changeCardboardUnicornTokenAddress(address _newTokenAddress) onlyOwner {
cardboardUnicornTokenAddress = _newTokenAddress;
}
function changeUnicornRanchAddress(address _newAddress) onlyOwner {
unicornRanchAddress = _newAddress;
}
/**
* Update unicorn price
*/
function changePricePerUnicorn(uint _newPrice) onlyOwner {
pricePerUnicorn = _newPrice;
}
/**
* Update reward amount
*/
function changeRewardAmount(uint _newAmount) onlyOwner {
rewardUnicornAmount = _newAmount;
}
function setAllowance(address _who, uint _amount) onlyOwner {
allowedAmounts[_who] = _amount;
}
function withdraw() onlyOwner {
owner.transfer(this.balance); // Send all ether in this contract to this contract's owner
}
function withdrawForeignTokens(address _tokenContract) onlyOwner {
ERC20Token token = ERC20Token(_tokenContract);
token.transfer(owner, token.balanceOf(address(this))); // Send all owned tokens to this contract's owner
}
}
@MidnightLightning
Copy link
Author

MidnightLightning commented Jun 8, 2017

Load these contracts into the online Remix editor by visiting:

https://remix.ethereum.org#gist=00bc71c4a78f7aa661ab1d2b97a8e90a

@MidnightLightning
Copy link
Author

MidnightLightning commented Jul 1, 2017

Deployed on main blockchain at:
0x2DC588Af5eff094401b1F8016E74E7D46d9E7A31 -- CardboardUnicornAssembler (unicornsRus.eth)
0x69b5357D893fcE82248E83CCd9B0871F5D5d9461 -- CardboardUnicorns (Token)
0x97E7ef310499bE2f97C392B8B16Ddd494Af73E22 -- UnicornRanch (unicornRanch.eth)
0x2F490751589DB68f3C406bF9c14C95Ec7fa26840 -- UnicornRefunds


Deployed on Rinkeby at:
0x13f03daf3884d2924b31047723330599Aa59BC3A -- CardboardUnicornAssembler
0x9308ea90D7A92E0430F2B03e501119Bc7c3bD8fc -- CardboardUnicorns (Token)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment