Skip to content

Commit

Permalink
Flatten transferFrom to minimize state reads
Browse files Browse the repository at this point in the history
  • Loading branch information
abandeali1 committed Jun 19, 2018
1 parent a0fe5a9 commit 59603a7
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 5 deletions.
22 changes: 17 additions & 5 deletions contracts/token/ERC721/ERC721BasicToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,25 @@ contract ERC721BasicToken is SupportsInterfaceWithLookup, ERC721Basic {
)
public
{
require(isApprovedOrOwner(msg.sender, _tokenId));
require(_from != address(0));
address owner = ownerOf(_tokenId);
require(_from == owner);
require(_to != address(0));

clearApproval(_from, _tokenId);
removeTokenFrom(_from, _tokenId);
addTokenTo(_to, _tokenId);
address spender = msg.sender;
require(
spender == owner ||
isApprovedForAll(owner, spender) ||
getApproved(_tokenId) == spender
);

if (tokenApprovals[_tokenId] != address(0)) {
tokenApprovals[_tokenId] = address(0);
emit Approval(owner, address(0), _tokenId);
}

tokenOwner[_tokenId] = _to;
ownedTokensCount[_from] = ownedTokensCount[_from].sub(1);
ownedTokensCount[_to] = ownedTokensCount[_to].add(1);

emit Transfer(_from, _to, _tokenId);
}
Expand Down
35 changes: 35 additions & 0 deletions contracts/token/ERC721/ERC721Token.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,41 @@ contract ERC721Token is SupportsInterfaceWithLookup, ERC721BasicToken, ERC721 {
return ownedTokens[_owner][_index];
}

/**
* @dev Transfers the ownership of a given token ID to another address
* Usage of this method is discouraged, use `safeTransferFrom` whenever possible
* Requires the msg sender to be the owner, approved, or operator
* @param _from current owner of the token
* @param _to address to receive the ownership of the given token ID
* @param _tokenId uint256 ID of the token to be transferred
*/
function transferFrom(
address _from,
address _to,
uint256 _tokenId
)
public
{
super.transferFrom(_from, _to, _tokenId);

uint256 tokenIndex = ownedTokensIndex[_tokenId];
uint256 lastTokenIndex = ownedTokens[_from].length.sub(1);
uint256 lastToken = ownedTokens[_from][lastTokenIndex];

ownedTokens[_from][tokenIndex] = lastToken;
ownedTokens[_from][lastTokenIndex] = 0;
// Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to
// be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping
// the lastToken to the first position, and then dropping the element placed in the last position of the list

ownedTokens[_from].length--;
ownedTokensIndex[_tokenId] = 0;
ownedTokensIndex[lastToken] = tokenIndex;

uint256 length = ownedTokens[_to].length;
ownedTokens[_to].push(_tokenId);
ownedTokensIndex[_tokenId] = length;
}
/**
* @dev Gets the total amount of tokens stored by the contract
* @return uint256 representing the total amount of tokens
Expand Down

0 comments on commit 59603a7

Please sign in to comment.