浏览代码

Rename ERC interfaces to I prefix (#1252)

* rename ERC20 to IERC20

* move ERC20.sol to IERC20.sol

* rename StandardToken to ERC20

* rename StandardTokenMock to ERC20Mock

* move StandardToken.sol to ERC20.sol, likewise test and mock files

* rename MintableToken to ERC20Mintable

* move MintableToken.sol to ERC20Mintable.sol, likewise test and mock files

* rename BurnableToken to ERC20Burnable

* move BurnableToken.sol to ERC20Burnable.sol, likewise for related files

* rename CappedToken to ERC20Capped

* move CappedToken.sol to ERC20Capped.sol, likewise for related files

* rename PausableToken to ERC20Pausable

* move PausableToken.sol to ERC20Pausable.sol, likewise for related files

* rename DetailedERC20 to ERC20Detailed

* move DetailedERC20.sol to ERC20Detailed.sol, likewise for related files

* rename ERC721 to IERC721, and likewise for other related interfaces

* move ERC721.sol to IERC721.sol, likewise for other 721 interfaces

* rename ERC721Token to ERC721

* move ERC721Token.sol to ERC721.sol, likewise for related files

* rename ERC721BasicToken to ERC721Basic

* move ERC721BasicToken.sol to ERC721Basic.sol, likewise for related files

* rename ERC721PausableToken to ERC721Pausable

* move ERC721PausableToken.sol to ERC721Pausable.sol

* rename ERC165 to IERC165

* move ERC165.sol to IERC165.sol

* amend comment that ERC20 is based on FirstBlood

* fix comments mentioning IERC721Receiver
Francisco Giordano 7 年之前
父节点
当前提交
2e0713becb
共有 84 个文件被更改,包括 1059 次插入1059 次删除
  1. 1 1
      contracts/AutoIncrementing.sol
  2. 5 5
      contracts/crowdsale/Crowdsale.sol
  3. 1 1
      contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol
  4. 2 2
      contracts/crowdsale/emission/AllowanceCrowdsale.sol
  5. 2 2
      contracts/crowdsale/emission/MintedCrowdsale.sol
  6. 3 3
      contracts/examples/SampleCrowdsale.sol
  7. 3 3
      contracts/examples/SimpleToken.sol
  8. 2 2
      contracts/introspection/IERC165.sol
  9. 2 2
      contracts/introspection/SupportsInterfaceWithLookup.sol
  10. 2 2
      contracts/lifecycle/TokenDestructible.sol
  11. 2 2
      contracts/mocks/AllowanceCrowdsaleImpl.sol
  12. 2 2
      contracts/mocks/CappedCrowdsaleImpl.sol
  13. 4 4
      contracts/mocks/DetailedERC20Mock.sol
  14. 2 2
      contracts/mocks/ERC165/ERC165InterfacesSupported.sol
  15. 2 2
      contracts/mocks/ERC20BurnableMock.sol
  16. 3 3
      contracts/mocks/ERC20Mock.sol
  17. 3 3
      contracts/mocks/ERC20PausableMock.sol
  18. 2 2
      contracts/mocks/ERC20WithMetadataMock.sol
  19. 2 2
      contracts/mocks/ERC223TokenMock.sol
  20. 3 3
      contracts/mocks/ERC721BasicMock.sol
  21. 4 4
      contracts/mocks/ERC721Mock.sol
  22. 3 3
      contracts/mocks/ERC721PausableMock.sol
  23. 2 2
      contracts/mocks/ERC721ReceiverMock.sol
  24. 2 2
      contracts/mocks/FinalizableCrowdsaleImpl.sol
  25. 1 1
      contracts/mocks/IncreasingPriceCrowdsaleImpl.sol
  26. 2 2
      contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol
  27. 2 2
      contracts/mocks/MintedCrowdsaleImpl.sol
  28. 2 2
      contracts/mocks/PostDeliveryCrowdsaleImpl.sol
  29. 3 3
      contracts/mocks/RBACCappedTokenMock.sol
  30. 2 2
      contracts/mocks/RefundableCrowdsaleImpl.sol
  31. 6 6
      contracts/mocks/SafeERC20Helper.sol
  32. 2 2
      contracts/mocks/TimedCrowdsaleImpl.sol
  33. 2 2
      contracts/mocks/WhitelistedCrowdsaleImpl.sol
  34. 3 3
      contracts/ownership/CanReclaimToken.sol
  35. 3 3
      contracts/proposals/ERC1046/TokenMetadata.sol
  36. 191 22
      contracts/token/ERC20/ERC20.sol
  37. 3 3
      contracts/token/ERC20/ERC20Burnable.sol
  38. 2 2
      contracts/token/ERC20/ERC20Capped.sol
  39. 3 3
      contracts/token/ERC20/ERC20Detailed.sol
  40. 2 2
      contracts/token/ERC20/ERC20Mintable.sol
  41. 3 3
      contracts/token/ERC20/ERC20Pausable.sol
  42. 35 0
      contracts/token/ERC20/IERC20.sol
  43. 2 2
      contracts/token/ERC20/RBACMintableToken.sol
  44. 4 4
      contracts/token/ERC20/SafeERC20.sol
  45. 0 204
      contracts/token/ERC20/StandardToken.sol
  46. 3 3
      contracts/token/ERC20/TokenTimelock.sol
  47. 5 5
      contracts/token/ERC20/TokenVesting.sol
  48. 182 21
      contracts/token/ERC721/ERC721.sol
  49. 287 57
      contracts/token/ERC721/ERC721Basic.sol
  50. 0 310
      contracts/token/ERC721/ERC721BasicToken.sol
  51. 2 2
      contracts/token/ERC721/ERC721Holder.sol
  52. 3 3
      contracts/token/ERC721/ERC721Pausable.sol
  53. 0 201
      contracts/token/ERC721/ERC721Token.sol
  54. 2 2
      contracts/token/ERC721/IDeprecatedERC721.sol
  55. 40 0
      contracts/token/ERC721/IERC721.sol
  56. 80 0
      contracts/token/ERC721/IERC721Basic.sol
  57. 2 2
      contracts/token/ERC721/IERC721Receiver.sol
  58. 2 2
      test/crowdsale/FinalizableCrowdsale.test.js
  59. 5 5
      test/crowdsale/MintedCrowdsale.test.js
  60. 2 2
      test/lifecycle/TokenDestructible.test.js
  61. 2 2
      test/ownership/CanReclaimToken.test.js
  62. 0 12
      test/token/ERC20/BurnableToken.test.js
  63. 0 25
      test/token/ERC20/CappedToken.test.js
  64. 3 3
      test/token/ERC20/DetailedERC20.test.js
  65. 3 3
      test/token/ERC20/ERC20.test.js
  66. 2 2
      test/token/ERC20/ERC20Burnable.behavior.js
  67. 12 0
      test/token/ERC20/ERC20Burnable.test.js
  68. 2 2
      test/token/ERC20/ERC20Capped.behavior.js
  69. 25 0
      test/token/ERC20/ERC20Capped.test.js
  70. 2 2
      test/token/ERC20/ERC20Mintable.behavior.js
  71. 10 0
      test/token/ERC20/ERC20Mintable.test.js
  72. 3 3
      test/token/ERC20/ERC20Pausable.test.js
  73. 0 10
      test/token/ERC20/MintableToken.test.js
  74. 4 4
      test/token/ERC20/RBACCappedToken.test.js
  75. 2 2
      test/token/ERC20/RBACMintableToken.test.js
  76. 2 2
      test/token/ERC20/TokenTimelock.test.js
  77. 2 2
      test/token/ERC20/TokenVesting.test.js
  78. 7 7
      test/token/ERC721/ERC721.test.js
  79. 3 3
      test/token/ERC721/ERC721Basic.behavior.js
  80. 18 0
      test/token/ERC721/ERC721Basic.test.js
  81. 0 18
      test/token/ERC721/ERC721BasicToken.test.js
  82. 3 3
      test/token/ERC721/ERC721MintBurn.behavior.js
  83. 6 6
      test/token/ERC721/ERC721Pausable.test.js
  84. 1 1
      test/token/ERC721/ERC721PausedToken.behavior.js

+ 1 - 1
contracts/AutoIncrementing.sol

@@ -5,7 +5,7 @@ pragma solidity ^0.4.24;
  * @title AutoIncrementing
  * @author Matt Condon (@shrugs)
  * @dev Provides an auto-incrementing uint256 id acquired by the `Counter#nextId` getter.
- * Use this for issuing ERC721Token ids or keeping track of request ids, anything you want, really.
+ * Use this for issuing ERC721 ids or keeping track of request ids, anything you want, really.
  *
  * Include with `using AutoIncrementing for AutoIncrementing.Counter;`
  * @notice Does not allow an Id of 0, which is popularly used to signify a null state in solidity.

+ 5 - 5
contracts/crowdsale/Crowdsale.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/ERC20.sol";
+import "../token/ERC20/IERC20.sol";
 import "../math/SafeMath.sol";
 import "../token/ERC20/SafeERC20.sol";
 
@@ -19,17 +19,17 @@ import "../token/ERC20/SafeERC20.sol";
  */
 contract Crowdsale {
   using SafeMath for uint256;
-  using SafeERC20 for ERC20;
+  using SafeERC20 for IERC20;
 
   // The token being sold
-  ERC20 public token;
+  IERC20 public token;
 
   // Address where funds are collected
   address public wallet;
 
   // How many token units a buyer gets per wei.
   // The rate is the conversion between wei and the smallest and indivisible token unit.
-  // So, if you are using a rate of 1 with a DetailedERC20 token with 3 decimals called TOK
+  // So, if you are using a rate of 1 with a ERC20Detailed token with 3 decimals called TOK
   // 1 wei will give you 1 unit, or 0.001 TOK.
   uint256 public rate;
 
@@ -55,7 +55,7 @@ contract Crowdsale {
    * @param _wallet Address where collected funds will be forwarded to
    * @param _token Address of the token being sold
    */
-  constructor(uint256 _rate, address _wallet, ERC20 _token) public {
+  constructor(uint256 _rate, address _wallet, IERC20 _token) public {
     require(_rate > 0);
     require(_wallet != address(0));
     require(_token != address(0));

+ 1 - 1
contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.24;
 
 import "../validation/TimedCrowdsale.sol";
-import "../../token/ERC20/ERC20.sol";
+import "../../token/ERC20/IERC20.sol";
 import "../../math/SafeMath.sol";
 
 

+ 2 - 2
contracts/crowdsale/emission/AllowanceCrowdsale.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.24;
 
 import "../Crowdsale.sol";
-import "../../token/ERC20/ERC20.sol";
+import "../../token/ERC20/IERC20.sol";
 import "../../token/ERC20/SafeERC20.sol";
 import "../../math/SafeMath.sol";
 
@@ -12,7 +12,7 @@ import "../../math/SafeMath.sol";
  */
 contract AllowanceCrowdsale is Crowdsale {
   using SafeMath for uint256;
-  using SafeERC20 for ERC20;
+  using SafeERC20 for IERC20;
 
   address public tokenWallet;
 

+ 2 - 2
contracts/crowdsale/emission/MintedCrowdsale.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.24;
 
 import "../Crowdsale.sol";
-import "../../token/ERC20/MintableToken.sol";
+import "../../token/ERC20/ERC20Mintable.sol";
 
 
 /**
@@ -23,6 +23,6 @@ contract MintedCrowdsale is Crowdsale {
     internal
   {
     // Potentially dangerous assumption about the type of the token.
-    require(MintableToken(address(token)).mint(_beneficiary, _tokenAmount));
+    require(ERC20Mintable(address(token)).mint(_beneficiary, _tokenAmount));
   }
 }

+ 3 - 3
contracts/examples/SampleCrowdsale.sol

@@ -3,7 +3,7 @@ pragma solidity ^0.4.24;
 import "../crowdsale/validation/CappedCrowdsale.sol";
 import "../crowdsale/distribution/RefundableCrowdsale.sol";
 import "../crowdsale/emission/MintedCrowdsale.sol";
-import "../token/ERC20/MintableToken.sol";
+import "../token/ERC20/ERC20Mintable.sol";
 
 
 /**
@@ -11,7 +11,7 @@ import "../token/ERC20/MintableToken.sol";
  * @dev Very simple ERC20 Token that can be minted.
  * It is meant to be used in a crowdsale contract.
  */
-contract SampleCrowdsaleToken is MintableToken {
+contract SampleCrowdsaleToken is ERC20Mintable {
 
   string public constant name = "Sample Crowdsale Token";
   string public constant symbol = "SCT";
@@ -44,7 +44,7 @@ contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale, MintedCrowdsal
     uint256 _rate,
     address _wallet,
     uint256 _cap,
-    MintableToken _token,
+    ERC20Mintable _token,
     uint256 _goal
   )
     public

+ 3 - 3
contracts/examples/SimpleToken.sol

@@ -1,16 +1,16 @@
 pragma solidity ^0.4.24;
 
 
-import "../token/ERC20/StandardToken.sol";
+import "../token/ERC20/ERC20.sol";
 
 
 /**
  * @title SimpleToken
  * @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator.
  * Note they can later distribute these tokens as they wish using `transfer` and other
- * `StandardToken` functions.
+ * `ERC20` functions.
  */
-contract SimpleToken is StandardToken {
+contract SimpleToken is ERC20 {
 
   string public constant name = "SimpleToken";
   string public constant symbol = "SIM";

+ 2 - 2
contracts/introspection/ERC165.sol → contracts/introspection/IERC165.sol

@@ -2,10 +2,10 @@ pragma solidity ^0.4.24;
 
 
 /**
- * @title ERC165
+ * @title IERC165
  * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
  */
-interface ERC165 {
+interface IERC165 {
 
   /**
    * @notice Query if a contract implements an interface

+ 2 - 2
contracts/introspection/SupportsInterfaceWithLookup.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "./ERC165.sol";
+import "./IERC165.sol";
 
 
 /**
@@ -8,7 +8,7 @@ import "./ERC165.sol";
  * @author Matt Condon (@shrugs)
  * @dev Implements ERC165 using a lookup table.
  */
-contract SupportsInterfaceWithLookup is ERC165 {
+contract SupportsInterfaceWithLookup is IERC165 {
 
   bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7;
   /**

+ 2 - 2
contracts/lifecycle/TokenDestructible.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.24;
 
 import "../ownership/Ownable.sol";
-import "../token/ERC20/ERC20.sol";
+import "../token/ERC20/IERC20.sol";
 
 
 /**
@@ -25,7 +25,7 @@ contract TokenDestructible is Ownable {
 
     // Transfer tokens to owner
     for (uint256 i = 0; i < _tokens.length; i++) {
-      ERC20 token = ERC20(_tokens[i]);
+      IERC20 token = IERC20(_tokens[i]);
       uint256 balance = token.balanceOf(this);
       token.transfer(owner, balance);
     }

+ 2 - 2
contracts/mocks/AllowanceCrowdsaleImpl.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/ERC20.sol";
+import "../token/ERC20/IERC20.sol";
 import "../crowdsale/emission/AllowanceCrowdsale.sol";
 
 
@@ -9,7 +9,7 @@ contract AllowanceCrowdsaleImpl is AllowanceCrowdsale {
   constructor (
     uint256 _rate,
     address _wallet,
-    ERC20 _token,
+    IERC20 _token,
     address _tokenWallet
   )
     public

+ 2 - 2
contracts/mocks/CappedCrowdsaleImpl.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/ERC20.sol";
+import "../token/ERC20/IERC20.sol";
 import "../crowdsale/validation/CappedCrowdsale.sol";
 
 
@@ -9,7 +9,7 @@ contract CappedCrowdsaleImpl is CappedCrowdsale {
   constructor (
     uint256 _rate,
     address _wallet,
-    ERC20 _token,
+    IERC20 _token,
     uint256 _cap
   )
     public

+ 4 - 4
contracts/mocks/DetailedERC20Mock.sol

@@ -1,16 +1,16 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/StandardToken.sol";
-import "../token/ERC20/DetailedERC20.sol";
+import "../token/ERC20/ERC20.sol";
+import "../token/ERC20/ERC20Detailed.sol";
 
 
-contract DetailedERC20Mock is StandardToken, DetailedERC20 {
+contract ERC20DetailedMock is ERC20, ERC20Detailed {
   constructor(
     string _name,
     string _symbol,
     uint8 _decimals
   )
-    DetailedERC20(_name, _symbol, _decimals)
+    ERC20Detailed(_name, _symbol, _decimals)
     public
   {}
 }

+ 2 - 2
contracts/mocks/ERC165/ERC165InterfacesSupported.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "../../introspection/ERC165.sol";
+import "../../introspection/IERC165.sol";
 
 
 /**
@@ -11,7 +11,7 @@ import "../../introspection/ERC165.sol";
  * therefore, because this contract is staticcall'd we need to not emit events (which is how solidity-coverage works)
  * solidity-coverage ignores the /mocks folder, so we duplicate its implementation here to avoid instrumenting it
  */
-contract SupportsInterfaceWithLookupMock is ERC165 {
+contract SupportsInterfaceWithLookupMock is IERC165 {
 
   bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7;
   /**

+ 2 - 2
contracts/mocks/BurnableTokenMock.sol → contracts/mocks/ERC20BurnableMock.sol

@@ -1,9 +1,9 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/BurnableToken.sol";
+import "../token/ERC20/ERC20Burnable.sol";
 
 
-contract BurnableTokenMock is BurnableToken {
+contract ERC20BurnableMock is ERC20Burnable {
 
   constructor(address _initialAccount, uint256 _initialBalance) public {
     _mint(_initialAccount, _initialBalance);

+ 3 - 3
contracts/mocks/StandardTokenMock.sol → contracts/mocks/ERC20Mock.sol

@@ -1,10 +1,10 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/StandardToken.sol";
+import "../token/ERC20/ERC20.sol";
 
 
-// mock class using StandardToken
-contract StandardTokenMock is StandardToken {
+// mock class using ERC20
+contract ERC20Mock is ERC20 {
 
   constructor(address _initialAccount, uint256 _initialBalance) public {
     _mint(_initialAccount, _initialBalance);

+ 3 - 3
contracts/mocks/PausableTokenMock.sol → contracts/mocks/ERC20PausableMock.sol

@@ -1,10 +1,10 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/PausableToken.sol";
+import "../token/ERC20/ERC20Pausable.sol";
 
 
-// mock class using PausableToken
-contract PausableTokenMock is PausableToken {
+// mock class using ERC20Pausable
+contract ERC20PausableMock is ERC20Pausable {
 
   constructor(address _initialAccount, uint _initialBalance) public {
     _mint(_initialAccount, _initialBalance);

+ 2 - 2
contracts/mocks/ERC20WithMetadataMock.sol

@@ -1,10 +1,10 @@
 pragma solidity ^0.4.21;
 
-import "../token/ERC20/StandardToken.sol";
+import "../token/ERC20/ERC20.sol";
 import "../proposals/ERC1046/TokenMetadata.sol";
 
 
-contract ERC20WithMetadataMock is StandardToken, ERC20WithMetadata {
+contract ERC20WithMetadataMock is ERC20, ERC20WithMetadata {
   constructor(string _tokenURI) public
     ERC20WithMetadata(_tokenURI)
   {

+ 2 - 2
contracts/mocks/ERC223TokenMock.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/StandardToken.sol";
+import "../token/ERC20/ERC20.sol";
 
 
 contract ERC223ContractInterface {
@@ -8,7 +8,7 @@ contract ERC223ContractInterface {
 }
 
 
-contract ERC223TokenMock is StandardToken {
+contract ERC223TokenMock is ERC20 {
 
   constructor(address _initialAccount, uint256 _initialBalance) public {
     _mint(_initialAccount, _initialBalance);

+ 3 - 3
contracts/mocks/ERC721BasicTokenMock.sol → contracts/mocks/ERC721BasicMock.sol

@@ -1,13 +1,13 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC721/ERC721BasicToken.sol";
+import "../token/ERC721/ERC721Basic.sol";
 
 
 /**
- * @title ERC721BasicTokenMock
+ * @title ERC721BasicMock
  * This mock just provides a public mint and burn functions for testing purposes
  */
-contract ERC721BasicTokenMock is ERC721BasicToken {
+contract ERC721BasicMock is ERC721Basic {
   function mint(address _to, uint256 _tokenId) public {
     super._mint(_to, _tokenId);
   }

+ 4 - 4
contracts/mocks/ERC721TokenMock.sol → contracts/mocks/ERC721Mock.sol

@@ -1,16 +1,16 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC721/ERC721Token.sol";
+import "../token/ERC721/ERC721.sol";
 
 
 /**
- * @title ERC721TokenMock
+ * @title ERC721Mock
  * This mock just provides a public mint and burn functions for testing purposes,
  * and a public setter for metadata URI
  */
-contract ERC721TokenMock is ERC721Token {
+contract ERC721Mock is ERC721 {
   constructor(string name, string symbol) public
-    ERC721Token(name, symbol)
+    ERC721(name, symbol)
   { }
 
   function mint(address _to, uint256 _tokenId) public {

+ 3 - 3
contracts/mocks/ERC721PausableTokenMock.sol → contracts/mocks/ERC721PausableMock.sol

@@ -1,13 +1,13 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC721/ERC721PausableToken.sol";
+import "../token/ERC721/ERC721Pausable.sol";
 
 
 /**
- * @title ERC721PausableTokenMock
+ * @title ERC721PausableMock
  * This mock just provides a public mint, burn and exists functions for testing purposes
  */
-contract ERC721PausableTokenMock is ERC721PausableToken {
+contract ERC721PausableMock is ERC721Pausable {
   function mint(address _to, uint256 _tokenId) public {
     super._mint(_to, _tokenId);
   }

+ 2 - 2
contracts/mocks/ERC721ReceiverMock.sol

@@ -1,9 +1,9 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC721/ERC721Receiver.sol";
+import "../token/ERC721/IERC721Receiver.sol";
 
 
-contract ERC721ReceiverMock is ERC721Receiver {
+contract ERC721ReceiverMock is IERC721Receiver {
   bytes4 retval_;
   bool reverts_;
 

+ 2 - 2
contracts/mocks/FinalizableCrowdsaleImpl.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/MintableToken.sol";
+import "../token/ERC20/ERC20Mintable.sol";
 import "../crowdsale/distribution/FinalizableCrowdsale.sol";
 
 
@@ -11,7 +11,7 @@ contract FinalizableCrowdsaleImpl is FinalizableCrowdsale {
     uint256 _closingTime,
     uint256 _rate,
     address _wallet,
-    MintableToken _token
+    ERC20Mintable _token
   )
     public
     Crowdsale(_rate, _wallet, _token)

+ 1 - 1
contracts/mocks/IncreasingPriceCrowdsaleImpl.sol

@@ -10,7 +10,7 @@ contract IncreasingPriceCrowdsaleImpl is IncreasingPriceCrowdsale {
     uint256 _openingTime,
     uint256 _closingTime,
     address _wallet,
-    ERC20 _token,
+    IERC20 _token,
     uint256 _initialRate,
     uint256 _finalRate
   )

+ 2 - 2
contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/ERC20.sol";
+import "../token/ERC20/IERC20.sol";
 import "../crowdsale/validation/IndividuallyCappedCrowdsale.sol";
 
 
@@ -9,7 +9,7 @@ contract IndividuallyCappedCrowdsaleImpl is IndividuallyCappedCrowdsale {
   constructor (
     uint256 _rate,
     address _wallet,
-    ERC20 _token
+    IERC20 _token
   )
     public
     Crowdsale(_rate, _wallet, _token)

+ 2 - 2
contracts/mocks/MintedCrowdsaleImpl.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/MintableToken.sol";
+import "../token/ERC20/ERC20Mintable.sol";
 import "../crowdsale/emission/MintedCrowdsale.sol";
 
 
@@ -9,7 +9,7 @@ contract MintedCrowdsaleImpl is MintedCrowdsale {
   constructor (
     uint256 _rate,
     address _wallet,
-    MintableToken _token
+    ERC20Mintable _token
   )
     public
     Crowdsale(_rate, _wallet, _token)

+ 2 - 2
contracts/mocks/PostDeliveryCrowdsaleImpl.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/ERC20.sol";
+import "../token/ERC20/IERC20.sol";
 import "../crowdsale/distribution/PostDeliveryCrowdsale.sol";
 
 
@@ -11,7 +11,7 @@ contract PostDeliveryCrowdsaleImpl is PostDeliveryCrowdsale {
     uint256 _closingTime,
     uint256 _rate,
     address _wallet,
-    ERC20 _token
+    IERC20 _token
   )
     public
     TimedCrowdsale(_openingTime, _closingTime)

+ 3 - 3
contracts/mocks/RBACCappedTokenMock.sol

@@ -1,12 +1,12 @@
 pragma solidity ^0.4.24;
 
 import "../token/ERC20/RBACMintableToken.sol";
-import "../token/ERC20/CappedToken.sol";
+import "../token/ERC20/ERC20Capped.sol";
 
 
-contract RBACCappedTokenMock is CappedToken, RBACMintableToken {
+contract RBACCappedTokenMock is ERC20Capped, RBACMintableToken {
   constructor(uint256 _cap)
-    CappedToken(_cap)
+    ERC20Capped(_cap)
     public
   {}
 }

+ 2 - 2
contracts/mocks/RefundableCrowdsaleImpl.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/MintableToken.sol";
+import "../token/ERC20/ERC20Mintable.sol";
 import "../crowdsale/distribution/RefundableCrowdsale.sol";
 
 
@@ -11,7 +11,7 @@ contract RefundableCrowdsaleImpl is RefundableCrowdsale {
     uint256 _closingTime,
     uint256 _rate,
     address _wallet,
-    MintableToken _token,
+    ERC20Mintable _token,
     uint256 _goal
   )
     public

+ 6 - 6
contracts/mocks/SafeERC20Helper.sol

@@ -1,10 +1,10 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/ERC20.sol";
+import "../token/ERC20/IERC20.sol";
 import "../token/ERC20/SafeERC20.sol";
 
 
-contract ERC20FailingMock is ERC20 {
+contract ERC20FailingMock is IERC20 {
   function totalSupply() public view returns (uint256) {
     return 0;
   }
@@ -31,7 +31,7 @@ contract ERC20FailingMock is ERC20 {
 }
 
 
-contract ERC20SucceedingMock is ERC20 {
+contract ERC20SucceedingMock is IERC20 {
   function totalSupply() public view returns (uint256) {
     return 0;
   }
@@ -59,10 +59,10 @@ contract ERC20SucceedingMock is ERC20 {
 
 
 contract SafeERC20Helper {
-  using SafeERC20 for ERC20;
+  using SafeERC20 for IERC20;
 
-  ERC20 failing;
-  ERC20 succeeding;
+  IERC20 failing;
+  IERC20 succeeding;
 
   constructor() public {
     failing = new ERC20FailingMock();

+ 2 - 2
contracts/mocks/TimedCrowdsaleImpl.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/ERC20.sol";
+import "../token/ERC20/IERC20.sol";
 import "../crowdsale/validation/TimedCrowdsale.sol";
 
 
@@ -11,7 +11,7 @@ contract TimedCrowdsaleImpl is TimedCrowdsale {
     uint256 _closingTime,
     uint256 _rate,
     address _wallet,
-    ERC20 _token
+    IERC20 _token
   )
     public
     Crowdsale(_rate, _wallet, _token)

+ 2 - 2
contracts/mocks/WhitelistedCrowdsaleImpl.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "../token/ERC20/ERC20.sol";
+import "../token/ERC20/IERC20.sol";
 import "../crowdsale/validation/WhitelistedCrowdsale.sol";
 import "../crowdsale/Crowdsale.sol";
 
@@ -10,7 +10,7 @@ contract WhitelistedCrowdsaleImpl is Crowdsale, WhitelistedCrowdsale {
   constructor (
     uint256 _rate,
     address _wallet,
-    ERC20 _token
+    IERC20 _token
   )
     Crowdsale(_rate, _wallet, _token)
     public

+ 3 - 3
contracts/ownership/CanReclaimToken.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.24;
 
 import "./Ownable.sol";
-import "../token/ERC20/ERC20.sol";
+import "../token/ERC20/IERC20.sol";
 import "../token/ERC20/SafeERC20.sol";
 
 
@@ -12,13 +12,13 @@ import "../token/ERC20/SafeERC20.sol";
  * This will prevent any accidental loss of tokens.
  */
 contract CanReclaimToken is Ownable {
-  using SafeERC20 for ERC20;
+  using SafeERC20 for IERC20;
 
   /**
    * @dev Reclaim all ERC20 compatible tokens
    * @param _token ERC20 The address of the token contract
    */
-  function reclaimToken(ERC20 _token) external onlyOwner {
+  function reclaimToken(IERC20 _token) external onlyOwner {
     uint256 balance = _token.balanceOf(this);
     _token.safeTransfer(owner, balance);
   }

+ 3 - 3
contracts/proposals/ERC1046/TokenMetadata.sol

@@ -1,15 +1,15 @@
 pragma solidity ^0.4.21;
 
-import "../../token/ERC20/ERC20.sol";
+import "../../token/ERC20/IERC20.sol";
 
 
 /**
  * @title ERC-1047 Token Metadata
  * @dev See https://eips.ethereum.org/EIPS/eip-1046
  * @dev tokenURI must respond with a URI that implements https://eips.ethereum.org/EIPS/eip-1047
- * @dev TODO - update https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC721/ERC721.sol#L17 when 1046 is finalized
+ * @dev TODO - update https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC721/IERC721.sol#L17 when 1046 is finalized
  */
-contract ERC20TokenMetadata is ERC20 {
+contract ERC20TokenMetadata is IERC20 {
   function tokenURI() external view returns (string);
 }
 

+ 191 - 22
contracts/token/ERC20/ERC20.sol

@@ -1,35 +1,204 @@
 pragma solidity ^0.4.24;
 
+import "./IERC20.sol";
+import "../../math/SafeMath.sol";
+
 
 /**
- * @title ERC20 interface
- * @dev see https://github.com/ethereum/EIPs/issues/20
+ * @title Standard ERC20 token
+ *
+ * @dev Implementation of the basic standard token.
+ * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
+ * Originally based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
  */
-contract ERC20 {
-  function totalSupply() public view returns (uint256);
+contract ERC20 is IERC20 {
+  using SafeMath for uint256;
+
+  mapping (address => uint256) private balances_;
+
+  mapping (address => mapping (address => uint256)) private allowed_;
+
+  uint256 private totalSupply_;
+
+  /**
+  * @dev Total number of tokens in existence
+  */
+  function totalSupply() public view returns (uint256) {
+    return totalSupply_;
+  }
+
+  /**
+  * @dev Gets the balance of the specified address.
+  * @param _owner The address to query the the balance of.
+  * @return An uint256 representing the amount owned by the passed address.
+  */
+  function balanceOf(address _owner) public view returns (uint256) {
+    return balances_[_owner];
+  }
+
+  /**
+   * @dev Function to check the amount of tokens that an owner allowed to a spender.
+   * @param _owner address The address which owns the funds.
+   * @param _spender address The address which will spend the funds.
+   * @return A uint256 specifying the amount of tokens still available for the spender.
+   */
+  function allowance(
+    address _owner,
+    address _spender
+   )
+    public
+    view
+    returns (uint256)
+  {
+    return allowed_[_owner][_spender];
+  }
+
+  /**
+  * @dev Transfer token for a specified address
+  * @param _to The address to transfer to.
+  * @param _value The amount to be transferred.
+  */
+  function transfer(address _to, uint256 _value) public returns (bool) {
+    require(_value <= balances_[msg.sender]);
+    require(_to != address(0));
+
+    balances_[msg.sender] = balances_[msg.sender].sub(_value);
+    balances_[_to] = balances_[_to].add(_value);
+    emit Transfer(msg.sender, _to, _value);
+    return true;
+  }
+
+  /**
+   * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
+   * Beware that changing an allowance with this method brings the risk that someone may use both the old
+   * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
+   * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
+   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
+   * @param _spender The address which will spend the funds.
+   * @param _value The amount of tokens to be spent.
+   */
+  function approve(address _spender, uint256 _value) public returns (bool) {
+    allowed_[msg.sender][_spender] = _value;
+    emit Approval(msg.sender, _spender, _value);
+    return true;
+  }
+
+  /**
+   * @dev Transfer tokens from one address to another
+   * @param _from address The address which you want to send tokens from
+   * @param _to address The address which you want to transfer to
+   * @param _value uint256 the amount of tokens to be transferred
+   */
+  function transferFrom(
+    address _from,
+    address _to,
+    uint256 _value
+  )
+    public
+    returns (bool)
+  {
+    require(_value <= balances_[_from]);
+    require(_value <= allowed_[_from][msg.sender]);
+    require(_to != address(0));
+
+    balances_[_from] = balances_[_from].sub(_value);
+    balances_[_to] = balances_[_to].add(_value);
+    allowed_[_from][msg.sender] = allowed_[_from][msg.sender].sub(_value);
+    emit Transfer(_from, _to, _value);
+    return true;
+  }
 
-  function balanceOf(address _who) public view returns (uint256);
+  /**
+   * @dev Increase the amount of tokens that an owner allowed to a spender.
+   * approve should be called when allowed_[_spender] == 0. To increment
+   * allowed value is better to use this function to avoid 2 calls (and wait until
+   * the first transaction is mined)
+   * From MonolithDAO Token.sol
+   * @param _spender The address which will spend the funds.
+   * @param _addedValue The amount of tokens to increase the allowance by.
+   */
+  function increaseApproval(
+    address _spender,
+    uint256 _addedValue
+  )
+    public
+    returns (bool)
+  {
+    allowed_[msg.sender][_spender] = (
+      allowed_[msg.sender][_spender].add(_addedValue));
+    emit Approval(msg.sender, _spender, allowed_[msg.sender][_spender]);
+    return true;
+  }
 
-  function allowance(address _owner, address _spender)
-    public view returns (uint256);
+  /**
+   * @dev Decrease the amount of tokens that an owner allowed to a spender.
+   * approve should be called when allowed_[_spender] == 0. To decrement
+   * allowed value is better to use this function to avoid 2 calls (and wait until
+   * the first transaction is mined)
+   * From MonolithDAO Token.sol
+   * @param _spender The address which will spend the funds.
+   * @param _subtractedValue The amount of tokens to decrease the allowance by.
+   */
+  function decreaseApproval(
+    address _spender,
+    uint256 _subtractedValue
+  )
+    public
+    returns (bool)
+  {
+    uint256 oldValue = allowed_[msg.sender][_spender];
+    if (_subtractedValue >= oldValue) {
+      allowed_[msg.sender][_spender] = 0;
+    } else {
+      allowed_[msg.sender][_spender] = oldValue.sub(_subtractedValue);
+    }
+    emit Approval(msg.sender, _spender, allowed_[msg.sender][_spender]);
+    return true;
+  }
 
-  function transfer(address _to, uint256 _value) public returns (bool);
+  /**
+   * @dev Internal function that mints an amount of the token and assigns it to
+   * an account. This encapsulates the modification of balances such that the
+   * proper events are emitted.
+   * @param _account The account that will receive the created tokens.
+   * @param _amount The amount that will be created.
+   */
+  function _mint(address _account, uint256 _amount) internal {
+    require(_account != 0);
+    totalSupply_ = totalSupply_.add(_amount);
+    balances_[_account] = balances_[_account].add(_amount);
+    emit Transfer(address(0), _account, _amount);
+  }
 
-  function approve(address _spender, uint256 _value)
-    public returns (bool);
+  /**
+   * @dev Internal function that burns an amount of the token of a given
+   * account.
+   * @param _account The account whose tokens will be burnt.
+   * @param _amount The amount that will be burnt.
+   */
+  function _burn(address _account, uint256 _amount) internal {
+    require(_account != 0);
+    require(_amount <= balances_[_account]);
 
-  function transferFrom(address _from, address _to, uint256 _value)
-    public returns (bool);
+    totalSupply_ = totalSupply_.sub(_amount);
+    balances_[_account] = balances_[_account].sub(_amount);
+    emit Transfer(_account, address(0), _amount);
+  }
 
-  event Transfer(
-    address indexed from,
-    address indexed to,
-    uint256 value
-  );
+  /**
+   * @dev Internal function that burns an amount of the token of a given
+   * account, deducting from the sender's allowance for said account. Uses the
+   * internal _burn function.
+   * @param _account The account whose tokens will be burnt.
+   * @param _amount The amount that will be burnt.
+   */
+  function _burnFrom(address _account, uint256 _amount) internal {
+    require(_amount <= allowed_[_account][msg.sender]);
 
-  event Approval(
-    address indexed owner,
-    address indexed spender,
-    uint256 value
-  );
+    // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted,
+    // this function needs to emit an event with the updated approval.
+    allowed_[_account][msg.sender] = allowed_[_account][msg.sender].sub(
+      _amount);
+    _burn(_account, _amount);
+  }
 }

+ 3 - 3
contracts/token/ERC20/BurnableToken.sol → contracts/token/ERC20/ERC20Burnable.sol

@@ -1,13 +1,13 @@
 pragma solidity ^0.4.24;
 
-import "./StandardToken.sol";
+import "./ERC20.sol";
 
 
 /**
  * @title Burnable Token
  * @dev Token that can be irreversibly burned (destroyed).
  */
-contract BurnableToken is StandardToken {
+contract ERC20Burnable is ERC20 {
 
   event TokensBurned(address indexed burner, uint256 value);
 
@@ -29,7 +29,7 @@ contract BurnableToken is StandardToken {
   }
 
   /**
-   * @dev Overrides StandardToken._burn in order for burn and burnFrom to emit
+   * @dev Overrides ERC20._burn in order for burn and burnFrom to emit
    * an additional Burn event.
    */
   function _burn(address _who, uint256 _value) internal {

+ 2 - 2
contracts/token/ERC20/CappedToken.sol → contracts/token/ERC20/ERC20Capped.sol

@@ -1,13 +1,13 @@
 pragma solidity ^0.4.24;
 
-import "./MintableToken.sol";
+import "./ERC20Mintable.sol";
 
 
 /**
  * @title Capped token
  * @dev Mintable token with a token cap.
  */
-contract CappedToken is MintableToken {
+contract ERC20Capped is ERC20Mintable {
 
   uint256 public cap;
 

+ 3 - 3
contracts/token/ERC20/DetailedERC20.sol → contracts/token/ERC20/ERC20Detailed.sol

@@ -1,15 +1,15 @@
 pragma solidity ^0.4.24;
 
-import "./ERC20.sol";
+import "./IERC20.sol";
 
 
 /**
- * @title DetailedERC20 token
+ * @title ERC20Detailed token
  * @dev The decimals are only for visualization purposes.
  * All the operations are done using the smallest and indivisible token unit,
  * just as on Ethereum all the operations are done in wei.
  */
-contract DetailedERC20 is ERC20 {
+contract ERC20Detailed is IERC20 {
   string public name;
   string public symbol;
   uint8 public decimals;

+ 2 - 2
contracts/token/ERC20/MintableToken.sol → contracts/token/ERC20/ERC20Mintable.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "./StandardToken.sol";
+import "./ERC20.sol";
 import "../../ownership/Ownable.sol";
 
 
@@ -9,7 +9,7 @@ import "../../ownership/Ownable.sol";
  * @dev Simple ERC20 Token example, with mintable token creation
  * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
  */
-contract MintableToken is StandardToken, Ownable {
+contract ERC20Mintable is ERC20, Ownable {
   event Mint(address indexed to, uint256 amount);
   event MintFinished();
 

+ 3 - 3
contracts/token/ERC20/PausableToken.sol → contracts/token/ERC20/ERC20Pausable.sol

@@ -1,14 +1,14 @@
 pragma solidity ^0.4.24;
 
-import "./StandardToken.sol";
+import "./ERC20.sol";
 import "../../lifecycle/Pausable.sol";
 
 
 /**
  * @title Pausable token
- * @dev StandardToken modified with pausable transfers.
+ * @dev ERC20 modified with pausable transfers.
  **/
-contract PausableToken is StandardToken, Pausable {
+contract ERC20Pausable is ERC20, Pausable {
 
   function transfer(
     address _to,

+ 35 - 0
contracts/token/ERC20/IERC20.sol

@@ -0,0 +1,35 @@
+pragma solidity ^0.4.24;
+
+
+/**
+ * @title ERC20 interface
+ * @dev see https://github.com/ethereum/EIPs/issues/20
+ */
+interface IERC20 {
+  function totalSupply() public view returns (uint256);
+
+  function balanceOf(address _who) public view returns (uint256);
+
+  function allowance(address _owner, address _spender)
+    public view returns (uint256);
+
+  function transfer(address _to, uint256 _value) public returns (bool);
+
+  function approve(address _spender, uint256 _value)
+    public returns (bool);
+
+  function transferFrom(address _from, address _to, uint256 _value)
+    public returns (bool);
+
+  event Transfer(
+    address indexed from,
+    address indexed to,
+    uint256 value
+  );
+
+  event Approval(
+    address indexed owner,
+    address indexed spender,
+    uint256 value
+  );
+}

+ 2 - 2
contracts/token/ERC20/RBACMintableToken.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "./MintableToken.sol";
+import "./ERC20Mintable.sol";
 import "../../access/rbac/RBAC.sol";
 
 
@@ -9,7 +9,7 @@ import "../../access/rbac/RBAC.sol";
  * @author Vittorio Minacori (@vittominacori)
  * @dev Mintable Token, with RBAC minter permissions
  */
-contract RBACMintableToken is MintableToken, RBAC {
+contract RBACMintableToken is ERC20Mintable, RBAC {
   /**
    * A constant role name for indicating minters.
    */

+ 4 - 4
contracts/token/ERC20/SafeERC20.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.24;
 
-import "./StandardToken.sol";
 import "./ERC20.sol";
+import "./IERC20.sol";
 
 
 /**
@@ -12,7 +12,7 @@ import "./ERC20.sol";
  */
 library SafeERC20 {
   function safeTransfer(
-    ERC20 _token,
+    IERC20 _token,
     address _to,
     uint256 _value
   )
@@ -22,7 +22,7 @@ library SafeERC20 {
   }
 
   function safeTransferFrom(
-    ERC20 _token,
+    IERC20 _token,
     address _from,
     address _to,
     uint256 _value
@@ -33,7 +33,7 @@ library SafeERC20 {
   }
 
   function safeApprove(
-    ERC20 _token,
+    IERC20 _token,
     address _spender,
     uint256 _value
   )

+ 0 - 204
contracts/token/ERC20/StandardToken.sol

@@ -1,204 +0,0 @@
-pragma solidity ^0.4.24;
-
-import "./ERC20.sol";
-import "../../math/SafeMath.sol";
-
-
-/**
- * @title Standard ERC20 token
- *
- * @dev Implementation of the basic standard token.
- * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
- * Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
- */
-contract StandardToken is ERC20 {
-  using SafeMath for uint256;
-
-  mapping (address => uint256) private balances_;
-
-  mapping (address => mapping (address => uint256)) private allowed_;
-
-  uint256 private totalSupply_;
-
-  /**
-  * @dev Total number of tokens in existence
-  */
-  function totalSupply() public view returns (uint256) {
-    return totalSupply_;
-  }
-
-  /**
-  * @dev Gets the balance of the specified address.
-  * @param _owner The address to query the the balance of.
-  * @return An uint256 representing the amount owned by the passed address.
-  */
-  function balanceOf(address _owner) public view returns (uint256) {
-    return balances_[_owner];
-  }
-
-  /**
-   * @dev Function to check the amount of tokens that an owner allowed to a spender.
-   * @param _owner address The address which owns the funds.
-   * @param _spender address The address which will spend the funds.
-   * @return A uint256 specifying the amount of tokens still available for the spender.
-   */
-  function allowance(
-    address _owner,
-    address _spender
-   )
-    public
-    view
-    returns (uint256)
-  {
-    return allowed_[_owner][_spender];
-  }
-
-  /**
-  * @dev Transfer token for a specified address
-  * @param _to The address to transfer to.
-  * @param _value The amount to be transferred.
-  */
-  function transfer(address _to, uint256 _value) public returns (bool) {
-    require(_value <= balances_[msg.sender]);
-    require(_to != address(0));
-
-    balances_[msg.sender] = balances_[msg.sender].sub(_value);
-    balances_[_to] = balances_[_to].add(_value);
-    emit Transfer(msg.sender, _to, _value);
-    return true;
-  }
-
-  /**
-   * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
-   * Beware that changing an allowance with this method brings the risk that someone may use both the old
-   * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
-   * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
-   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
-   * @param _spender The address which will spend the funds.
-   * @param _value The amount of tokens to be spent.
-   */
-  function approve(address _spender, uint256 _value) public returns (bool) {
-    allowed_[msg.sender][_spender] = _value;
-    emit Approval(msg.sender, _spender, _value);
-    return true;
-  }
-
-  /**
-   * @dev Transfer tokens from one address to another
-   * @param _from address The address which you want to send tokens from
-   * @param _to address The address which you want to transfer to
-   * @param _value uint256 the amount of tokens to be transferred
-   */
-  function transferFrom(
-    address _from,
-    address _to,
-    uint256 _value
-  )
-    public
-    returns (bool)
-  {
-    require(_value <= balances_[_from]);
-    require(_value <= allowed_[_from][msg.sender]);
-    require(_to != address(0));
-
-    balances_[_from] = balances_[_from].sub(_value);
-    balances_[_to] = balances_[_to].add(_value);
-    allowed_[_from][msg.sender] = allowed_[_from][msg.sender].sub(_value);
-    emit Transfer(_from, _to, _value);
-    return true;
-  }
-
-  /**
-   * @dev Increase the amount of tokens that an owner allowed to a spender.
-   * approve should be called when allowed_[_spender] == 0. To increment
-   * allowed value is better to use this function to avoid 2 calls (and wait until
-   * the first transaction is mined)
-   * From MonolithDAO Token.sol
-   * @param _spender The address which will spend the funds.
-   * @param _addedValue The amount of tokens to increase the allowance by.
-   */
-  function increaseApproval(
-    address _spender,
-    uint256 _addedValue
-  )
-    public
-    returns (bool)
-  {
-    allowed_[msg.sender][_spender] = (
-      allowed_[msg.sender][_spender].add(_addedValue));
-    emit Approval(msg.sender, _spender, allowed_[msg.sender][_spender]);
-    return true;
-  }
-
-  /**
-   * @dev Decrease the amount of tokens that an owner allowed to a spender.
-   * approve should be called when allowed_[_spender] == 0. To decrement
-   * allowed value is better to use this function to avoid 2 calls (and wait until
-   * the first transaction is mined)
-   * From MonolithDAO Token.sol
-   * @param _spender The address which will spend the funds.
-   * @param _subtractedValue The amount of tokens to decrease the allowance by.
-   */
-  function decreaseApproval(
-    address _spender,
-    uint256 _subtractedValue
-  )
-    public
-    returns (bool)
-  {
-    uint256 oldValue = allowed_[msg.sender][_spender];
-    if (_subtractedValue >= oldValue) {
-      allowed_[msg.sender][_spender] = 0;
-    } else {
-      allowed_[msg.sender][_spender] = oldValue.sub(_subtractedValue);
-    }
-    emit Approval(msg.sender, _spender, allowed_[msg.sender][_spender]);
-    return true;
-  }
-
-  /**
-   * @dev Internal function that mints an amount of the token and assigns it to
-   * an account. This encapsulates the modification of balances such that the
-   * proper events are emitted.
-   * @param _account The account that will receive the created tokens.
-   * @param _amount The amount that will be created.
-   */
-  function _mint(address _account, uint256 _amount) internal {
-    require(_account != 0);
-    totalSupply_ = totalSupply_.add(_amount);
-    balances_[_account] = balances_[_account].add(_amount);
-    emit Transfer(address(0), _account, _amount);
-  }
-
-  /**
-   * @dev Internal function that burns an amount of the token of a given
-   * account.
-   * @param _account The account whose tokens will be burnt.
-   * @param _amount The amount that will be burnt.
-   */
-  function _burn(address _account, uint256 _amount) internal {
-    require(_account != 0);
-    require(_amount <= balances_[_account]);
-
-    totalSupply_ = totalSupply_.sub(_amount);
-    balances_[_account] = balances_[_account].sub(_amount);
-    emit Transfer(_account, address(0), _amount);
-  }
-
-  /**
-   * @dev Internal function that burns an amount of the token of a given
-   * account, deducting from the sender's allowance for said account. Uses the
-   * internal _burn function.
-   * @param _account The account whose tokens will be burnt.
-   * @param _amount The amount that will be burnt.
-   */
-  function _burnFrom(address _account, uint256 _amount) internal {
-    require(_amount <= allowed_[_account][msg.sender]);
-
-    // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted,
-    // this function needs to emit an event with the updated approval.
-    allowed_[_account][msg.sender] = allowed_[_account][msg.sender].sub(
-      _amount);
-    _burn(_account, _amount);
-  }
-}

+ 3 - 3
contracts/token/ERC20/TokenTimelock.sol

@@ -9,10 +9,10 @@ import "./SafeERC20.sol";
  * beneficiary to extract the tokens after a given release time
  */
 contract TokenTimelock {
-  using SafeERC20 for ERC20;
+  using SafeERC20 for IERC20;
 
   // ERC20 basic token contract being held
-  ERC20 public token;
+  IERC20 public token;
 
   // beneficiary of tokens after they are released
   address public beneficiary;
@@ -21,7 +21,7 @@ contract TokenTimelock {
   uint256 public releaseTime;
 
   constructor(
-    ERC20 _token,
+    IERC20 _token,
     address _beneficiary,
     uint256 _releaseTime
   )

+ 5 - 5
contracts/token/ERC20/TokenVesting.sol

@@ -15,7 +15,7 @@ import "../../math/SafeMath.sol";
  */
 contract TokenVesting is Ownable {
   using SafeMath for uint256;
-  using SafeERC20 for ERC20;
+  using SafeERC20 for IERC20;
 
   event Released(uint256 amount);
   event Revoked();
@@ -65,7 +65,7 @@ contract TokenVesting is Ownable {
    * @notice Transfers vested tokens to beneficiary.
    * @param _token ERC20 token which is being vested
    */
-  function release(ERC20 _token) public {
+  function release(IERC20 _token) public {
     uint256 unreleased = releasableAmount(_token);
 
     require(unreleased > 0);
@@ -82,7 +82,7 @@ contract TokenVesting is Ownable {
    * remain in the contract, the rest are returned to the owner.
    * @param _token ERC20 token which is being vested
    */
-  function revoke(ERC20 _token) public onlyOwner {
+  function revoke(IERC20 _token) public onlyOwner {
     require(revocable);
     require(!revoked[_token]);
 
@@ -102,7 +102,7 @@ contract TokenVesting is Ownable {
    * @dev Calculates the amount that has already vested but hasn't been released yet.
    * @param _token ERC20 token which is being vested
    */
-  function releasableAmount(ERC20 _token) public view returns (uint256) {
+  function releasableAmount(IERC20 _token) public view returns (uint256) {
     return vestedAmount(_token).sub(released[_token]);
   }
 
@@ -110,7 +110,7 @@ contract TokenVesting is Ownable {
    * @dev Calculates the amount that has already vested.
    * @param _token ERC20 token which is being vested
    */
-  function vestedAmount(ERC20 _token) public view returns (uint256) {
+  function vestedAmount(IERC20 _token) public view returns (uint256) {
     uint256 currentBalance = _token.balanceOf(this);
     uint256 totalBalance = currentBalance.add(released[_token]);
 

+ 182 - 21
contracts/token/ERC721/ERC721.sol

@@ -1,40 +1,201 @@
 pragma solidity ^0.4.24;
 
+import "./IERC721.sol";
 import "./ERC721Basic.sol";
+import "../../introspection/SupportsInterfaceWithLookup.sol";
 
 
 /**
- * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
- * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
+ * @title Full ERC721 Token
+ * This implementation includes all the required and some optional functionality of the ERC721 standard
+ * Moreover, it includes approve all functionality using operator terminology
+ * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
  */
-contract ERC721Enumerable is ERC721Basic {
-  function totalSupply() public view returns (uint256);
+contract ERC721 is SupportsInterfaceWithLookup, ERC721Basic, IERC721 {
+
+  // Token name
+  string internal name_;
+
+  // Token symbol
+  string internal symbol_;
+
+  // Mapping from owner to list of owned token IDs
+  mapping(address => uint256[]) internal ownedTokens;
+
+  // Mapping from token ID to index of the owner tokens list
+  mapping(uint256 => uint256) internal ownedTokensIndex;
+
+  // Array with all token ids, used for enumeration
+  uint256[] internal allTokens;
+
+  // Mapping from token id to position in the allTokens array
+  mapping(uint256 => uint256) internal allTokensIndex;
+
+  // Optional mapping for token URIs
+  mapping(uint256 => string) internal tokenURIs;
+
+  /**
+   * @dev Constructor function
+   */
+  constructor(string _name, string _symbol) public {
+    name_ = _name;
+    symbol_ = _symbol;
+
+    // register the supported interfaces to conform to ERC721 via ERC165
+    _registerInterface(InterfaceId_ERC721Enumerable);
+    _registerInterface(InterfaceId_ERC721Metadata);
+  }
+
+  /**
+   * @dev Gets the token name
+   * @return string representing the token name
+   */
+  function name() external view returns (string) {
+    return name_;
+  }
+
+  /**
+   * @dev Gets the token symbol
+   * @return string representing the token symbol
+   */
+  function symbol() external view returns (string) {
+    return symbol_;
+  }
+
+  /**
+   * @dev Returns an URI for a given token ID
+   * Throws if the token ID does not exist. May return an empty string.
+   * @param _tokenId uint256 ID of the token to query
+   */
+  function tokenURI(uint256 _tokenId) public view returns (string) {
+    require(_exists(_tokenId));
+    return tokenURIs[_tokenId];
+  }
+
+  /**
+   * @dev Gets the token ID at a given index of the tokens list of the requested owner
+   * @param _owner address owning the tokens list to be accessed
+   * @param _index uint256 representing the index to be accessed of the requested tokens list
+   * @return uint256 token ID at the given index of the tokens list owned by the requested address
+   */
   function tokenOfOwnerByIndex(
     address _owner,
     uint256 _index
   )
     public
     view
-    returns (uint256 _tokenId);
+    returns (uint256)
+  {
+    require(_index < balanceOf(_owner));
+    return ownedTokens[_owner][_index];
+  }
 
-  function tokenByIndex(uint256 _index) public view returns (uint256);
-}
+  /**
+   * @dev Gets the total amount of tokens stored by the contract
+   * @return uint256 representing the total amount of tokens
+   */
+  function totalSupply() public view returns (uint256) {
+    return allTokens.length;
+  }
 
+  /**
+   * @dev Gets the token ID at a given index of all the tokens in this contract
+   * Reverts if the index is greater or equal to the total number of tokens
+   * @param _index uint256 representing the index to be accessed of the tokens list
+   * @return uint256 token ID at the given index of the tokens list
+   */
+  function tokenByIndex(uint256 _index) public view returns (uint256) {
+    require(_index < totalSupply());
+    return allTokens[_index];
+  }
 
-/**
- * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
- * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
- */
-contract ERC721Metadata is ERC721Basic {
-  function name() external view returns (string _name);
-  function symbol() external view returns (string _symbol);
-  function tokenURI(uint256 _tokenId) public view returns (string);
-}
+  /**
+   * @dev Internal function to set the token URI for a given token
+   * Reverts if the token ID does not exist
+   * @param _tokenId uint256 ID of the token to set its URI
+   * @param _uri string URI to assign
+   */
+  function _setTokenURI(uint256 _tokenId, string _uri) internal {
+    require(_exists(_tokenId));
+    tokenURIs[_tokenId] = _uri;
+  }
 
+  /**
+   * @dev Internal function to add a token ID to the list of a given address
+   * @param _to address representing the new owner of the given token ID
+   * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
+   */
+  function addTokenTo(address _to, uint256 _tokenId) internal {
+    super.addTokenTo(_to, _tokenId);
+    uint256 length = ownedTokens[_to].length;
+    ownedTokens[_to].push(_tokenId);
+    ownedTokensIndex[_tokenId] = length;
+  }
+
+  /**
+   * @dev Internal function to remove a token ID from the list of a given address
+   * @param _from address representing the previous owner of the given token ID
+   * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
+   */
+  function removeTokenFrom(address _from, uint256 _tokenId) internal {
+    super.removeTokenFrom(_from, _tokenId);
+
+    // To prevent a gap in the array, we store the last token in the index of the token to delete, and
+    // then delete the last slot.
+    uint256 tokenIndex = ownedTokensIndex[_tokenId];
+    uint256 lastTokenIndex = ownedTokens[_from].length.sub(1);
+    uint256 lastToken = ownedTokens[_from][lastTokenIndex];
+
+    ownedTokens[_from][tokenIndex] = lastToken;
+    // This also deletes the contents at the last position of the array
+    ownedTokens[_from].length--;
+
+    // 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
+
+    ownedTokensIndex[_tokenId] = 0;
+    ownedTokensIndex[lastToken] = tokenIndex;
+  }
+
+  /**
+   * @dev Internal function to mint a new token
+   * Reverts if the given token ID already exists
+   * @param _to address the beneficiary that will own the minted token
+   * @param _tokenId uint256 ID of the token to be minted by the msg.sender
+   */
+  function _mint(address _to, uint256 _tokenId) internal {
+    super._mint(_to, _tokenId);
+
+    allTokensIndex[_tokenId] = allTokens.length;
+    allTokens.push(_tokenId);
+  }
+
+  /**
+   * @dev Internal function to burn a specific token
+   * Reverts if the token does not exist
+   * @param _owner owner of the token to burn
+   * @param _tokenId uint256 ID of the token being burned by the msg.sender
+   */
+  function _burn(address _owner, uint256 _tokenId) internal {
+    super._burn(_owner, _tokenId);
+
+    // Clear metadata (if any)
+    if (bytes(tokenURIs[_tokenId]).length != 0) {
+      delete tokenURIs[_tokenId];
+    }
+
+    // Reorg all tokens array
+    uint256 tokenIndex = allTokensIndex[_tokenId];
+    uint256 lastTokenIndex = allTokens.length.sub(1);
+    uint256 lastToken = allTokens[lastTokenIndex];
+
+    allTokens[tokenIndex] = lastToken;
+    allTokens[lastTokenIndex] = 0;
+
+    allTokens.length--;
+    allTokensIndex[_tokenId] = 0;
+    allTokensIndex[lastToken] = tokenIndex;
+  }
 
-/**
- * @title ERC-721 Non-Fungible Token Standard, full implementation interface
- * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
- */
-contract ERC721 is ERC721Basic, ERC721Enumerable, ERC721Metadata {
 }

+ 287 - 57
contracts/token/ERC721/ERC721Basic.sol

@@ -1,80 +1,310 @@
 pragma solidity ^0.4.24;
 
-import "../../introspection/ERC165.sol";
+import "./IERC721Basic.sol";
+import "./IERC721Receiver.sol";
+import "../../math/SafeMath.sol";
+import "../../AddressUtils.sol";
+import "../../introspection/SupportsInterfaceWithLookup.sol";
 
 
 /**
- * @title ERC721 Non-Fungible Token Standard basic interface
+ * @title ERC721 Non-Fungible Token Standard basic implementation
  * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
  */
-contract ERC721Basic is ERC165 {
-
-  bytes4 internal constant InterfaceId_ERC721 = 0x80ac58cd;
-  /*
-   * 0x80ac58cd ===
-   *   bytes4(keccak256('balanceOf(address)')) ^
-   *   bytes4(keccak256('ownerOf(uint256)')) ^
-   *   bytes4(keccak256('approve(address,uint256)')) ^
-   *   bytes4(keccak256('getApproved(uint256)')) ^
-   *   bytes4(keccak256('setApprovalForAll(address,bool)')) ^
-   *   bytes4(keccak256('isApprovedForAll(address,address)')) ^
-   *   bytes4(keccak256('transferFrom(address,address,uint256)')) ^
-   *   bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
-   *   bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
+contract ERC721Basic is SupportsInterfaceWithLookup, IERC721Basic {
+
+  using SafeMath for uint256;
+  using AddressUtils for address;
+
+  // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
+  // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
+  bytes4 private constant ERC721_RECEIVED = 0x150b7a02;
+
+  // Mapping from token ID to owner
+  mapping (uint256 => address) internal tokenOwner;
+
+  // Mapping from token ID to approved address
+  mapping (uint256 => address) internal tokenApprovals;
+
+  // Mapping from owner to number of owned token
+  mapping (address => uint256) internal ownedTokensCount;
+
+  // Mapping from owner to operator approvals
+  mapping (address => mapping (address => bool)) internal operatorApprovals;
+
+  constructor()
+    public
+  {
+    // register the supported interfaces to conform to ERC721 via ERC165
+    _registerInterface(InterfaceId_ERC721);
+  }
+
+  /**
+   * @dev Gets the balance of the specified address
+   * @param _owner address to query the balance of
+   * @return uint256 representing the amount owned by the passed address
+   */
+  function balanceOf(address _owner) public view returns (uint256) {
+    require(_owner != address(0));
+    return ownedTokensCount[_owner];
+  }
+
+  /**
+   * @dev Gets the owner of the specified token ID
+   * @param _tokenId uint256 ID of the token to query the owner of
+   * @return owner address currently marked as the owner of the given token ID
+   */
+  function ownerOf(uint256 _tokenId) public view returns (address) {
+    address owner = tokenOwner[_tokenId];
+    require(owner != address(0));
+    return owner;
+  }
+
+  /**
+   * @dev Approves another address to transfer the given token ID
+   * The zero address indicates there is no approved address.
+   * There can only be one approved address per token at a given time.
+   * Can only be called by the token owner or an approved operator.
+   * @param _to address to be approved for the given token ID
+   * @param _tokenId uint256 ID of the token to be approved
+   */
+  function approve(address _to, uint256 _tokenId) public {
+    address owner = ownerOf(_tokenId);
+    require(_to != owner);
+    require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
+
+    tokenApprovals[_tokenId] = _to;
+    emit Approval(owner, _to, _tokenId);
+  }
+
+  /**
+   * @dev Gets the approved address for a token ID, or zero if no address set
+   * @param _tokenId uint256 ID of the token to query the approval of
+   * @return address currently approved for the given token ID
    */
+  function getApproved(uint256 _tokenId) public view returns (address) {
+    return tokenApprovals[_tokenId];
+  }
 
-  bytes4 internal constant InterfaceId_ERC721Enumerable = 0x780e9d63;
   /**
-   * 0x780e9d63 ===
-   *   bytes4(keccak256('totalSupply()')) ^
-   *   bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^
-   *   bytes4(keccak256('tokenByIndex(uint256)'))
+   * @dev Sets or unsets the approval of a given operator
+   * An operator is allowed to transfer all tokens of the sender on their behalf
+   * @param _to operator address to set the approval
+   * @param _approved representing the status of the approval to be set
    */
+  function setApprovalForAll(address _to, bool _approved) public {
+    require(_to != msg.sender);
+    operatorApprovals[msg.sender][_to] = _approved;
+    emit ApprovalForAll(msg.sender, _to, _approved);
+  }
 
-  bytes4 internal constant InterfaceId_ERC721Metadata = 0x5b5e139f;
   /**
-   * 0x5b5e139f ===
-   *   bytes4(keccak256('name()')) ^
-   *   bytes4(keccak256('symbol()')) ^
-   *   bytes4(keccak256('tokenURI(uint256)'))
+   * @dev Tells whether an operator is approved by a given owner
+   * @param _owner owner address which you want to query the approval of
+   * @param _operator operator address which you want to query the approval of
+   * @return bool whether the given operator is approved by the given owner
    */
+  function isApprovedForAll(
+    address _owner,
+    address _operator
+  )
+    public
+    view
+    returns (bool)
+  {
+    return operatorApprovals[_owner][_operator];
+  }
+
+  /**
+   * @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
+  {
+    require(isApprovedOrOwner(msg.sender, _tokenId));
+    require(_to != address(0));
+
+    clearApproval(_from, _tokenId);
+    removeTokenFrom(_from, _tokenId);
+    addTokenTo(_to, _tokenId);
 
-  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) public view returns (uint256 _balance);
-  function ownerOf(uint256 _tokenId) public view returns (address _owner);
-
-  function approve(address _to, uint256 _tokenId) public;
-  function getApproved(uint256 _tokenId)
-    public view returns (address _operator);
-
-  function setApprovalForAll(address _operator, bool _approved) public;
-  function isApprovedForAll(address _owner, address _operator)
-    public view returns (bool);
-
-  function transferFrom(address _from, address _to, uint256 _tokenId) public;
-  function safeTransferFrom(address _from, address _to, uint256 _tokenId)
-    public;
+    emit Transfer(_from, _to, _tokenId);
+  }
+
+  /**
+   * @dev Safely transfers the ownership of a given token ID to another address
+   * If the target address is a contract, it must implement `onERC721Received`,
+   * which is called upon a safe transfer, and return the magic value
+   * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
+   * the transfer is reverted.
+   *
+   * 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 safeTransferFrom(
+    address _from,
+    address _to,
+    uint256 _tokenId
+  )
+    public
+  {
+    // solium-disable-next-line arg-overflow
+    safeTransferFrom(_from, _to, _tokenId, "");
+  }
 
+  /**
+   * @dev Safely transfers the ownership of a given token ID to another address
+   * If the target address is a contract, it must implement `onERC721Received`,
+   * which is called upon a safe transfer, and return the magic value
+   * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
+   * the transfer is reverted.
+   * 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
+   * @param _data bytes data to send along with a safe transfer check
+   */
   function safeTransferFrom(
     address _from,
     address _to,
     uint256 _tokenId,
     bytes _data
   )
-    public;
+    public
+  {
+    transferFrom(_from, _to, _tokenId);
+    // solium-disable-next-line arg-overflow
+    require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data));
+  }
+
+  /**
+   * @dev Returns whether the specified token exists
+   * @param _tokenId uint256 ID of the token to query the existence of
+   * @return whether the token exists
+   */
+  function _exists(uint256 _tokenId) internal view returns (bool) {
+    address owner = tokenOwner[_tokenId];
+    return owner != address(0);
+  }
+
+  /**
+   * @dev Returns whether the given spender can transfer a given token ID
+   * @param _spender address of the spender to query
+   * @param _tokenId uint256 ID of the token to be transferred
+   * @return bool whether the msg.sender is approved for the given token ID,
+   *  is an operator of the owner, or is the owner of the token
+   */
+  function isApprovedOrOwner(
+    address _spender,
+    uint256 _tokenId
+  )
+    internal
+    view
+    returns (bool)
+  {
+    address owner = ownerOf(_tokenId);
+    // Disable solium check because of
+    // https://github.com/duaraghav8/Solium/issues/175
+    // solium-disable-next-line operator-whitespace
+    return (
+      _spender == owner ||
+      getApproved(_tokenId) == _spender ||
+      isApprovedForAll(owner, _spender)
+    );
+  }
+
+  /**
+   * @dev Internal function to mint a new token
+   * Reverts if the given token ID already exists
+   * @param _to The address that will own the minted token
+   * @param _tokenId uint256 ID of the token to be minted by the msg.sender
+   */
+  function _mint(address _to, uint256 _tokenId) internal {
+    require(_to != address(0));
+    addTokenTo(_to, _tokenId);
+    emit Transfer(address(0), _to, _tokenId);
+  }
+
+  /**
+   * @dev Internal function to burn a specific token
+   * Reverts if the token does not exist
+   * @param _tokenId uint256 ID of the token being burned by the msg.sender
+   */
+  function _burn(address _owner, uint256 _tokenId) internal {
+    clearApproval(_owner, _tokenId);
+    removeTokenFrom(_owner, _tokenId);
+    emit Transfer(_owner, address(0), _tokenId);
+  }
+
+  /**
+   * @dev Internal function to clear current approval of a given token ID
+   * Reverts if the given address is not indeed the owner of the token
+   * @param _owner owner of the token
+   * @param _tokenId uint256 ID of the token to be transferred
+   */
+  function clearApproval(address _owner, uint256 _tokenId) internal {
+    require(ownerOf(_tokenId) == _owner);
+    if (tokenApprovals[_tokenId] != address(0)) {
+      tokenApprovals[_tokenId] = address(0);
+    }
+  }
+
+  /**
+   * @dev Internal function to add a token ID to the list of a given address
+   * @param _to address representing the new owner of the given token ID
+   * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
+   */
+  function addTokenTo(address _to, uint256 _tokenId) internal {
+    require(tokenOwner[_tokenId] == address(0));
+    tokenOwner[_tokenId] = _to;
+    ownedTokensCount[_to] = ownedTokensCount[_to].add(1);
+  }
+
+  /**
+   * @dev Internal function to remove a token ID from the list of a given address
+   * @param _from address representing the previous owner of the given token ID
+   * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
+   */
+  function removeTokenFrom(address _from, uint256 _tokenId) internal {
+    require(ownerOf(_tokenId) == _from);
+    ownedTokensCount[_from] = ownedTokensCount[_from].sub(1);
+    tokenOwner[_tokenId] = address(0);
+  }
+
+  /**
+   * @dev Internal function to invoke `onERC721Received` on a target address
+   * The call is not executed if the target address is not a contract
+   * @param _from address representing the previous owner of the given token ID
+   * @param _to target address that will receive the tokens
+   * @param _tokenId uint256 ID of the token to be transferred
+   * @param _data bytes optional data to send along with the call
+   * @return whether the call correctly returned the expected magic value
+   */
+  function checkAndCallSafeTransfer(
+    address _from,
+    address _to,
+    uint256 _tokenId,
+    bytes _data
+  )
+    internal
+    returns (bool)
+  {
+    if (!_to.isContract()) {
+      return true;
+    }
+    bytes4 retval = IERC721Receiver(_to).onERC721Received(
+      msg.sender, _from, _tokenId, _data);
+    return (retval == ERC721_RECEIVED);
+  }
 }

+ 0 - 310
contracts/token/ERC721/ERC721BasicToken.sol

@@ -1,310 +0,0 @@
-pragma solidity ^0.4.24;
-
-import "./ERC721Basic.sol";
-import "./ERC721Receiver.sol";
-import "../../math/SafeMath.sol";
-import "../../AddressUtils.sol";
-import "../../introspection/SupportsInterfaceWithLookup.sol";
-
-
-/**
- * @title ERC721 Non-Fungible Token Standard basic implementation
- * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
- */
-contract ERC721BasicToken is SupportsInterfaceWithLookup, ERC721Basic {
-
-  using SafeMath for uint256;
-  using AddressUtils for address;
-
-  // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
-  // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
-  bytes4 private constant ERC721_RECEIVED = 0x150b7a02;
-
-  // Mapping from token ID to owner
-  mapping (uint256 => address) internal tokenOwner;
-
-  // Mapping from token ID to approved address
-  mapping (uint256 => address) internal tokenApprovals;
-
-  // Mapping from owner to number of owned token
-  mapping (address => uint256) internal ownedTokensCount;
-
-  // Mapping from owner to operator approvals
-  mapping (address => mapping (address => bool)) internal operatorApprovals;
-
-  constructor()
-    public
-  {
-    // register the supported interfaces to conform to ERC721 via ERC165
-    _registerInterface(InterfaceId_ERC721);
-  }
-
-  /**
-   * @dev Gets the balance of the specified address
-   * @param _owner address to query the balance of
-   * @return uint256 representing the amount owned by the passed address
-   */
-  function balanceOf(address _owner) public view returns (uint256) {
-    require(_owner != address(0));
-    return ownedTokensCount[_owner];
-  }
-
-  /**
-   * @dev Gets the owner of the specified token ID
-   * @param _tokenId uint256 ID of the token to query the owner of
-   * @return owner address currently marked as the owner of the given token ID
-   */
-  function ownerOf(uint256 _tokenId) public view returns (address) {
-    address owner = tokenOwner[_tokenId];
-    require(owner != address(0));
-    return owner;
-  }
-
-  /**
-   * @dev Approves another address to transfer the given token ID
-   * The zero address indicates there is no approved address.
-   * There can only be one approved address per token at a given time.
-   * Can only be called by the token owner or an approved operator.
-   * @param _to address to be approved for the given token ID
-   * @param _tokenId uint256 ID of the token to be approved
-   */
-  function approve(address _to, uint256 _tokenId) public {
-    address owner = ownerOf(_tokenId);
-    require(_to != owner);
-    require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
-
-    tokenApprovals[_tokenId] = _to;
-    emit Approval(owner, _to, _tokenId);
-  }
-
-  /**
-   * @dev Gets the approved address for a token ID, or zero if no address set
-   * @param _tokenId uint256 ID of the token to query the approval of
-   * @return address currently approved for the given token ID
-   */
-  function getApproved(uint256 _tokenId) public view returns (address) {
-    return tokenApprovals[_tokenId];
-  }
-
-  /**
-   * @dev Sets or unsets the approval of a given operator
-   * An operator is allowed to transfer all tokens of the sender on their behalf
-   * @param _to operator address to set the approval
-   * @param _approved representing the status of the approval to be set
-   */
-  function setApprovalForAll(address _to, bool _approved) public {
-    require(_to != msg.sender);
-    operatorApprovals[msg.sender][_to] = _approved;
-    emit ApprovalForAll(msg.sender, _to, _approved);
-  }
-
-  /**
-   * @dev Tells whether an operator is approved by a given owner
-   * @param _owner owner address which you want to query the approval of
-   * @param _operator operator address which you want to query the approval of
-   * @return bool whether the given operator is approved by the given owner
-   */
-  function isApprovedForAll(
-    address _owner,
-    address _operator
-  )
-    public
-    view
-    returns (bool)
-  {
-    return operatorApprovals[_owner][_operator];
-  }
-
-  /**
-   * @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
-  {
-    require(isApprovedOrOwner(msg.sender, _tokenId));
-    require(_to != address(0));
-
-    clearApproval(_from, _tokenId);
-    removeTokenFrom(_from, _tokenId);
-    addTokenTo(_to, _tokenId);
-
-    emit Transfer(_from, _to, _tokenId);
-  }
-
-  /**
-   * @dev Safely transfers the ownership of a given token ID to another address
-   * If the target address is a contract, it must implement `onERC721Received`,
-   * which is called upon a safe transfer, and return the magic value
-   * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
-   * the transfer is reverted.
-   *
-   * 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 safeTransferFrom(
-    address _from,
-    address _to,
-    uint256 _tokenId
-  )
-    public
-  {
-    // solium-disable-next-line arg-overflow
-    safeTransferFrom(_from, _to, _tokenId, "");
-  }
-
-  /**
-   * @dev Safely transfers the ownership of a given token ID to another address
-   * If the target address is a contract, it must implement `onERC721Received`,
-   * which is called upon a safe transfer, and return the magic value
-   * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
-   * the transfer is reverted.
-   * 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
-   * @param _data bytes data to send along with a safe transfer check
-   */
-  function safeTransferFrom(
-    address _from,
-    address _to,
-    uint256 _tokenId,
-    bytes _data
-  )
-    public
-  {
-    transferFrom(_from, _to, _tokenId);
-    // solium-disable-next-line arg-overflow
-    require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data));
-  }
-
-  /**
-   * @dev Returns whether the specified token exists
-   * @param _tokenId uint256 ID of the token to query the existence of
-   * @return whether the token exists
-   */
-  function _exists(uint256 _tokenId) internal view returns (bool) {
-    address owner = tokenOwner[_tokenId];
-    return owner != address(0);
-  }
-
-  /**
-   * @dev Returns whether the given spender can transfer a given token ID
-   * @param _spender address of the spender to query
-   * @param _tokenId uint256 ID of the token to be transferred
-   * @return bool whether the msg.sender is approved for the given token ID,
-   *  is an operator of the owner, or is the owner of the token
-   */
-  function isApprovedOrOwner(
-    address _spender,
-    uint256 _tokenId
-  )
-    internal
-    view
-    returns (bool)
-  {
-    address owner = ownerOf(_tokenId);
-    // Disable solium check because of
-    // https://github.com/duaraghav8/Solium/issues/175
-    // solium-disable-next-line operator-whitespace
-    return (
-      _spender == owner ||
-      getApproved(_tokenId) == _spender ||
-      isApprovedForAll(owner, _spender)
-    );
-  }
-
-  /**
-   * @dev Internal function to mint a new token
-   * Reverts if the given token ID already exists
-   * @param _to The address that will own the minted token
-   * @param _tokenId uint256 ID of the token to be minted by the msg.sender
-   */
-  function _mint(address _to, uint256 _tokenId) internal {
-    require(_to != address(0));
-    addTokenTo(_to, _tokenId);
-    emit Transfer(address(0), _to, _tokenId);
-  }
-
-  /**
-   * @dev Internal function to burn a specific token
-   * Reverts if the token does not exist
-   * @param _tokenId uint256 ID of the token being burned by the msg.sender
-   */
-  function _burn(address _owner, uint256 _tokenId) internal {
-    clearApproval(_owner, _tokenId);
-    removeTokenFrom(_owner, _tokenId);
-    emit Transfer(_owner, address(0), _tokenId);
-  }
-
-  /**
-   * @dev Internal function to clear current approval of a given token ID
-   * Reverts if the given address is not indeed the owner of the token
-   * @param _owner owner of the token
-   * @param _tokenId uint256 ID of the token to be transferred
-   */
-  function clearApproval(address _owner, uint256 _tokenId) internal {
-    require(ownerOf(_tokenId) == _owner);
-    if (tokenApprovals[_tokenId] != address(0)) {
-      tokenApprovals[_tokenId] = address(0);
-    }
-  }
-
-  /**
-   * @dev Internal function to add a token ID to the list of a given address
-   * @param _to address representing the new owner of the given token ID
-   * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
-   */
-  function addTokenTo(address _to, uint256 _tokenId) internal {
-    require(tokenOwner[_tokenId] == address(0));
-    tokenOwner[_tokenId] = _to;
-    ownedTokensCount[_to] = ownedTokensCount[_to].add(1);
-  }
-
-  /**
-   * @dev Internal function to remove a token ID from the list of a given address
-   * @param _from address representing the previous owner of the given token ID
-   * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
-   */
-  function removeTokenFrom(address _from, uint256 _tokenId) internal {
-    require(ownerOf(_tokenId) == _from);
-    ownedTokensCount[_from] = ownedTokensCount[_from].sub(1);
-    tokenOwner[_tokenId] = address(0);
-  }
-
-  /**
-   * @dev Internal function to invoke `onERC721Received` on a target address
-   * The call is not executed if the target address is not a contract
-   * @param _from address representing the previous owner of the given token ID
-   * @param _to target address that will receive the tokens
-   * @param _tokenId uint256 ID of the token to be transferred
-   * @param _data bytes optional data to send along with the call
-   * @return whether the call correctly returned the expected magic value
-   */
-  function checkAndCallSafeTransfer(
-    address _from,
-    address _to,
-    uint256 _tokenId,
-    bytes _data
-  )
-    internal
-    returns (bool)
-  {
-    if (!_to.isContract()) {
-      return true;
-    }
-    bytes4 retval = ERC721Receiver(_to).onERC721Received(
-      msg.sender, _from, _tokenId, _data);
-    return (retval == ERC721_RECEIVED);
-  }
-}

+ 2 - 2
contracts/token/ERC721/ERC721Holder.sol

@@ -1,9 +1,9 @@
 pragma solidity ^0.4.24;
 
-import "./ERC721Receiver.sol";
+import "./IERC721Receiver.sol";
 
 
-contract ERC721Holder is ERC721Receiver {
+contract ERC721Holder is IERC721Receiver {
   function onERC721Received(
     address,
     address,

+ 3 - 3
contracts/token/ERC721/ERC721PausableToken.sol → contracts/token/ERC721/ERC721Pausable.sol

@@ -1,14 +1,14 @@
 pragma solidity ^0.4.24;
 
-import "./ERC721BasicToken.sol";
+import "./ERC721Basic.sol";
 import "../../lifecycle/Pausable.sol";
 
 
 /**
  * @title ERC721 Non-Fungible Pausable token
- * @dev ERC721BasicToken modified with pausable transfers.
+ * @dev ERC721Basic modified with pausable transfers.
  **/
-contract ERC721PausableToken is ERC721BasicToken, Pausable {
+contract ERC721Pausable is ERC721Basic, Pausable {
   function approve(
     address _to,
     uint256 _tokenId

+ 0 - 201
contracts/token/ERC721/ERC721Token.sol

@@ -1,201 +0,0 @@
-pragma solidity ^0.4.24;
-
-import "./ERC721.sol";
-import "./ERC721BasicToken.sol";
-import "../../introspection/SupportsInterfaceWithLookup.sol";
-
-
-/**
- * @title Full ERC721 Token
- * This implementation includes all the required and some optional functionality of the ERC721 standard
- * Moreover, it includes approve all functionality using operator terminology
- * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
- */
-contract ERC721Token is SupportsInterfaceWithLookup, ERC721BasicToken, ERC721 {
-
-  // Token name
-  string internal name_;
-
-  // Token symbol
-  string internal symbol_;
-
-  // Mapping from owner to list of owned token IDs
-  mapping(address => uint256[]) internal ownedTokens;
-
-  // Mapping from token ID to index of the owner tokens list
-  mapping(uint256 => uint256) internal ownedTokensIndex;
-
-  // Array with all token ids, used for enumeration
-  uint256[] internal allTokens;
-
-  // Mapping from token id to position in the allTokens array
-  mapping(uint256 => uint256) internal allTokensIndex;
-
-  // Optional mapping for token URIs
-  mapping(uint256 => string) internal tokenURIs;
-
-  /**
-   * @dev Constructor function
-   */
-  constructor(string _name, string _symbol) public {
-    name_ = _name;
-    symbol_ = _symbol;
-
-    // register the supported interfaces to conform to ERC721 via ERC165
-    _registerInterface(InterfaceId_ERC721Enumerable);
-    _registerInterface(InterfaceId_ERC721Metadata);
-  }
-
-  /**
-   * @dev Gets the token name
-   * @return string representing the token name
-   */
-  function name() external view returns (string) {
-    return name_;
-  }
-
-  /**
-   * @dev Gets the token symbol
-   * @return string representing the token symbol
-   */
-  function symbol() external view returns (string) {
-    return symbol_;
-  }
-
-  /**
-   * @dev Returns an URI for a given token ID
-   * Throws if the token ID does not exist. May return an empty string.
-   * @param _tokenId uint256 ID of the token to query
-   */
-  function tokenURI(uint256 _tokenId) public view returns (string) {
-    require(_exists(_tokenId));
-    return tokenURIs[_tokenId];
-  }
-
-  /**
-   * @dev Gets the token ID at a given index of the tokens list of the requested owner
-   * @param _owner address owning the tokens list to be accessed
-   * @param _index uint256 representing the index to be accessed of the requested tokens list
-   * @return uint256 token ID at the given index of the tokens list owned by the requested address
-   */
-  function tokenOfOwnerByIndex(
-    address _owner,
-    uint256 _index
-  )
-    public
-    view
-    returns (uint256)
-  {
-    require(_index < balanceOf(_owner));
-    return ownedTokens[_owner][_index];
-  }
-
-  /**
-   * @dev Gets the total amount of tokens stored by the contract
-   * @return uint256 representing the total amount of tokens
-   */
-  function totalSupply() public view returns (uint256) {
-    return allTokens.length;
-  }
-
-  /**
-   * @dev Gets the token ID at a given index of all the tokens in this contract
-   * Reverts if the index is greater or equal to the total number of tokens
-   * @param _index uint256 representing the index to be accessed of the tokens list
-   * @return uint256 token ID at the given index of the tokens list
-   */
-  function tokenByIndex(uint256 _index) public view returns (uint256) {
-    require(_index < totalSupply());
-    return allTokens[_index];
-  }
-
-  /**
-   * @dev Internal function to set the token URI for a given token
-   * Reverts if the token ID does not exist
-   * @param _tokenId uint256 ID of the token to set its URI
-   * @param _uri string URI to assign
-   */
-  function _setTokenURI(uint256 _tokenId, string _uri) internal {
-    require(_exists(_tokenId));
-    tokenURIs[_tokenId] = _uri;
-  }
-
-  /**
-   * @dev Internal function to add a token ID to the list of a given address
-   * @param _to address representing the new owner of the given token ID
-   * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
-   */
-  function addTokenTo(address _to, uint256 _tokenId) internal {
-    super.addTokenTo(_to, _tokenId);
-    uint256 length = ownedTokens[_to].length;
-    ownedTokens[_to].push(_tokenId);
-    ownedTokensIndex[_tokenId] = length;
-  }
-
-  /**
-   * @dev Internal function to remove a token ID from the list of a given address
-   * @param _from address representing the previous owner of the given token ID
-   * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
-   */
-  function removeTokenFrom(address _from, uint256 _tokenId) internal {
-    super.removeTokenFrom(_from, _tokenId);
-
-    // To prevent a gap in the array, we store the last token in the index of the token to delete, and
-    // then delete the last slot.
-    uint256 tokenIndex = ownedTokensIndex[_tokenId];
-    uint256 lastTokenIndex = ownedTokens[_from].length.sub(1);
-    uint256 lastToken = ownedTokens[_from][lastTokenIndex];
-
-    ownedTokens[_from][tokenIndex] = lastToken;
-    // This also deletes the contents at the last position of the array
-    ownedTokens[_from].length--;
-
-    // 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
-
-    ownedTokensIndex[_tokenId] = 0;
-    ownedTokensIndex[lastToken] = tokenIndex;
-  }
-
-  /**
-   * @dev Internal function to mint a new token
-   * Reverts if the given token ID already exists
-   * @param _to address the beneficiary that will own the minted token
-   * @param _tokenId uint256 ID of the token to be minted by the msg.sender
-   */
-  function _mint(address _to, uint256 _tokenId) internal {
-    super._mint(_to, _tokenId);
-
-    allTokensIndex[_tokenId] = allTokens.length;
-    allTokens.push(_tokenId);
-  }
-
-  /**
-   * @dev Internal function to burn a specific token
-   * Reverts if the token does not exist
-   * @param _owner owner of the token to burn
-   * @param _tokenId uint256 ID of the token being burned by the msg.sender
-   */
-  function _burn(address _owner, uint256 _tokenId) internal {
-    super._burn(_owner, _tokenId);
-
-    // Clear metadata (if any)
-    if (bytes(tokenURIs[_tokenId]).length != 0) {
-      delete tokenURIs[_tokenId];
-    }
-
-    // Reorg all tokens array
-    uint256 tokenIndex = allTokensIndex[_tokenId];
-    uint256 lastTokenIndex = allTokens.length.sub(1);
-    uint256 lastToken = allTokens[lastTokenIndex];
-
-    allTokens[tokenIndex] = lastToken;
-    allTokens[lastTokenIndex] = 0;
-
-    allTokens.length--;
-    allTokensIndex[_tokenId] = 0;
-    allTokensIndex[lastToken] = tokenIndex;
-  }
-
-}

+ 2 - 2
contracts/token/ERC721/DeprecatedERC721.sol → contracts/token/ERC721/IDeprecatedERC721.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.24;
 
-import "./ERC721.sol";
+import "./IERC721.sol";
 
 
 /**
@@ -8,7 +8,7 @@ import "./ERC721.sol";
  * @dev Only use this interface for compatibility with previously deployed contracts
  * Use ERC721 for interacting with new contracts which are standard-compliant
  */
-contract DeprecatedERC721 is ERC721 {
+contract IDeprecatedERC721 is IERC721 {
   function takeOwnership(uint256 _tokenId) public;
   function transfer(address _to, uint256 _tokenId) public;
   function tokensOf(address _owner) public view returns (uint256[]);

+ 40 - 0
contracts/token/ERC721/IERC721.sol

@@ -0,0 +1,40 @@
+pragma solidity ^0.4.24;
+
+import "./IERC721Basic.sol";
+
+
+/**
+ * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
+ * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
+ */
+contract IERC721Enumerable is IERC721Basic {
+  function totalSupply() public view returns (uint256);
+  function tokenOfOwnerByIndex(
+    address _owner,
+    uint256 _index
+  )
+    public
+    view
+    returns (uint256 _tokenId);
+
+  function tokenByIndex(uint256 _index) public view returns (uint256);
+}
+
+
+/**
+ * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
+ * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
+ */
+contract IERC721Metadata is IERC721Basic {
+  function name() external view returns (string _name);
+  function symbol() external view returns (string _symbol);
+  function tokenURI(uint256 _tokenId) public view returns (string);
+}
+
+
+/**
+ * @title ERC-721 Non-Fungible Token Standard, full implementation interface
+ * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
+ */
+contract IERC721 is IERC721Basic, IERC721Enumerable, IERC721Metadata {
+}

+ 80 - 0
contracts/token/ERC721/IERC721Basic.sol

@@ -0,0 +1,80 @@
+pragma solidity ^0.4.24;
+
+import "../../introspection/IERC165.sol";
+
+
+/**
+ * @title ERC721 Non-Fungible Token Standard basic interface
+ * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
+ */
+contract IERC721Basic is IERC165 {
+
+  bytes4 internal constant InterfaceId_ERC721 = 0x80ac58cd;
+  /*
+   * 0x80ac58cd ===
+   *   bytes4(keccak256('balanceOf(address)')) ^
+   *   bytes4(keccak256('ownerOf(uint256)')) ^
+   *   bytes4(keccak256('approve(address,uint256)')) ^
+   *   bytes4(keccak256('getApproved(uint256)')) ^
+   *   bytes4(keccak256('setApprovalForAll(address,bool)')) ^
+   *   bytes4(keccak256('isApprovedForAll(address,address)')) ^
+   *   bytes4(keccak256('transferFrom(address,address,uint256)')) ^
+   *   bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
+   *   bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
+   */
+
+  bytes4 internal constant InterfaceId_ERC721Enumerable = 0x780e9d63;
+  /**
+   * 0x780e9d63 ===
+   *   bytes4(keccak256('totalSupply()')) ^
+   *   bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^
+   *   bytes4(keccak256('tokenByIndex(uint256)'))
+   */
+
+  bytes4 internal constant InterfaceId_ERC721Metadata = 0x5b5e139f;
+  /**
+   * 0x5b5e139f ===
+   *   bytes4(keccak256('name()')) ^
+   *   bytes4(keccak256('symbol()')) ^
+   *   bytes4(keccak256('tokenURI(uint256)'))
+   */
+
+  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) public view returns (uint256 _balance);
+  function ownerOf(uint256 _tokenId) public view returns (address _owner);
+
+  function approve(address _to, uint256 _tokenId) public;
+  function getApproved(uint256 _tokenId)
+    public view returns (address _operator);
+
+  function setApprovalForAll(address _operator, bool _approved) public;
+  function isApprovedForAll(address _owner, address _operator)
+    public view returns (bool);
+
+  function transferFrom(address _from, address _to, uint256 _tokenId) public;
+  function safeTransferFrom(address _from, address _to, uint256 _tokenId)
+    public;
+
+  function safeTransferFrom(
+    address _from,
+    address _to,
+    uint256 _tokenId,
+    bytes _data
+  )
+    public;
+}

+ 2 - 2
contracts/token/ERC721/ERC721Receiver.sol → contracts/token/ERC721/IERC721Receiver.sol

@@ -6,11 +6,11 @@ pragma solidity ^0.4.24;
  * @dev Interface for any contract that wants to support safeTransfers
  * from ERC721 asset contracts.
  */
-contract ERC721Receiver {
+contract IERC721Receiver {
   /**
    * @dev Magic value to be returned upon successful reception of an NFT
    *  Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`,
-   *  which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
+   *  which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
    */
   bytes4 internal constant ERC721_RECEIVED = 0x150b7a02;
 

+ 2 - 2
test/crowdsale/FinalizableCrowdsale.test.js

@@ -11,7 +11,7 @@ const should = require('chai')
   .should();
 
 const FinalizableCrowdsale = artifacts.require('FinalizableCrowdsaleImpl');
-const MintableToken = artifacts.require('MintableToken');
+const ERC20Mintable = artifacts.require('ERC20Mintable');
 
 contract('FinalizableCrowdsale', function ([_, owner, wallet, thirdparty]) {
   const rate = new BigNumber(1000);
@@ -26,7 +26,7 @@ contract('FinalizableCrowdsale', function ([_, owner, wallet, thirdparty]) {
     this.closingTime = this.openingTime + duration.weeks(1);
     this.afterClosingTime = this.closingTime + duration.seconds(1);
 
-    this.token = await MintableToken.new();
+    this.token = await ERC20Mintable.new();
     this.crowdsale = await FinalizableCrowdsale.new(
       this.openingTime, this.closingTime, rate, wallet, this.token.address, { from: owner }
     );

+ 5 - 5
test/crowdsale/MintedCrowdsale.test.js

@@ -5,17 +5,17 @@ const { assertRevert } = require('../helpers/assertRevert');
 const BigNumber = web3.BigNumber;
 
 const MintedCrowdsale = artifacts.require('MintedCrowdsaleImpl');
-const MintableToken = artifacts.require('MintableToken');
+const ERC20Mintable = artifacts.require('ERC20Mintable');
 const RBACMintableToken = artifacts.require('RBACMintableToken');
-const StandardToken = artifacts.require('StandardToken');
+const ERC20 = artifacts.require('ERC20');
 
 contract('MintedCrowdsale', function ([_, investor, wallet, purchaser]) {
   const rate = new BigNumber(1000);
   const value = ether(5);
 
-  describe('using MintableToken', function () {
+  describe('using ERC20Mintable', function () {
     beforeEach(async function () {
-      this.token = await MintableToken.new();
+      this.token = await ERC20Mintable.new();
       this.crowdsale = await MintedCrowdsale.new(rate, wallet, this.token.address);
       await this.token.transferOwnership(this.crowdsale.address);
     });
@@ -45,7 +45,7 @@ contract('MintedCrowdsale', function ([_, investor, wallet, purchaser]) {
 
   describe('using non-mintable token', function () {
     beforeEach(async function () {
-      this.token = await StandardToken.new();
+      this.token = await ERC20.new();
       this.crowdsale = await MintedCrowdsale.new(rate, wallet, this.token.address);
     });
 

+ 2 - 2
test/lifecycle/TokenDestructible.test.js

@@ -1,7 +1,7 @@
 const { ethGetBalance } = require('../helpers/web3');
 
 const TokenDestructible = artifacts.require('TokenDestructible');
-const StandardTokenMock = artifacts.require('StandardTokenMock');
+const ERC20Mock = artifacts.require('ERC20Mock');
 
 const BigNumber = web3.BigNumber;
 
@@ -28,7 +28,7 @@ contract('TokenDestructible', function ([_, owner]) {
   });
 
   it('should send tokens to owner after destruction', async function () {
-    const token = await StandardTokenMock.new(tokenDestructible.address, 100);
+    const token = await ERC20Mock.new(tokenDestructible.address, 100);
     (await token.balanceOf(tokenDestructible.address)).should.be.bignumber.equal(100);
     (await token.balanceOf(owner)).should.be.bignumber.equal(0);
 

+ 2 - 2
test/ownership/CanReclaimToken.test.js

@@ -1,7 +1,7 @@
 const { expectThrow } = require('../helpers/expectThrow');
 
 const CanReclaimToken = artifacts.require('CanReclaimToken');
-const StandardTokenMock = artifacts.require('StandardTokenMock');
+const ERC20Mock = artifacts.require('ERC20Mock');
 
 const BigNumber = web3.BigNumber;
 
@@ -15,7 +15,7 @@ contract('CanReclaimToken', function ([_, owner, anyone]) {
 
   beforeEach(async function () {
     // Create contract and token
-    token = await StandardTokenMock.new(owner, 100, { from: owner });
+    token = await ERC20Mock.new(owner, 100, { from: owner });
     canReclaimToken = await CanReclaimToken.new({ from: owner });
 
     // Force token into contract

+ 0 - 12
test/token/ERC20/BurnableToken.test.js

@@ -1,12 +0,0 @@
-const { shouldBehaveLikeBurnableToken } = require('./BurnableToken.behavior');
-const BurnableTokenMock = artifacts.require('BurnableTokenMock');
-
-contract('BurnableToken', function ([_, owner, ...otherAccounts]) {
-  const initialBalance = 1000;
-
-  beforeEach(async function () {
-    this.token = await BurnableTokenMock.new(owner, initialBalance, { from: owner });
-  });
-
-  shouldBehaveLikeBurnableToken(owner, initialBalance, otherAccounts);
-});

+ 0 - 25
test/token/ERC20/CappedToken.test.js

@@ -1,25 +0,0 @@
-const { assertRevert } = require('../../helpers/assertRevert');
-const { ether } = require('../../helpers/ether');
-const { shouldBehaveLikeMintableToken } = require('./MintableToken.behavior');
-const { shouldBehaveLikeCappedToken } = require('./CappedToken.behavior');
-
-const CappedToken = artifacts.require('CappedToken');
-
-contract('Capped', function ([_, owner, ...otherAccounts]) {
-  const cap = ether(1000);
-
-  it('requires a non-zero cap', async function () {
-    await assertRevert(
-      CappedToken.new(0, { from: owner })
-    );
-  });
-
-  context('once deployed', async function () {
-    beforeEach(async function () {
-      this.token = await CappedToken.new(cap, { from: owner });
-    });
-
-    shouldBehaveLikeCappedToken(owner, otherAccounts, cap);
-    shouldBehaveLikeMintableToken(owner, owner, otherAccounts);
-  });
-});

+ 3 - 3
test/token/ERC20/DetailedERC20.test.js

@@ -4,9 +4,9 @@ require('chai')
   .use(require('chai-bignumber')(BigNumber))
   .should();
 
-const DetailedERC20Mock = artifacts.require('DetailedERC20Mock');
+const ERC20DetailedMock = artifacts.require('ERC20DetailedMock');
 
-contract('DetailedERC20', function () {
+contract('ERC20Detailed', function () {
   let detailedERC20 = null;
 
   const _name = 'My Detailed ERC20';
@@ -14,7 +14,7 @@ contract('DetailedERC20', function () {
   const _decimals = 18;
 
   beforeEach(async function () {
-    detailedERC20 = await DetailedERC20Mock.new(_name, _symbol, _decimals);
+    detailedERC20 = await ERC20DetailedMock.new(_name, _symbol, _decimals);
   });
 
   it('has a name', async function () {

+ 3 - 3
test/token/ERC20/StandardToken.test.js → test/token/ERC20/ERC20.test.js

@@ -1,7 +1,7 @@
 const { assertRevert } = require('../../helpers/assertRevert');
 const expectEvent = require('../../helpers/expectEvent');
 
-const StandardToken = artifacts.require('StandardTokenMock');
+const ERC20 = artifacts.require('ERC20Mock');
 
 const BigNumber = web3.BigNumber;
 
@@ -9,11 +9,11 @@ require('chai')
   .use(require('chai-bignumber')(BigNumber))
   .should();
 
-contract('StandardToken', function ([_, owner, recipient, anotherAccount]) {
+contract('ERC20', function ([_, owner, recipient, anotherAccount]) {
   const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
 
   beforeEach(async function () {
-    this.token = await StandardToken.new(owner, 100);
+    this.token = await ERC20.new(owner, 100);
   });
 
   describe('total supply', function () {

+ 2 - 2
test/token/ERC20/BurnableToken.behavior.js → test/token/ERC20/ERC20Burnable.behavior.js

@@ -8,7 +8,7 @@ require('chai')
   .use(require('chai-bignumber')(BigNumber))
   .should();
 
-function shouldBehaveLikeBurnableToken (owner, initialBalance, [burner]) {
+function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) {
   describe('burn', function () {
     describe('when the given amount is not greater than balance of the sender', function () {
       context('for a zero amount', function () {
@@ -113,5 +113,5 @@ function shouldBehaveLikeBurnableToken (owner, initialBalance, [burner]) {
 }
 
 module.exports = {
-  shouldBehaveLikeBurnableToken,
+  shouldBehaveLikeERC20Burnable,
 };

+ 12 - 0
test/token/ERC20/ERC20Burnable.test.js

@@ -0,0 +1,12 @@
+const { shouldBehaveLikeERC20Burnable } = require('./ERC20Burnable.behavior');
+const ERC20BurnableMock = artifacts.require('ERC20BurnableMock');
+
+contract('ERC20Burnable', function ([_, owner, ...otherAccounts]) {
+  const initialBalance = 1000;
+
+  beforeEach(async function () {
+    this.token = await ERC20BurnableMock.new(owner, initialBalance, { from: owner });
+  });
+
+  shouldBehaveLikeERC20Burnable(owner, initialBalance, otherAccounts);
+});

+ 2 - 2
test/token/ERC20/CappedToken.behavior.js → test/token/ERC20/ERC20Capped.behavior.js

@@ -7,7 +7,7 @@ require('chai')
   .use(require('chai-bignumber')(BigNumber))
   .should();
 
-function shouldBehaveLikeCappedToken (minter, [anyone], cap) {
+function shouldBehaveLikeERC20Capped (minter, [anyone], cap) {
   describe('capped token', function () {
     const from = minter;
 
@@ -33,5 +33,5 @@ function shouldBehaveLikeCappedToken (minter, [anyone], cap) {
 }
 
 module.exports = {
-  shouldBehaveLikeCappedToken,
+  shouldBehaveLikeERC20Capped,
 };

+ 25 - 0
test/token/ERC20/ERC20Capped.test.js

@@ -0,0 +1,25 @@
+const { assertRevert } = require('../../helpers/assertRevert');
+const { ether } = require('../../helpers/ether');
+const { shouldBehaveLikeERC20Mintable } = require('./ERC20Mintable.behavior');
+const { shouldBehaveLikeERC20Capped } = require('./ERC20Capped.behavior');
+
+const ERC20Capped = artifacts.require('ERC20Capped');
+
+contract('ERC20Capped', function ([_, owner, ...otherAccounts]) {
+  const cap = ether(1000);
+
+  it('requires a non-zero cap', async function () {
+    await assertRevert(
+      ERC20Capped.new(0, { from: owner })
+    );
+  });
+
+  context('once deployed', async function () {
+    beforeEach(async function () {
+      this.token = await ERC20Capped.new(cap, { from: owner });
+    });
+
+    shouldBehaveLikeERC20Capped(owner, otherAccounts, cap);
+    shouldBehaveLikeERC20Mintable(owner, owner, otherAccounts);
+  });
+});

+ 2 - 2
test/token/ERC20/MintableToken.behavior.js → test/token/ERC20/ERC20Mintable.behavior.js

@@ -7,7 +7,7 @@ require('chai')
   .use(require('chai-bignumber')(BigNumber))
   .should();
 
-function shouldBehaveLikeMintableToken (owner, minter, [anyone]) {
+function shouldBehaveLikeERC20Mintable (owner, minter, [anyone]) {
   const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
 
   describe('as a basic mintable token', function () {
@@ -160,5 +160,5 @@ function shouldBehaveLikeMintableToken (owner, minter, [anyone]) {
 }
 
 module.exports = {
-  shouldBehaveLikeMintableToken,
+  shouldBehaveLikeERC20Mintable,
 };

+ 10 - 0
test/token/ERC20/ERC20Mintable.test.js

@@ -0,0 +1,10 @@
+const { shouldBehaveLikeERC20Mintable } = require('./ERC20Mintable.behavior');
+const ERC20Mintable = artifacts.require('ERC20Mintable');
+
+contract('ERC20Mintable', function ([_, owner, ...otherAccounts]) {
+  beforeEach(async function () {
+    this.token = await ERC20Mintable.new({ from: owner });
+  });
+
+  shouldBehaveLikeERC20Mintable(owner, owner, otherAccounts);
+});

+ 3 - 3
test/token/ERC20/PausableToken.test.js → test/token/ERC20/ERC20Pausable.test.js

@@ -1,9 +1,9 @@
 const { assertRevert } = require('../../helpers/assertRevert');
-const PausableToken = artifacts.require('PausableTokenMock');
+const ERC20Pausable = artifacts.require('ERC20PausableMock');
 
-contract('PausableToken', function ([_, owner, recipient, anotherAccount]) {
+contract('ERC20Pausable', function ([_, owner, recipient, anotherAccount]) {
   beforeEach(async function () {
-    this.token = await PausableToken.new(owner, 100, { from: owner });
+    this.token = await ERC20Pausable.new(owner, 100, { from: owner });
   });
 
   describe('pause', function () {

+ 0 - 10
test/token/ERC20/MintableToken.test.js

@@ -1,10 +0,0 @@
-const { shouldBehaveLikeMintableToken } = require('./MintableToken.behavior');
-const MintableToken = artifacts.require('MintableToken');
-
-contract('MintableToken', function ([_, owner, ...otherAccounts]) {
-  beforeEach(async function () {
-    this.token = await MintableToken.new({ from: owner });
-  });
-
-  shouldBehaveLikeMintableToken(owner, owner, otherAccounts);
-});

+ 4 - 4
test/token/ERC20/RBACCappedToken.test.js

@@ -1,7 +1,7 @@
 const { ether } = require('../../helpers/ether');
 const { shouldBehaveLikeRBACMintableToken } = require('./RBACMintableToken.behavior');
-const { shouldBehaveLikeMintableToken } = require('./MintableToken.behavior');
-const { shouldBehaveLikeCappedToken } = require('./CappedToken.behavior');
+const { shouldBehaveLikeERC20Mintable } = require('./ERC20Mintable.behavior');
+const { shouldBehaveLikeERC20Capped } = require('./ERC20Capped.behavior');
 
 const RBACCappedTokenMock = artifacts.require('RBACCappedTokenMock');
 
@@ -13,7 +13,7 @@ contract('RBACCappedToken', function ([_, owner, minter, ...otherAccounts]) {
     await this.token.addMinter(minter, { from: owner });
   });
 
-  shouldBehaveLikeMintableToken(owner, minter, otherAccounts);
+  shouldBehaveLikeERC20Mintable(owner, minter, otherAccounts);
   shouldBehaveLikeRBACMintableToken(owner, otherAccounts);
-  shouldBehaveLikeCappedToken(minter, otherAccounts, cap);
+  shouldBehaveLikeERC20Capped(minter, otherAccounts, cap);
 });

+ 2 - 2
test/token/ERC20/RBACMintableToken.test.js

@@ -1,5 +1,5 @@
 const { shouldBehaveLikeRBACMintableToken } = require('./RBACMintableToken.behavior');
-const { shouldBehaveLikeMintableToken } = require('./MintableToken.behavior');
+const { shouldBehaveLikeERC20Mintable } = require('./ERC20Mintable.behavior');
 
 const RBACMintableToken = artifacts.require('RBACMintableToken');
 
@@ -10,5 +10,5 @@ contract('RBACMintableToken', function ([_, owner, minter, ...otherAccounts]) {
   });
 
   shouldBehaveLikeRBACMintableToken(owner, otherAccounts);
-  shouldBehaveLikeMintableToken(owner, minter, otherAccounts);
+  shouldBehaveLikeERC20Mintable(owner, minter, otherAccounts);
 });

+ 2 - 2
test/token/ERC20/TokenTimelock.test.js

@@ -8,7 +8,7 @@ require('chai')
   .use(require('chai-bignumber')(BigNumber))
   .should();
 
-const MintableToken = artifacts.require('MintableToken');
+const ERC20Mintable = artifacts.require('ERC20Mintable');
 const TokenTimelock = artifacts.require('TokenTimelock');
 
 contract('TokenTimelock', function ([_, owner, beneficiary]) {
@@ -16,7 +16,7 @@ contract('TokenTimelock', function ([_, owner, beneficiary]) {
 
   context('with token', function () {
     beforeEach(async function () {
-      this.token = await MintableToken.new({ from: owner });
+      this.token = await ERC20Mintable.new({ from: owner });
     });
 
     it('rejects a release time in the past', async function () {

+ 2 - 2
test/token/ERC20/TokenVesting.test.js

@@ -10,7 +10,7 @@ require('chai')
   .use(require('chai-bignumber')(BigNumber))
   .should();
 
-const MintableToken = artifacts.require('MintableToken');
+const ERC20Mintable = artifacts.require('ERC20Mintable');
 const TokenVesting = artifacts.require('TokenVesting');
 
 contract('TokenVesting', function ([_, owner, beneficiary]) {
@@ -44,7 +44,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) {
     beforeEach(async function () {
       this.vesting = await TokenVesting.new(beneficiary, this.start, this.cliff, this.duration, true, { from: owner });
 
-      this.token = await MintableToken.new({ from: owner });
+      this.token = await ERC20Mintable.new({ from: owner });
       await this.token.mint(this.vesting.address, amount, { from: owner });
     });
 

+ 7 - 7
test/token/ERC721/ERC721Token.test.js → test/token/ERC721/ERC721.test.js

@@ -1,17 +1,17 @@
 const { assertRevert } = require('../../helpers/assertRevert');
-const { shouldBehaveLikeERC721BasicToken } = require('./ERC721BasicToken.behavior');
-const { shouldBehaveLikeMintAndBurnERC721Token } = require('./ERC721MintBurn.behavior');
+const { shouldBehaveLikeERC721Basic } = require('./ERC721Basic.behavior');
+const { shouldBehaveLikeMintAndBurnERC721 } = require('./ERC721MintBurn.behavior');
 const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior');
 const _ = require('lodash');
 
 const BigNumber = web3.BigNumber;
-const ERC721Token = artifacts.require('ERC721TokenMock.sol');
+const ERC721 = artifacts.require('ERC721Mock.sol');
 
 require('chai')
   .use(require('chai-bignumber')(BigNumber))
   .should();
 
-contract('ERC721Token', function (accounts) {
+contract('ERC721', function (accounts) {
   const name = 'Non Fungible Token';
   const symbol = 'NFT';
   const firstTokenId = 100;
@@ -21,11 +21,11 @@ contract('ERC721Token', function (accounts) {
   const anyone = accounts[9];
 
   beforeEach(async function () {
-    this.token = await ERC721Token.new(name, symbol, { from: creator });
+    this.token = await ERC721.new(name, symbol, { from: creator });
   });
 
-  shouldBehaveLikeERC721BasicToken(accounts);
-  shouldBehaveLikeMintAndBurnERC721Token(accounts);
+  shouldBehaveLikeERC721Basic(accounts);
+  shouldBehaveLikeMintAndBurnERC721(accounts);
 
   describe('like a full ERC721', function () {
     beforeEach(async function () {

+ 3 - 3
test/token/ERC721/ERC721BasicToken.behavior.js → test/token/ERC721/ERC721Basic.behavior.js

@@ -11,7 +11,7 @@ require('chai')
   .use(require('chai-bignumber')(BigNumber))
   .should();
 
-function shouldBehaveLikeERC721BasicToken (accounts) {
+function shouldBehaveLikeERC721Basic (accounts) {
   const firstTokenId = 1;
   const secondTokenId = 2;
   const unknownTokenId = 3;
@@ -19,7 +19,7 @@ function shouldBehaveLikeERC721BasicToken (accounts) {
   const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
   const RECEIVER_MAGIC_VALUE = '0x150b7a02';
 
-  describe('like an ERC721BasicToken', function () {
+  describe('like an ERC721Basic', function () {
     beforeEach(async function () {
       await this.token.mint(creator, firstTokenId, { from: creator });
       await this.token.mint(creator, secondTokenId, { from: creator });
@@ -521,5 +521,5 @@ function shouldBehaveLikeERC721BasicToken (accounts) {
 }
 
 module.exports = {
-  shouldBehaveLikeERC721BasicToken,
+  shouldBehaveLikeERC721Basic,
 };

+ 18 - 0
test/token/ERC721/ERC721Basic.test.js

@@ -0,0 +1,18 @@
+const { shouldBehaveLikeERC721Basic } = require('./ERC721Basic.behavior');
+const { shouldBehaveLikeMintAndBurnERC721 } = require('./ERC721MintBurn.behavior');
+
+const BigNumber = web3.BigNumber;
+const ERC721Basic = artifacts.require('ERC721BasicMock.sol');
+
+require('chai')
+  .use(require('chai-bignumber')(BigNumber))
+  .should();
+
+contract('ERC721Basic', function (accounts) {
+  beforeEach(async function () {
+    this.token = await ERC721Basic.new({ from: accounts[0] });
+  });
+
+  shouldBehaveLikeERC721Basic(accounts);
+  shouldBehaveLikeMintAndBurnERC721(accounts);
+});

+ 0 - 18
test/token/ERC721/ERC721BasicToken.test.js

@@ -1,18 +0,0 @@
-const { shouldBehaveLikeERC721BasicToken } = require('./ERC721BasicToken.behavior');
-const { shouldBehaveLikeMintAndBurnERC721Token } = require('./ERC721MintBurn.behavior');
-
-const BigNumber = web3.BigNumber;
-const ERC721BasicToken = artifacts.require('ERC721BasicTokenMock.sol');
-
-require('chai')
-  .use(require('chai-bignumber')(BigNumber))
-  .should();
-
-contract('ERC721BasicToken', function (accounts) {
-  beforeEach(async function () {
-    this.token = await ERC721BasicToken.new({ from: accounts[0] });
-  });
-
-  shouldBehaveLikeERC721BasicToken(accounts);
-  shouldBehaveLikeMintAndBurnERC721Token(accounts);
-});

+ 3 - 3
test/token/ERC721/ERC721MintBurn.behavior.js

@@ -5,14 +5,14 @@ require('chai')
   .use(require('chai-bignumber')(BigNumber))
   .should();
 
-function shouldBehaveLikeMintAndBurnERC721Token (accounts) {
+function shouldBehaveLikeMintAndBurnERC721 (accounts) {
   const firstTokenId = 1;
   const secondTokenId = 2;
   const unknownTokenId = 3;
   const creator = accounts[0];
   const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
 
-  describe('like a mintable and burnable ERC721Token', function () {
+  describe('like a mintable and burnable ERC721', function () {
     beforeEach(async function () {
       await this.token.mint(creator, firstTokenId, { from: creator });
       await this.token.mint(creator, secondTokenId, { from: creator });
@@ -106,5 +106,5 @@ function shouldBehaveLikeMintAndBurnERC721Token (accounts) {
 }
 
 module.exports = {
-  shouldBehaveLikeMintAndBurnERC721Token,
+  shouldBehaveLikeMintAndBurnERC721,
 };

+ 6 - 6
test/token/ERC721/ERC721PausableToken.test.js → test/token/ERC721/ERC721Pausable.test.js

@@ -1,16 +1,16 @@
 const { shouldBehaveLikeERC721PausedToken } = require('./ERC721PausedToken.behavior');
-const { shouldBehaveLikeERC721BasicToken } = require('./ERC721BasicToken.behavior');
+const { shouldBehaveLikeERC721Basic } = require('./ERC721Basic.behavior');
 
 const BigNumber = web3.BigNumber;
-const ERC721PausableToken = artifacts.require('ERC721PausableTokenMock.sol');
+const ERC721Pausable = artifacts.require('ERC721PausableMock.sol');
 
 require('chai')
   .use(require('chai-bignumber')(BigNumber))
   .should();
 
-contract('ERC721PausableToken', function ([_, owner, recipient, operator, ...otherAccounts]) {
+contract('ERC721Pausable', function ([_, owner, recipient, operator, ...otherAccounts]) {
   beforeEach(async function () {
-    this.token = await ERC721PausableToken.new({ from: owner });
+    this.token = await ERC721Pausable.new({ from: owner });
   });
 
   context('when token is paused', function () {
@@ -22,7 +22,7 @@ contract('ERC721PausableToken', function ([_, owner, recipient, operator, ...oth
   });
 
   context('when token is not paused yet', function () {
-    shouldBehaveLikeERC721BasicToken([owner, ...otherAccounts]);
+    shouldBehaveLikeERC721Basic([owner, ...otherAccounts]);
   });
 
   context('when token is paused and then unpaused', function () {
@@ -31,6 +31,6 @@ contract('ERC721PausableToken', function ([_, owner, recipient, operator, ...oth
       await this.token.unpause({ from: owner });
     });
 
-    shouldBehaveLikeERC721BasicToken([owner, ...otherAccounts]);
+    shouldBehaveLikeERC721Basic([owner, ...otherAccounts]);
   });
 });

+ 1 - 1
test/token/ERC721/ERC721PausedToken.behavior.js

@@ -13,7 +13,7 @@ function shouldBehaveLikeERC721PausedToken (owner, [recipient, operator]) {
   const mockData = '0x42';
   const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
 
-  describe('like a paused ERC721Token', function () {
+  describe('like a paused ERC721', function () {
     beforeEach(async function () {
       await this.token.mint(owner, firstTokenId, { from: owner });
     });