-
Notifications
You must be signed in to change notification settings - Fork 228
/
KittyOwnership.sol
180 lines (159 loc) · 7.19 KB
/
KittyOwnership.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
pragma solidity ^0.4.18;
import "./KittyBase.sol";
import "./ERC721Draft.sol";
/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant.
/// @author Axiom Zen (https://www.axiomzen.co)
/// @dev Ref: https://github.com/ethereum/EIPs/issues/721
/// See the KittyCore contract documentation to understand how the various contract facets are arranged.
contract KittyOwnership is KittyBase, ERC721 {
/// @notice Name and symbol of the non fungible token, as defined in ERC721.
string public name = "CryptoKitties";
string public symbol = "CK";
// bool public implementsERC721 = true;
//
function implementsERC721() public pure returns (bool)
{
return true;
}
// Internal utility functions: These functions all assume that their input arguments
// are valid. We leave it to public methods to sanitize their inputs and follow
// the required logic.
/// @dev Checks if a given address is the current owner of a particular Kitty.
/// @param _claimant the address we are validating against.
/// @param _tokenId kitten id, only valid when > 0
function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) {
return kittyIndexToOwner[_tokenId] == _claimant;
}
/// @dev Checks if a given address currently has transferApproval for a particular Kitty.
/// @param _claimant the address we are confirming kitten is approved for.
/// @param _tokenId kitten id, only valid when > 0
function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) {
return kittyIndexToApproved[_tokenId] == _claimant;
}
/// @dev Marks an address as being approved for transferFrom(), overwriting any previous
/// approval. Setting _approved to address(0) clears all transfer approval.
/// NOTE: _approve() does NOT send the Approval event. This is intentional because
/// _approve() and transferFrom() are used together for putting Kitties on auction, and
/// there is no value in spamming the log with Approval events in that case.
function _approve(uint256 _tokenId, address _approved) internal {
kittyIndexToApproved[_tokenId] = _approved;
}
/// @dev Transfers a kitty owned by this contract to the specified address.
/// Used to rescue lost kitties. (There is no "proper" flow where this contract
/// should be the owner of any Kitty. This function exists for us to reassign
/// the ownership of Kitties that users may have accidentally sent to our address.)
/// @param _kittyId - ID of kitty
/// @param _recipient - Address to send the cat to
function rescueLostKitty(uint256 _kittyId, address _recipient) public onlyCOO whenNotPaused {
require(_owns(this, _kittyId));
_transfer(this, _recipient, _kittyId);
}
/// @notice Returns the number of Kitties owned by a specific address.
/// @param _owner The owner address to check.
/// @dev Required for ERC-721 compliance
function balanceOf(address _owner) public view returns (uint256 count) {
return ownershipTokenCount[_owner];
}
/// @notice Transfers a Kitty to another address. If transferring to a smart
/// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or
/// CryptoKitties specifically) or your Kitty may be lost forever. Seriously.
/// @param _to The address of the recipient, can be a user or contract.
/// @param _tokenId The ID of the Kitty to transfer.
/// @dev Required for ERC-721 compliance.
function transfer(
address _to,
uint256 _tokenId
)
public
whenNotPaused
{
// Safety check to prevent against an unexpected 0x0 default.
require(_to != address(0));
// You can only send your own cat.
require(_owns(msg.sender, _tokenId));
// Reassign ownership, clear pending approvals, emit Transfer event.
_transfer(msg.sender, _to, _tokenId);
}
/// @notice Grant another address the right to transfer a specific Kitty via
/// transferFrom(). This is the preferred flow for transfering NFTs to contracts.
/// @param _to The address to be granted transfer approval. Pass address(0) to
/// clear all approvals.
/// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds.
/// @dev Required for ERC-721 compliance.
function approve(
address _to,
uint256 _tokenId
)
public
whenNotPaused
{
// Only an owner can grant transfer approval.
require(_owns(msg.sender, _tokenId));
// Register the approval (replacing any previous approval).
_approve(_tokenId, _to);
// Emit approval event.
Approval(msg.sender, _to, _tokenId);
}
/// @notice Transfer a Kitty owned by another address, for which the calling address
/// has previously been granted transfer approval by the owner.
/// @param _from The address that owns the Kitty to be transfered.
/// @param _to The address that should take ownership of the Kitty. Can be any address,
/// including the caller.
/// @param _tokenId The ID of the Kitty to be transferred.
/// @dev Required for ERC-721 compliance.
function transferFrom(
address _from,
address _to,
uint256 _tokenId
)
public
whenNotPaused
{
// Check for approval and valid ownership
require(_approvedFor(msg.sender, _tokenId));
require(_owns(_from, _tokenId));
// Reassign ownership (also clears pending approvals and emits Transfer event).
_transfer(_from, _to, _tokenId);
}
/// @notice Returns the total number of Kitties currently in existence.
/// @dev Required for ERC-721 compliance.
function totalSupply() public view returns (uint) {
return kitties.length - 1;
}
/// @notice Returns the address currently assigned ownership of a given Kitty.
/// @dev Required for ERC-721 compliance.
function ownerOf(uint256 _tokenId)
public
view
returns (address owner)
{
owner = kittyIndexToOwner[_tokenId];
require(owner != address(0));
}
/// @notice Returns the nth Kitty assigned to an address, with n specified by the
/// _index argument.
/// @param _owner The owner whose Kitties we are interested in.
/// @param _index The zero-based index of the cat within the owner's list of cats.
/// Must be less than balanceOf(_owner).
/// @dev This method MUST NEVER be called by smart contract code. It will almost
/// certainly blow past the block gas limit once there are a large number of
/// Kitties in existence. Exists only to allow off-chain queries of ownership.
/// Optional method for ERC-721.
function tokensOfOwnerByIndex(address _owner, uint256 _index)
external
view
returns (uint256 tokenId)
{
uint256 count = 0;
for (uint256 i = 1; i <= totalSupply(); i++) {
if (kittyIndexToOwner[i] == _owner) {
if (count == _index) {
return i;
} else {
count++;
}
}
}
revert();
}
}