Add BytesSet (#2395)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
This commit is contained in:
@ -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)
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user