/ contracts / SpaceshipMarketplace.sol
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  }