Skip to content

Commit

Permalink
Merge branch 'master' into codegen/safecast
Browse files Browse the repository at this point in the history
  • Loading branch information
frangio committed May 20, 2022
2 parents 550d20a + c4f76cf commit 5b1d491
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,7 @@
* `CrossChainEnabledPolygonChild`: replace the `require` statement with the custom error `NotCrossChainCall`. ([#3380](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3380))
* `ERC20FlashMint`: Add customizable flash fee receiver. ([#3327](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3327))
* `Strings`: add a new overloaded function `toHexString` that converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. ([#3403](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3403))
* `EnumerableMap`: add new `UintToUintMap` map type. ([#3338](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3338))
* `SafeCast`: add support for many more types, using procedural code generation. ([#3245](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3245))

## 4.6.0 (2022-04-26)
Expand Down
12 changes: 12 additions & 0 deletions contracts/access/AccessControl.sol
Expand Up @@ -138,6 +138,8 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
Expand All @@ -151,6 +153,8 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
Expand All @@ -169,6 +173,8 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
Expand All @@ -183,6 +189,8 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
Expand Down Expand Up @@ -213,6 +221,8 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
Expand All @@ -225,6 +235,8 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
Expand Down
2 changes: 1 addition & 1 deletion contracts/governance/TimelockController.sol
Expand Up @@ -131,7 +131,7 @@ contract TimelockController is AccessControl, IERC721Receiver, IERC1155Receiver
* @dev Returns whether an id correspond to a registered operation. This
* includes both Pending, Ready and Done operations.
*/
function isOperation(bytes32 id) public view virtual returns (bool pending) {
function isOperation(bytes32 id) public view virtual returns (bool registered) {
return getTimestamp(id) > 0;
}

Expand Down
43 changes: 43 additions & 0 deletions contracts/mocks/EnumerableMapMock.sol
Expand Up @@ -131,3 +131,46 @@ contract Bytes32ToBytes32MapMock {
return _map.get(key, errorMessage);
}
}

// UintToUintMap
contract UintToUintMapMock {
using EnumerableMap for EnumerableMap.UintToUintMap;

event OperationResult(bool result);

EnumerableMap.UintToUintMap private _map;

function contains(uint256 key) public view returns (bool) {
return _map.contains(key);
}

function set(uint256 key, uint256 value) public {
bool result = _map.set(key, value);
emit OperationResult(result);
}

function remove(uint256 key) public {
bool result = _map.remove(key);
emit OperationResult(result);
}

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

function at(uint256 index) public view returns (uint256 key, uint256 value) {
return _map.at(index);
}

function tryGet(uint256 key) public view returns (bool, uint256) {
return _map.tryGet(key);
}

function get(uint256 key) public view returns (uint256) {
return _map.get(key);
}

function getWithMessage(uint256 key, string calldata errorMessage) public view returns (uint256) {
return _map.get(key, errorMessage);
}
}
95 changes: 93 additions & 2 deletions contracts/utils/structs/EnumerableMap.sol
Expand Up @@ -31,6 +31,7 @@ import "./EnumerableSet.sol";
* - `uint256 -> address` (`UintToAddressMap`) since v3.0.0
* - `address -> uint256` (`AddressToUintMap`) since v4.6.0
* - `bytes32 -> bytes32` (`Bytes32ToBytes32`) since v4.6.0
* - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0
*
* [WARNING]
* ====
Expand Down Expand Up @@ -155,6 +156,98 @@ library EnumerableMap {
return value;
}

// UintToUintMap

struct UintToUintMap {
Bytes32ToBytes32Map _inner;
}

/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(
UintToUintMap storage map,
uint256 key,
uint256 value
) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(value));
}

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

/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}

/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}

/**
* @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 at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), uint256(value));
}

/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, uint256(value));
}

/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key)));
}

/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
UintToUintMap storage map,
uint256 key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key), errorMessage));
}

// UintToAddressMap

struct UintToAddressMap {
Expand Down Expand Up @@ -310,8 +403,6 @@ library EnumerableMap {
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*
* _Available since v3.4._
*/
function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));
Expand Down
14 changes: 14 additions & 0 deletions test/utils/structs/EnumerableMap.test.js
Expand Up @@ -3,6 +3,7 @@ const { BN, constants } = require('@openzeppelin/test-helpers');
const AddressToUintMapMock = artifacts.require('AddressToUintMapMock');
const UintToAddressMapMock = artifacts.require('UintToAddressMapMock');
const Bytes32ToBytes32MapMock = artifacts.require('Bytes32ToBytes32MapMock');
const UintToUintMapMock = artifacts.require('UintToUintMapMock');

const { shouldBehaveLikeMap } = require('./EnumerableMap.behavior');

Expand Down Expand Up @@ -55,4 +56,17 @@ contract('EnumerableMap', function (accounts) {
constants.ZERO_BYTES32,
);
});

// UintToUintMap
describe('UintToUintMap', function () {
beforeEach(async function () {
this.map = await UintToUintMapMock.new();
});

shouldBehaveLikeMap(
[ keyA, keyB, keyC ],
[ keyA, keyB, keyC ].map(k => k.add(new BN('1332'))),
new BN('0'),
);
});
});

0 comments on commit 5b1d491

Please sign in to comment.