Skip to content

Commit

Permalink
Update to ERC721 final spec and Solidity 0.4.24
Browse files Browse the repository at this point in the history
  • Loading branch information
fulldecent committed Jul 3, 2018
1 parent 90daf64 commit d844941
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 43 deletions.
6 changes: 3 additions & 3 deletions contracts/AccessControl.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pragma solidity ^0.4.21;
pragma solidity ^0.4.24;

/// @title Reusable three-role access control inspired by CryptoKitties
/// @author William Entriken (https://phor.net)
/// @dev Keep the CEO wallet stored offline, I warned you
/// @dev Keep the CEO wallet stored offline, I warned you.
contract AccessControl {
/// @notice The account that can only reassign executive accounts
address public executiveOfficerAddress;
Expand All @@ -13,7 +13,7 @@ contract AccessControl {
/// @notice The account with administrative control of this contract
address public operatingOfficerAddress;

function AccessControl() internal {
constructor() internal {
executiveOfficerAddress = msg.sender;
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/ERC165.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity ^0.4.21;
pragma solidity ^0.4.24;

/// @title ERC-165 Standard Interface Detection
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
Expand Down
12 changes: 6 additions & 6 deletions contracts/ERC721.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
pragma solidity ^0.4.21;
pragma solidity ^0.4.24;

import "./ERC165.sol";

/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
contract ERC721 is ERC165 {
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
/// @dev Reference https://eips.ethereum.org/EIPS/eip-721
interface ERC721 /* is ERC165 */ {
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
Expand All @@ -21,7 +21,7 @@ contract ERC721 is ERC165 {

/// @title ERC-721 Non-Fungible Token Standard
interface ERC721TokenReceiver {
function onERC721Received(address _from, uint256 _tokenId, bytes data) external returns(bytes4);
function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4);
}

/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
Expand Down
5 changes: 2 additions & 3 deletions contracts/SuMain.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity ^0.4.21;
pragma solidity ^0.4.24;

import "./AccessControl.sol";
import "./SuNFT.sol";
Expand All @@ -10,7 +10,6 @@ import "./SuVending.sol";
/// @author William Entriken (https://phor.net)
/// @dev See SuMain contract documentation for detail on how contracts interact.
contract SuMain is AccessControl, SuNFT, SuOperation, SuVending, SuPromo {
function SuMain() public {
constructor() public {
}
}

44 changes: 23 additions & 21 deletions contracts/SuNFT.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pragma solidity ^0.4.21;
pragma solidity ^0.4.24;

import "./ERC721.sol";
import "./PublishInterfaces.sol";
import "./SupportsInterface.sol";

/// @title Compliance with ERC-721 for Su Squares
/// @dev This implementation assumes:
Expand All @@ -10,7 +10,7 @@ import "./PublishInterfaces.sol";
/// - NFTs are initially assigned to this contract
/// - This contract does not externally call its own functions
/// @author William Entriken (https://phor.net)
contract SuNFT is ERC165, ERC721, ERC721Metadata, ERC721Enumerable, PublishInterfaces {
contract SuNFT is ERC165, ERC721, ERC721Metadata, ERC721Enumerable, SupportsInterface {
/// @dev The authorized address for each NFT
mapping (uint256 => address) internal tokenApprovals;

Expand Down Expand Up @@ -59,13 +59,13 @@ contract SuNFT is ERC165, ERC721, ERC721Metadata, ERC721Enumerable, PublishInter
/// (`to` == 0). Exception: during contract creation, any number of NFTs
/// may be created and assigned without emitting Transfer. At the time of
/// any transfer, the approved address for that NFT (if any) is reset to none.
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);

/// @dev This emits when the approved address for an NFT is changed or
/// reaffirmed. The zero address indicates there is no approved address.
/// When a Transfer event emits, this also indicates that the approved
/// address for that NFT (if any) is reset to none.
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);

/// @dev This emits when an operator is enabled or disabled for an owner.
/// The operator can manage all NFTs of the owner.
Expand Down Expand Up @@ -106,7 +106,7 @@ contract SuNFT is ERC165, ERC721, ERC721Metadata, ERC721Enumerable, PublishInter
/// `_tokenId` is not a valid NFT. When transfer is complete, this function
/// checks if `_to` is a smart contract (code size > 0). If so, it calls
/// `onERC721Received` on `_to` and throws if the return value is not
/// `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`.
/// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
Expand All @@ -118,7 +118,7 @@ contract SuNFT is ERC165, ERC721, ERC721Metadata, ERC721Enumerable, PublishInter

/// @notice Transfers the ownership of an NFT from one address to another address
/// @dev This works identically to the other function with an extra data parameter,
/// except this function just sets data to ""
/// except this function just sets data to "".
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
Expand Down Expand Up @@ -153,9 +153,9 @@ contract SuNFT is ERC165, ERC721, ERC721Metadata, ERC721Enumerable, PublishInter
_transfer(_tokenId, _to);
}

/// @notice Set or reaffirm the approved address for an NFT
/// @notice Change or reaffirm the approved address for an NFT
/// @dev The zero address indicates there is no approved address.
/// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
/// Throws unless `msg.sender` is the current NFT owner, or an authorized
/// operator of the current owner.
/// @param _approved The new approved NFT controller
/// @param _tokenId The NFT to approve
Expand All @@ -174,18 +174,19 @@ contract SuNFT is ERC165, ERC721, ERC721Metadata, ERC721Enumerable, PublishInter
emit Approval(_owner, _approved, _tokenId);
}

/// @notice Enable or disable approval for a third party ("operator") to manage
/// all your asset.
/// @dev Emits the ApprovalForAll event
/// @param _operator Address to add to the set of authorized operators.
/// @param _approved True if the operators is approved, false to revoke approval
/// @notice Enable or disable approval for a third party ("operator") to
/// manage all of `msg.sender`'s assets
/// @dev Emits the ApprovalForAll event. The contract MUST allow
/// multiple operators per owner.
/// @param _operator Address to add to the set of authorized operators
/// @param _approved True if operator is approved, false to revoke approval
function setApprovalForAll(address _operator, bool _approved) external {
operatorApprovals[msg.sender][_operator] = _approved;
emit ApprovalForAll(msg.sender, _operator, _approved);
}

/// @notice Get the approved address for a single NFT
/// @dev Throws if `_tokenId` is not a valid NFT
/// @dev Throws if `_tokenId` is not a valid NFT.
/// @param _tokenId The NFT to find the approved address for
/// @return The approved address for this NFT, or the zero address if there is none
function getApproved(uint256 _tokenId)
Expand Down Expand Up @@ -240,8 +241,8 @@ contract SuNFT is ERC165, ERC721, ERC721Metadata, ERC721Enumerable, PublishInter
// COMPLIANCE WITH ERC721Enumerable ////////////////////////////////////////

/// @notice Count NFTs tracked by this contract
/// @return A count of valid NFTs tracked by this contract, where each one of
/// them has an assigned and queryable owner not equal to the zero address
/// @return A count of valid NFTs tracked by this contract, where each one
/// has an assigned and queryable owner not equal to the zero address
function totalSupply() external view returns (uint256) {
return TOTAL_SUPPLY;
}
Expand Down Expand Up @@ -326,9 +327,10 @@ contract SuNFT is ERC165, ERC721, ERC721Metadata, ERC721Enumerable, PublishInter

// PRIVATE STORAGE AND FUNCTIONS ///////////////////////////////////////////

uint256 private constant TOTAL_SUPPLY = 10000; // SOLIDITY ISSUE #3356 make this immutable
// See Solidity issue #3356, it would be clearer to initialize in SuMain
uint256 private constant TOTAL_SUPPLY = 10000;

bytes4 private constant ERC721_RECEIVED = bytes4(keccak256("onERC721Received(address,uint256,bytes)"));
bytes4 private constant ERC721_RECEIVED = bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));

/// @dev The owner of each NFT
/// If value == address(0), NFT is owned by address(this)
Expand Down Expand Up @@ -359,7 +361,7 @@ contract SuNFT is ERC165, ERC721, ERC721Metadata, ERC721Enumerable, PublishInter
// address[] private nftIds;
// mapping (uint256 => uint256) private nftIndexOfId;

function SuNFT() internal {
constructor() internal {
// Publish interfaces with ERC-165
supportedInterfaces[0x80ac58cd] = true; // ERC721
supportedInterfaces[0x5b5e139f] = true; // ERC721Metadata
Expand Down Expand Up @@ -405,7 +407,7 @@ contract SuNFT is ERC165, ERC721, ERC721Metadata, ERC721Enumerable, PublishInter
if (codeSize == 0) {
return;
}
bytes4 retval = ERC721TokenReceiver(_to).onERC721Received(_from, _tokenId, data);
bytes4 retval = ERC721TokenReceiver(_to).onERC721Received(msg.sender, _from, _tokenId, data);
require(retval == ERC721_RECEIVED);
}
}
4 changes: 2 additions & 2 deletions contracts/SuOperation.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity ^0.4.21;
pragma solidity ^0.4.24;

import "./SuNFT.sol";

Expand All @@ -9,7 +9,7 @@ contract SuOperation is SuNFT {
/// @dev The personalization of a square has changed
event Personalized(uint256 _nftId);

/// @dev The main SuSquare struct. The owner may set these properties, subject
/// @dev The main SuSquare struct. The owner may set these properties,
/// subject to certain rules. The actual 10x10 image is rendered on our
/// website using this data.
struct SuSquare {
Expand Down
4 changes: 2 additions & 2 deletions contracts/SuPromo.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
pragma solidity ^0.4.21;
pragma solidity ^0.4.24;

import "./SuNFT.sol";
import "./AccessControl.sol";

/// @title A limited pre-sale and promotional giveaway.
/// @title A limited pre-sale and promotional giveaway
/// @author William Entriken (https://phor.net)
/// @dev See SuMain contract documentation for detail on how contracts interact.
contract SuPromo is AccessControl, SuNFT {
Expand Down
2 changes: 1 addition & 1 deletion contracts/SuVending.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity ^0.4.21;
pragma solidity ^0.4.24;

import "./AccessControl.sol";
import "./SuNFT.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
pragma solidity ^0.4.21;
pragma solidity ^0.4.24;

import "./ERC165.sol";

/// @title A reusable contract to comply with ERC-165
/// @author William Entriken (https://phor.net)
contract PublishInterfaces is ERC165 {
/// @dev Every interface that we support
contract SupportsInterface is ERC165 {
/// @dev Every interface that we support, do not set 0xffffffff to true
mapping(bytes4 => bool) internal supportedInterfaces;

function PublishInterfaces() internal {
constructor() internal {
supportedInterfaces[0x01ffc9a7] = true; // ERC165
}

Expand Down

0 comments on commit d844941

Please sign in to comment.