Browse Source

Add a simple wrapper for address. (#1773)

* Updated code style to no more than120 characters per line.

* Unify code comments style with Doxygen-style tags.

* Fix the conflicts.

* Add a return value in the contract ERC20Burnable.

* A Add a wrapper function to change type of address to address payable.

* U Modify Address utils.

* A Add test case for Address.

* U Modify code style in ERC20Burnable.

* Add changelog entry.

* Improved dev docs.
skyge 6 years ago
parent
commit
b95d7e7f8a
4 changed files with 41 additions and 6 deletions
  1. 5 0
      CHANGELOG.md
  2. 4 0
      contracts/mocks/AddressImpl.sol
  3. 8 0
      contracts/utils/Address.sol
  4. 24 6
      test/utils/Address.test.js

+ 5 - 0
CHANGELOG.md

@@ -1,5 +1,10 @@
 # Changelog
 
+## 2.4.0 (unreleased)
+
+### New features:
+ * `Address.toPayable`: added a helper to convert between address types without having to resort to low-level casting. ([#1773](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1773))
+
 ## 2.3.0 (2019-05-27)
 
 ### New features:

+ 4 - 0
contracts/mocks/AddressImpl.sol

@@ -6,4 +6,8 @@ contract AddressImpl {
     function isContract(address account) external view returns (bool) {
         return Address.isContract(account);
     }
+
+    function toPayable(address account) external pure returns (address payable) {
+        return Address.toPayable(account);
+    }
 }

+ 8 - 0
contracts/utils/Address.sol

@@ -24,4 +24,12 @@ library Address {
         assembly { size := extcodesize(account) }
         return size > 0;
     }
+
+    /**
+     * @dev Converts an `address` into `address payable`. Note that this is
+     * simply a type cast: the actual underlying value is not changed.
+     */
+    function toPayable(address account) internal pure returns (address payable) {
+        return address(uint160(account));
+    }
 }

+ 24 - 6
test/utils/Address.test.js

@@ -1,19 +1,37 @@
-require('openzeppelin-test-helpers');
+const { constants } = require('openzeppelin-test-helpers');
 
 const AddressImpl = artifacts.require('AddressImpl');
 const SimpleToken = artifacts.require('SimpleToken');
 
 contract('Address', function ([_, other]) {
+  const ALL_ONES_ADDRESS = '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF';
+
   beforeEach(async function () {
     this.mock = await AddressImpl.new();
   });
 
-  it('should return false for account address', async function () {
-    (await this.mock.isContract(other)).should.equal(false);
+  describe('isContract', function () {
+    it('should return false for account address', async function () {
+      (await this.mock.isContract(other)).should.equal(false);
+    });
+
+    it('should return true for contract address', async function () {
+      const contract = await SimpleToken.new();
+      (await this.mock.isContract(contract.address)).should.equal(true);
+    });
   });
 
-  it('should return true for contract address', async function () {
-    const contract = await SimpleToken.new();
-    (await this.mock.isContract(contract.address)).should.equal(true);
+  describe('toPayable', function () {
+    it('should return a payable address when the account is the zero address', async function () {
+      (await this.mock.toPayable(constants.ZERO_ADDRESS)).should.equal(constants.ZERO_ADDRESS);
+    });
+
+    it('should return a payable address when the account is an arbitrary address', async function () {
+      (await this.mock.toPayable(other)).should.equal(other);
+    });
+
+    it('should return a payable address when the account is the all ones address', async function () {
+      (await this.mock.toPayable(ALL_ONES_ADDRESS)).should.equal(ALL_ONES_ADDRESS);
+    });
   });
 });