Compare commits

...

5 Commits

Author SHA1 Message Date
58a3368215 2.5.0 2020-02-04 19:39:23 -03:00
941d305044 Update docs 2020-02-04 19:35:31 -03:00
1b938e39a8 EnumerableSet improvements (#2077)
* Remove newAddressSet

* Add count and get functions.

* Fix lint

(cherry picked from commit 7988c044e0)
2020-02-04 19:33:57 -03:00
0ac83ce289 Fix EnumerableSetMock for 2.5.rc1 (#2069)
* Drafted Enumerable.sol.

* Drafted test framework.

* Tweaked the tests to follow oz structure.

* Coded EnumerableSet.

* Moved EnumerableSet to `utils`.

* Fixed linting.

* Improved comments.

* Tweaked contract description.

* Renamed struct to AddressSet.

* Relaxed version pragma to 0.5.0

* Removed events.

* Revert on useless operations.

* Small comment.

* Created AddressSet factory method.

* Failed transactions return false.

* Transactions now return false on failure.

* Remove comments from mock

* Rename mock functions

* Adapt tests to code style, use test-helpers

* Fix bug in remove, improve tests.

* Add changelog entry

* Add entry on Utils doc

* Add optimization for removal of last slot

* Update docs

* Fix headings of utilities documentation

* Simplified mock.

* Fixed comment.

* Revert "Fixed comment."

This reverts commit 39627f9a6f.

* Revert "Simplified mock."

This reverts commit 67468e464b.

* Simplified mock.

Co-authored-by: Nicolás Venturo <nicolas.venturo@gmail.com>
(cherry picked from commit 8975289c6b)
2020-02-04 18:06:34 -03:00
d775e315cc Update package homepage. 2020-01-24 15:07:37 -03:00
8 changed files with 72 additions and 42 deletions

View File

@ -1,6 +1,6 @@
# Changelog
## 2.5.0 (unreleased)
## 2.5.0 (2020-02-04)
### New features
* `SafeCast.toUintXX`: new library for integer downcasting, which allows for safe operation on smaller types (e.g. `uint32`) when combined with `SafeMath`. ([#1926](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1926))

View File

@ -9,25 +9,29 @@ contract EnumerableSetMock{
EnumerableSet.AddressSet private set;
constructor() public {
set = EnumerableSet.newAddressSet();
}
function contains(address value) public view returns (bool) {
return EnumerableSet.contains(set, value);
return set.contains(value);
}
function add(address value) public {
bool result = EnumerableSet.add(set, value);
bool result = set.add(value);
emit TransactionResult(result);
}
function remove(address value) public {
bool result = EnumerableSet.remove(set, value);
bool result = set.remove(value);
emit TransactionResult(result);
}
function enumerate() public view returns (address[] memory) {
return EnumerableSet.enumerate(set);
return set.enumerate();
}
function length() public view returns (uint256) {
return set.length();
}
function get(uint256 index) public view returns (address) {
return set.get(index);
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@openzeppelin/contracts",
"version": "2.5.0-rc.0",
"version": "2.5.0",
"description": "Secure Smart Contract library for Solidity",
"files": [
"**/*.sol",
@ -28,5 +28,5 @@
"bugs": {
"url": "https://github.com/OpenZeppelin/openzeppelin-contracts/issues"
},
"homepage": "https://github.com/OpenZeppelin/openzeppelin-contracts"
"homepage": "https://openzeppelin.com/contracts/"
}

View File

@ -13,8 +13,7 @@ pragma solidity ^0.5.0;
*
* As of v2.5.0, only `address` sets are supported.
*
* Include with `using EnumerableSet for EnumerableSet.AddressSet;`, and use
* {newAddressSet} to create a new `AddressSet`.
* Include with `using EnumerableSet for EnumerableSet.AddressSet;`.
*
* _Available since v2.5.0._
*
@ -29,17 +28,6 @@ library EnumerableSet {
address[] values;
}
/**
* @dev Creates a new empty address set.
*/
function newAddressSet()
internal
pure
returns (AddressSet memory)
{
return AddressSet({values: new address[](0)});
}
/**
* @dev Add a value to a set. O(1).
* Returns false if the value was already in the set.
@ -105,6 +93,9 @@ library EnumerableSet {
* @dev Returns an array with all values in the set. O(N).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
* WARNING: This function may run out of gas on large sets: use {length} and
* {get} instead in these cases.
*/
function enumerate(AddressSet storage set)
internal
@ -117,4 +108,31 @@ library EnumerableSet {
}
return output;
}
/**
* @dev Returns the number of elements on the set. O(1).
*/
function length(AddressSet storage set)
internal
view
returns (uint256)
{
return set.values.length;
}
/** @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function get(AddressSet storage set, uint256 index)
internal
view
returns (address)
{
return set.values[index];
}
}

View File

@ -1,6 +1,6 @@
{
"package_name": "zeppelin",
"version": "2.5.0-rc.0",
"version": "2.5.0",
"description": "Secure Smart Contract library for Solidity",
"authors": [
"OpenZeppelin Community <maintainers@openzeppelin.org>"

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "openzeppelin-solidity",
"version": "2.5.0-rc.0",
"version": "2.5.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "openzeppelin-solidity",
"version": "2.5.0-rc.0",
"version": "2.5.0",
"description": "Secure Smart Contract library for Solidity",
"files": [
"/contracts/**/*.sol",
@ -42,7 +42,7 @@
"bugs": {
"url": "https://github.com/OpenZeppelin/openzeppelin-contracts/issues"
},
"homepage": "https://github.com/OpenZeppelin/openzeppelin-contracts",
"homepage": "https://openzeppelin.com/contracts/",
"devDependencies": {
"@openzeppelin/cli": "^2.5.3",
"@openzeppelin/gsn-helpers": "^0.2.3",

View File

@ -11,29 +11,39 @@ describe('EnumerableSet', function () {
this.set = await EnumerableSetMock.new();
});
async function expectMembersMatch (set, members) {
await Promise.all(members.map(async account =>
expect(await set.contains(account)).to.equal(true)
));
expect(await set.enumerate()).to.have.same.members(members);
expect(await set.length()).to.bignumber.equal(members.length.toString());
expect(await Promise.all([...Array(members.length).keys()].map(index =>
set.get(index)
))).to.have.same.members(members);
}
it('starts empty', async function () {
expect(await this.set.contains(accountA)).to.equal(false);
expect(await this.set.enumerate()).to.have.same.members([]);
await expectMembersMatch(this.set, []);
});
it('adds a value', async function () {
const receipt = await this.set.add(accountA);
expectEvent(receipt, 'TransactionResult', { result: true });
expect(await this.set.contains(accountA)).to.equal(true);
expect(await this.set.enumerate()).to.have.same.members([ accountA ]);
await expectMembersMatch(this.set, [accountA]);
});
it('adds several values', async function () {
await this.set.add(accountA);
await this.set.add(accountB);
expect(await this.set.contains(accountA)).to.equal(true);
expect(await this.set.contains(accountB)).to.equal(true);
await expectMembersMatch(this.set, [accountA, accountB]);
expect(await this.set.contains(accountC)).to.equal(false);
expect(await this.set.enumerate()).to.have.same.members([ accountA, accountB ]);
});
it('returns false when adding elements already in the set', async function () {
@ -42,7 +52,7 @@ describe('EnumerableSet', function () {
const receipt = (await this.set.add(accountA));
expectEvent(receipt, 'TransactionResult', { result: false });
expect(await this.set.enumerate()).to.have.same.members([ accountA ]);
await expectMembersMatch(this.set, [accountA]);
});
it('removes added values', async function () {
@ -52,7 +62,7 @@ describe('EnumerableSet', function () {
expectEvent(receipt, 'TransactionResult', { result: true });
expect(await this.set.contains(accountA)).to.equal(false);
expect(await this.set.enumerate()).to.have.same.members([]);
await expectMembersMatch(this.set, []);
});
it('returns false when removing elements not in the set', async function () {
@ -99,10 +109,8 @@ describe('EnumerableSet', function () {
// [A, C]
expect(await this.set.contains(accountA)).to.equal(true);
expect(await this.set.contains(accountB)).to.equal(false);
expect(await this.set.contains(accountC)).to.equal(true);
await expectMembersMatch(this.set, [accountA, accountC]);
expect(await this.set.enumerate()).to.have.same.members([ accountA, accountC ]);
expect(await this.set.contains(accountB)).to.equal(false);
});
});