Add BytesSet (#2395)

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
This commit is contained in:
Nicolás Venturo
2020-11-04 16:57:48 -03:00
committed by GitHub
parent 8533499507
commit fcdf8f4618
4 changed files with 104 additions and 4 deletions

View File

@ -4,6 +4,7 @@
* `Address`: added `functionStaticCall` and `functionDelegateCall`, similar to the existing `functionCall`. ([#2333](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2333)) * `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)) * `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) ## 3.2.0 (2020-09-10)

View File

@ -4,6 +4,37 @@ pragma solidity ^0.6.0;
import "../utils/EnumerableSet.sol"; 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 // AddressSet
contract EnumerableAddressSetMock { contract EnumerableAddressSetMock {
using EnumerableSet for EnumerableSet.AddressSet; using EnumerableSet for EnumerableSet.AddressSet;

View File

@ -23,8 +23,8 @@ pragma solidity ^0.6.0;
* } * }
* ``` * ```
* *
* As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256` * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* (`UintSet`) are supported. * and `uint256` (`UintSet`) are supported.
*/ */
library EnumerableSet { library EnumerableSet {
// To implement this library for multiple types with as little code // To implement this library for multiple types with as little code
@ -132,6 +132,60 @@ library EnumerableSet {
return set._values[index]; 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 // AddressSet
struct AddressSet { struct AddressSet {

View File

@ -1,14 +1,28 @@
const { BN } = require('@openzeppelin/test-helpers'); const { BN } = require('@openzeppelin/test-helpers');
const EnumerableBytes32SetMock = artifacts.require('EnumerableBytes32SetMock');
const EnumerableAddressSetMock = artifacts.require('EnumerableAddressSetMock'); const EnumerableAddressSetMock = artifacts.require('EnumerableAddressSetMock');
const EnumerableUintSetMock = artifacts.require('EnumerableUintSetMock'); const EnumerableUintSetMock = artifacts.require('EnumerableUintSetMock');
const { shouldBehaveLikeSet } = require('./EnumerableSet.behavior'); const { shouldBehaveLikeSet } = require('./EnumerableSet.behavior');
contract('EnumerableSet', function (accounts) { 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 // AddressSet
describe('EnumerableAddressSet', function () { describe('EnumerableAddressSet', function () {
const [ accountA, accountB, accountC ] = accounts; const [accountA, accountB, accountC] = accounts;
beforeEach(async function () { beforeEach(async function () {
this.set = await EnumerableAddressSetMock.new(); this.set = await EnumerableAddressSetMock.new();