SpaceshipMarketplace.sol
1 pragma solidity 0.4.24; 2 3 import "./SpaceshipToken.sol"; 4 import "zeppelin-solidity/contracts/token/ERC721/ERC721Holder.sol"; 5 6 7 /// @title Escrow contract 8 contract SpaceshipMarketplace is ERC721Holder { 9 10 struct Sale { 11 uint spaceshipId; 12 uint price; 13 address owner; 14 } 15 16 SpaceshipToken public token; 17 18 Sale[] public sales; 19 20 mapping(uint => uint) public spaceshipToSale; 21 22 event NewSale(uint indexed spaceshipId, uint price, uint saleId); 23 24 event ShipSold(uint indexed spaceshipId, uint price, address indexed oldOwner, address indexed newOwner); 25 26 /// @notice Constructor 27 /// @param _token Spaceship token address 28 constructor(address _token) public { 29 token = SpaceshipToken(_token); 30 } 31 32 /// @notice Buy token 33 /// @param _saleId Index of sales[] 34 function buy(uint _saleId) public payable { 35 Sale storage s = sales[_saleId]; 36 37 // TODO: uncomment this to avoid the owner buying his own tokens 38 // require(s.owner != msg.sender); 39 require(msg.value >= s.price); 40 41 uint refund = msg.value - s.price; 42 if(refund > 0) 43 msg.sender.transfer(refund); 44 45 s.owner.transfer(s.price); 46 47 emit ShipSold(s.spaceshipId, s.price, s.owner, msg.sender); 48 49 // Transfer the token 50 token.approve(msg.sender, s.spaceshipId); 51 token.safeTransferFrom(address(this), msg.sender, s.spaceshipId); 52 53 // Delete sale 54 delete spaceshipToSale[s.spaceshipId]; 55 Sale replacer = sales[sales.length - 1]; 56 sales[_saleId] = replacer; 57 sales.length--; 58 } 59 60 /// @notice Set token for sale 61 /// @param _spaceshipId Token Id 62 /// @param _price Sale price 63 function forSale(uint _spaceshipId, uint _price){ 64 // You can only sell your own ships 65 require(token.ownerOf(_spaceshipId) == msg.sender); 66 67 token.safeTransferFrom(msg.sender, address(this), _spaceshipId); 68 69 Sale memory s = Sale({ 70 spaceshipId: _spaceshipId, 71 price: _price, 72 owner: msg.sender 73 }); 74 75 uint saleId = sales.push(s) - 1; 76 77 spaceshipToSale[_spaceshipId] = saleId; 78 79 emit NewSale(_spaceshipId, _price, saleId); 80 } 81 82 /// @notice Remove listing 83 /// @param _spaceshipId Spaceship Id 84 function withdraw(uint _spaceshipId){ 85 require(sales[spaceshipToSale[_spaceshipId]].owner == msg.sender); 86 87 delete sales[spaceshipToSale[_spaceshipId]]; 88 delete spaceshipToSale[_spaceshipId]; 89 90 token.safeTransferFrom(address(this), msg.sender, _spaceshipId); 91 } 92 93 /// @notice Ships for sale quantity 94 function nSale() public view returns(uint) { 95 return sales.length; 96 } 97 98 }