pragma solidity ^0.4.23; import "./ERC721.sol"; import "./SafeMath.sol"; import "./ShowHelper.sol"; contract ShowOwnership is ERC721, ShowHelper { event WantToExchange(uint mine, uint yours); event RefuseToExchange(uint indexed yours); using SafeMath for uint256; mapping (uint=>address) showApprovals; mapping (uint=>uint) public showExchange; // 0: not for exchange, n: exchange for the n_th show function balanceOf(address _owner) public view returns (uint256 _balance) { return ownerShowCount[_owner]; } function ownerOf(uint256 _tokenId) public view returns (address _owner) { return showToOwner[_tokenId]; } function transfer(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) { _transfer(msg.sender, _to, _tokenId); } function approve(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) { showApprovals[_tokenId] = _to; emit Approval(msg.sender, _to, _tokenId); } function takeOwnership(uint256 _tokenId) public { require(msg.sender == showApprovals[_tokenId] && showExchange[_tokenId] == 0); address owner = ownerOf(_tokenId); _transfer(owner, msg.sender, _tokenId); } function wantToExchange(uint mine, uint yours) public onlyOwnerOf(mine) { if (msg.sender == showApprovals[yours] && showExchange[yours] == mine.add(1)) { showExchange[yours] = 0; transfer(ownerOf(yours), mine); takeOwnership(yours); } else { showExchange[mine] = yours.add(1); showApprovals[mine] = ownerOf(yours); emit WantToExchange(mine, yours); } } function refuseToExchange(uint yours) public { require(msg.sender == showApprovals[yours]); require(showExchange[yours] != 0); require(msg.sender == showToOwner[showExchange[yours].sub(1)]); showApprovals[yours] = address(0); showExchange[yours] = 0; } function _transfer(address _from, address _to, uint _tokenId) internal { ownerShowCount[_from] = ownerShowCount[_from].sub(1); ownerShowCount[_to] = ownerShowCount[_to].add(1); showToOwner[_tokenId] = _to; emit Transfer(_from, _to, _tokenId); } }