pragma solidity ^0.4.24; /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */ contract Ownable { address private _owner; event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ constructor() internal { _owner = msg.sender; emit OwnershipTransferred(address(0), _owner); } /** * @return the address of the owner. */ function owner() public view returns(address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner()); _; } /** * @return true if `msg.sender` is the owner of the contract. */ function isOwner() public view returns(bool) { return msg.sender == _owner; } /** * @dev Allows the current owner to relinquish control of the contract. * @notice Renouncing to ownership will leave the contract without an owner. * It will not be possible to call the functions with the `onlyOwner` * modifier anymore. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0)); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } contract CryptoCanvas is Ownable { event PixelChangedOwner(uint pixelId, address newOwner); event PixelChangedColor(uint pixelId, uint8 colorRed, uint8 colorGreen, uint8 colorBlue); uint256 minimumPrice = 0.0001 ether; uint256 percentFee = 100; address feeAddress = 0xd75d32755D7cA56C455C5FE6cEf7B956A5e88ac8; // Canvas size details // Can be increased (but not decreased) by contract owner // New pixel are automatically generated on resize uint256 canvasWidth = 0; uint256 canvasHeight = 0; // Divide by 100 to get percent uint32 percentPriceIncreasePerSale = 15000; uint32 percentPriceDropPerDay = 100; struct Pixel { uint256 lastSalePrice; uint256 lastSaleTime; uint16 positionX; uint16 positionY; uint8 colorRed; uint8 colorGreen; uint8 colorBlue; } Pixel[] public pixels; mapping (uint256 => address) public pixelIndexToOwner; // Keeps track of pending payments of sold pixels mapping (address => uint) pendingWithdrawals; function getMinimumPixelPrice(uint _pixelId) public view returns (uint256) { Pixel memory pixel = pixels[_pixelId]; uint256 daysSinceLastSale = (now - pixel.lastSaleTime) / 1 days; uint256 newSalePrice = pixel.lastSalePrice * percentPriceIncreasePerSale / 10000; uint256 priceDecay = newSalePrice * daysSinceLastSale * percentPriceDropPerDay / 10000; return newSalePrice - priceDecay; } function _changePixelOwner(uint _pixelId, address _newOwner) internal { pixelIndexToOwner[_pixelId] = _newOwner; emit PixelChangedOwner(_pixelId, _newOwner); } function buyPixel(uint _pixelId) public payable returns (bool) { if (msg.value > getMinimumPixelPrice(_pixelId)) { pendingWithdrawals[pixelIndexToOwner[_pixelId]] += (msg.value * (10000 - percentFee) / 10000); pendingWithdrawals[feeAddress] += (msg.value * percentFee / 10000); pixelIndexToOwner[_pixelId] = msg.sender; pixels[_pixelId].lastSalePrice = msg.value; pixels[_pixelId].lastSaleTime = now; return true; } else { return false; } } function colorPixel(uint _pixelId, uint8 _colorRed, uint8 _colorGreen, uint8 _colorBlue) public { require(msg.sender == pixelIndexToOwner[_pixelId]); pixels[_pixelId].colorRed = _colorRed; pixels[_pixelId].colorGreen = _colorGreen; pixels[_pixelId].colorBlue = _colorBlue; emit PixelChangedColor(_pixelId, _colorRed, _colorGreen, _colorBlue); } // Allows user to withdraw their pending funds function withdraw() public { uint amount = pendingWithdrawals[msg.sender]; require(amount != 0); require(address(this).balance >= amount); pendingWithdrawals[msg.sender] = 0; msg.sender.transfer(amount); } }
0.4.24