Skip to content

Commit

Permalink
Add BytesSet (#2395)
Browse files Browse the repository at this point in the history
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
  • Loading branch information
nventuro and frangio authored Nov 4, 2020
1 parent 8533499 commit fcdf8f4
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* `Address`: added `functionStaticCall` and `functionDelegateCall`, similar to the existing `functionCall`. ([#2333](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2333))
* `TimelockController`: added a contract to augment access control schemes with a delay. ([#2364](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2364))
* `EnumerableSet`: added `BytesSet`, for sets of `bytes32`. ([#2395](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2395))

## 3.2.0 (2020-09-10)

Expand Down
33 changes: 32 additions & 1 deletion contracts/mocks/EnumerableSetMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,37 @@ pragma solidity ^0.6.0;

import "../utils/EnumerableSet.sol";

// Bytes32Set
contract EnumerableBytes32SetMock {
using EnumerableSet for EnumerableSet.Bytes32Set;

event OperationResult(bool result);

EnumerableSet.Bytes32Set private _set;

function contains(bytes32 value) public view returns (bool) {
return _set.contains(value);
}

function add(bytes32 value) public {
bool result = _set.add(value);
emit OperationResult(result);
}

function remove(bytes32 value) public {
bool result = _set.remove(value);
emit OperationResult(result);
}

function length() public view returns (uint256) {
return _set.length();
}

function at(uint256 index) public view returns (bytes32) {
return _set.at(index);
}
}

// AddressSet
contract EnumerableAddressSetMock {
using EnumerableSet for EnumerableSet.AddressSet;
Expand Down Expand Up @@ -64,4 +95,4 @@ contract EnumerableUintSetMock {
function at(uint256 index) public view returns (uint256) {
return _set.at(index);
}
}
}
58 changes: 56 additions & 2 deletions contracts/utils/EnumerableSet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ pragma solidity ^0.6.0;
* }
* ```
*
* As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256`
* (`UintSet`) are supported.
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
Expand Down Expand Up @@ -132,6 +132,60 @@ library EnumerableSet {
return set._values[index];
}

// Bytes32Set

struct Bytes32Set {
Set _inner;
}

/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}

/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}

/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}

/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}

/**
* @dev Returns the value 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 at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}

// AddressSet

struct AddressSet {
Expand Down
16 changes: 15 additions & 1 deletion test/utils/EnumerableSet.test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
const { BN } = require('@openzeppelin/test-helpers');

const EnumerableBytes32SetMock = artifacts.require('EnumerableBytes32SetMock');
const EnumerableAddressSetMock = artifacts.require('EnumerableAddressSetMock');
const EnumerableUintSetMock = artifacts.require('EnumerableUintSetMock');

const { shouldBehaveLikeSet } = require('./EnumerableSet.behavior');

contract('EnumerableSet', function (accounts) {
// Bytes32Set
describe('EnumerableBytes32Set', function () {
const bytesA = '0xdeadbeef'.padEnd(66, '0');
const bytesB = '0x0123456789'.padEnd(66, '0');
const bytesC = '0x42424242'.padEnd(66, '0');

beforeEach(async function () {
this.set = await EnumerableBytes32SetMock.new();
});

shouldBehaveLikeSet(bytesA, bytesB, bytesC);
});

// AddressSet
describe('EnumerableAddressSet', function () {
const [ accountA, accountB, accountC ] = accounts;
const [accountA, accountB, accountC] = accounts;

beforeEach(async function () {
this.set = await EnumerableAddressSetMock.new();
Expand Down

0 comments on commit fcdf8f4

Please sign in to comment.