/** * Source Code first verified at https://etherscan.io on Sunday, May 5, 2019 (UTC) */ pragma solidity ^0.5.0; contract DSMath { function add(uint x, uint y) internal pure returns (uint z) { require((z = x + y) >= x, "ds-math-add-overflow"); } function sub(uint x, uint y) internal pure returns (uint z) { require((z = x - y) <= x, "ds-math-sub-underflow"); } function mul(uint x, uint y) internal pure returns (uint z) { require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); } function min(uint x, uint y) internal pure returns (uint z) { return x <= y ? x : y; } function max(uint x, uint y) internal pure returns (uint z) { return x >= y ? x : y; } function imin(int x, int y) internal pure returns (int z) { return x <= y ? x : y; } function imax(int x, int y) internal pure returns (int z) { return x >= y ? x : y; } uint constant WAD = 10 ** 18; uint constant RAY = 10 ** 27; function wmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), WAD / 2) / WAD; } function rmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), RAY / 2) / RAY; } function wdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, WAD), y / 2) / y; } function rdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, RAY), y / 2) / y; } function rpow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : RAY; for (n /= 2; n != 0; n /= 2) { x = rmul(x, x); if (n % 2 != 0) { z = rmul(z, x); } } } } contract Bank is DSMath { mapping(address => uint) public balances; function deposit() public payable returns (uint balance) { balances[msg.sender] = add(balances[msg.sender], msg.value); return balances[msg.sender]; } function withdraw(uint amount) public returns (uint remainingBalance){ require(min(amount,balances[msg.sender]) == amount); balances[msg.sender] = sub(balances[msg.sender],amount); msg.sender.transfer(amount); return balances[msg.sender]; } function balance() view public returns (uint) { return balances[msg.sender]; } } contract OwnsArtSplit is DSMath, Bank{ struct Bundle{ address owner; uint decayedTime; } //8 bits: exponent //124 bits: generation //124 bits: sibling uint public constant exponentMask = 0xff00000000000000000000000000000000000000000000000000000000000000; uint public constant generationMask = 0x00fffffffffffffffffffffffffffffff0000000000000000000000000000000; uint public constant siblingMask = 0xff0000000000000000000000000000000fffffffffffffffffffffffffffffff; mapping(uint => Bundle) public bundleTable; //maps the bundle exponent to find sibling for that bundle size //next sibling for generation mapping(uint8 => mapping(uint128 => uint128)) public siblingTable; address public artist; uint public constant price = 0.01 ether; uint public constant resaleFee = 0.001 ether; uint public constant maxBundlesPerPurchase = 0xff; uint public constant maxBundleExponent = 16; uint public constant artDecayTime = 30 days; uint public constant itemsPerBundle = 10; bool private buyArtMutex = false; event LogPurchase(uint[] destroyedBundleID, uint[] createdBundleID1, uint[] createdBundleID2, uint decay, address buyer); event LogBundling(uint[] bundledIDs, uint newBundleID, uint decay, address bundler); event LogUnbundling(uint unbundledID, uint[] newBundleIDs, uint decay, address bundler); constructor() public { artist = msg.sender; bundleTable[0] = Bundle(msg.sender, now+artDecayTime); siblingTable[0][0] = 1; } function buyArtworkBundles(uint[] memory bundleIDs) public{ require(min(bundleIDs.length,maxBundlesPerPurchase)==bundleIDs.length,"Cannot buy too many bundles at once."); uint8 numberOfBundles = uint8(bundleIDs.length); require(numberOfBundles != 0,"Must buy more than zero bundles."); uint[] memory createdBundleID1 = new uint[](numberOfBundles); uint[] memory createdBundleID2 = new uint[](numberOfBundles); require(!buyArtMutex,"Only one person can buy bundles at the same time. Try again later."); buyArtMutex = true; for (uint i=0; i>124),uint128((bundleID&siblingMask)),uint8((bundleID&exponentMask)>>248)); } function generateBundleID(uint128 generation, uint128 sibling, uint8 exponent) pure public returns(uint bundleID){ return (uint(generation) << 124) | uint(sibling) | (uint(exponent) << 248); } function testValidBundle(Bundle memory bundle) view private returns (bool){ return (bundle.decayedTime != 0) && (!isDecayed(bundle.decayedTime)); } function isDecayed(uint decayedTime) view public returns (bool){ return (min(now,decayedTime) != now); } }