Commit b8d96a76 by github-actions

Transpile 7fa99045

parent bd5d681b
......@@ -2,9 +2,20 @@
## Unreleased
* `ERC20Votes`: add a new extension of the `ERC20` token with support for voting snapshots and delegation. This extension is compatible with Compound's `Comp` token interface. ([#2632](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2632))
* `ERC20Votes`: add a new extension of the `ERC20` token with support for voting snapshots and delegation. This extension is compatible with Compound's `Comp` token interface. ([#2632](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2632))
* Enumerables: Improve gas cost of removal in `EnumerableSet` and `EnumerableMap`.
* Enumerables: Improve gas cost of lookup in `EnumerableSet` and `EnumerableMap`.
* `Counter`: add a reset method. ([#2678](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2678))
* Tokens: Wrap definitely safe subtractions in `unchecked` blocks.
* `Math`: Add a `ceilDiv` method for performing ceiling division.
### Breaking Changes
* `ERC20FlashMint` is no longer a Draft ERC. ([#2673](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2673)))
**How to update:** Change your import paths by removing the `draft-` prefix from `@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20FlashMint.sol`.
> See [Releases and Stability: Drafts](https://docs.openzeppelin.com/contracts/4.x/releases-stability#drafts).
## 4.1.0 (2021-04-29)
......
......@@ -27,5 +27,9 @@ contract CountersImplUpgradeable is Initializable {
function decrement() public {
_counter.decrement();
}
function reset() public {
_counter.reset();
}
uint256[49] private __gap;
}
......@@ -3,7 +3,7 @@
pragma solidity ^0.8.0;
import "../token/ERC20/extensions/draft-ERC20FlashMintUpgradeable.sol";
import "../token/ERC20/extensions/ERC20FlashMintUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
contract ERC20FlashMintMockUpgradeable is Initializable, ERC20FlashMintUpgradeable {
......
......@@ -3,7 +3,7 @@
pragma solidity ^0.8.0;
import "../token/ERC20/extensions/draft-ERC20VotesUpgradeable.sol";
import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable {
......
......@@ -23,5 +23,9 @@ contract MathMockUpgradeable is Initializable {
function average(uint256 a, uint256 b) public pure returns (uint256) {
return MathUpgradeable.average(a, b);
}
function ceilDiv(uint256 a, uint256 b) public pure returns (uint256) {
return MathUpgradeable.ceilDiv(a, b);
}
uint256[50] private __gap;
}
......@@ -244,25 +244,6 @@ contract ERC721PausableMockUpgradeableWithInit is ERC721PausableMockUpgradeable
__ERC721PausableMock_init(name, symbol);
}
}
import "./ERC3156FlashBorrowerMockUpgradeable.sol";
contract ERC3156FlashBorrowerMockUpgradeableWithInit is ERC3156FlashBorrowerMockUpgradeable {
constructor(bool enableReturn, bool enableApprove) public payable {
__ERC3156FlashBorrowerMock_init(enableReturn, enableApprove);
}
}
import "./ERC3156MockUpgradeable.sol";
contract ERC20FlashMintMockUpgradeableWithInit is ERC20FlashMintMockUpgradeable {
constructor(
string memory name,
string memory symbol,
address initialAccount,
uint256 initialBalance
) public payable {
__ERC20FlashMintMock_init(name, symbol, initialAccount, initialBalance);
}
}
import "./EIP712ExternalUpgradeable.sol";
contract EIP712ExternalUpgradeableWithInit is EIP712ExternalUpgradeable {
......@@ -315,6 +296,25 @@ contract MulticallTestUpgradeableWithInit is MulticallTestUpgradeable {
__MulticallTest_init();
}
}
import "./ERC3156FlashBorrowerMockUpgradeable.sol";
contract ERC3156FlashBorrowerMockUpgradeableWithInit is ERC3156FlashBorrowerMockUpgradeable {
constructor(bool enableReturn, bool enableApprove) public payable {
__ERC3156FlashBorrowerMock_init(enableReturn, enableApprove);
}
}
import "./ERC20FlashMintMockUpgradeable.sol";
contract ERC20FlashMintMockUpgradeableWithInit is ERC20FlashMintMockUpgradeable {
constructor(
string memory name,
string memory symbol,
address initialAccount,
uint256 initialBalance
) public payable {
__ERC20FlashMintMock_init(name, symbol, initialAccount, initialBalance);
}
}
import "./ERC20DecimalsMockUpgradeable.sol";
contract ERC20DecimalsMockUpgradeableWithInit is ERC20DecimalsMockUpgradeable {
......
......@@ -194,7 +194,9 @@ contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradea
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
_balances[id][from] = fromBalance - amount;
unchecked {
_balances[id][from] = fromBalance - amount;
}
_balances[id][to] += amount;
emit TransferSingle(operator, from, to, id, amount);
......@@ -235,7 +237,9 @@ contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradea
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
_balances[id][from] = fromBalance - amount;
unchecked {
_balances[id][from] = fromBalance - amount;
}
_balances[id][to] += amount;
}
......@@ -334,7 +338,9 @@ contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradea
uint256 accountBalance = _balances[id][account];
require(accountBalance >= amount, "ERC1155: burn amount exceeds balance");
_balances[id][account] = accountBalance - amount;
unchecked {
_balances[id][account] = accountBalance - amount;
}
emit TransferSingle(operator, account, address(0), id, amount);
}
......@@ -360,7 +366,9 @@ contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradea
uint256 accountBalance = _balances[id][account];
require(accountBalance >= amount, "ERC1155: burn amount exceeds balance");
_balances[id][account] = accountBalance - amount;
unchecked {
_balances[id][account] = accountBalance - amount;
}
}
emit TransferBatch(operator, account, address(0), ids, amounts);
......
......@@ -156,7 +156,9 @@ contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeabl
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
_approve(sender, _msgSender(), currentAllowance - amount);
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
return true;
}
......@@ -195,7 +197,9 @@ contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeabl
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
......@@ -222,7 +226,9 @@ contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeabl
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
_balances[sender] = senderBalance - amount;
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
......@@ -265,8 +271,10 @@ contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeabl
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
_balances[account] = accountBalance - amount;
_totalSupply -= amount;
unchecked {
_balances[account] = accountBalance - amount;
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
}
......
......@@ -42,7 +42,9 @@ abstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable,
function burnFrom(address account, uint256 amount) public virtual {
uint256 currentAllowance = allowance(account, _msgSender());
require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");
_approve(account, _msgSender(), currentAllowance - amount);
unchecked {
_approve(account, _msgSender(), currentAllowance - amount);
}
_burn(account, amount);
}
uint256[50] private __gap;
......
......@@ -3,7 +3,7 @@
pragma solidity ^0.8.0;
import "./draft-ERC20PermitUpgradeable.sol";
import "./draft-IERC20VotesUpgradeable.sol";
import "./IERC20VotesUpgradeable.sol";
import "../../../utils/math/MathUpgradeable.sol";
import "../../../utils/math/SafeCastUpgradeable.sol";
import "../../../utils/cryptography/ECDSAUpgradeable.sol";
......
......@@ -105,8 +105,9 @@ contract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeab
}
/**
* @dev Base URI for computing {tokenURI}. Empty by default, can be overriden
* in child contracts.
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overriden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
......
......@@ -52,7 +52,7 @@ contract ERC777Upgradeable is Initializable, ContextUpgradeable, IERC777Upgradea
mapping(address => mapping(address => bool)) private _revokedDefaultOperators;
// ERC20-allowances
mapping (address => mapping (address => uint256)) private _allowances;
mapping(address => mapping(address => uint256)) private _allowances;
/**
* @dev `defaultOperators` may be an empty array.
......@@ -429,8 +429,10 @@ contract ERC777Upgradeable is Initializable, ContextUpgradeable, IERC777Upgradea
// Update state variables
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC777: burn amount exceeds balance");
_balances[from] = fromBalance - amount;
_totalSupply -= amount;
unchecked {
_balances[from] = fromBalance - amount;
_totalSupply -= amount;
}
emit Burned(operator, from, amount, data, operatorData);
emit Transfer(from, address(0), amount);
......@@ -450,7 +452,9 @@ contract ERC777Upgradeable is Initializable, ContextUpgradeable, IERC777Upgradea
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC777: transfer amount exceeds balance");
_balances[from] = fromBalance - amount;
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Sent(operator, from, to, amount, userData, operatorData);
......
......@@ -7,7 +7,7 @@ pragma solidity ^0.8.0;
*
* {IERC777} Token holders can be notified of operations performed on their
* tokens by having a contract implement this interface (contract holders can be
* their own implementer) and registering it on the
* their own implementer) and registering it on the
* https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].
*
* See {IERC1820Registry} and {ERC1820Implementer}.
......
......@@ -5,7 +5,7 @@ pragma solidity ^0.8.0;
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
* @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
*
* Include with `using Counters for Counters.Counter;`
......@@ -35,4 +35,8 @@ library CountersUpgradeable {
counter._value = value - 1;
}
}
function reset(Counter storage counter) internal {
counter._value = 0;
}
}
......@@ -10,7 +10,7 @@ The {Address}, {Arrays} and {Strings} libraries provide more operations related
For new data types:
* {Counters}: a simple way to get a counter that can only be incremented or decremented. Very useful for ID generation, counting contract activity, among others.
* {Counters}: a simple way to get a counter that can only be incremented, decremented or reset. Very useful for ID generation, counting contract activity, among others.
* {EnumerableMap}: like Solidity's https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] type, but with key-value _enumeration_: this will let you know how many entries a mapping has, and iterate over them (which is not possible with `mapping`).
* {EnumerableSet}: like {EnumerableMap}, but for https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets]. Can be used to store privileged accounts, issued IDs, etc.
......
......@@ -28,4 +28,15 @@ library MathUpgradeable {
// (a + b) / 2 can overflow, so we distribute.
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a / b + (a % b == 0 ? 0 : 1);
}
}
diff --git a/contracts/token/ERC20/extensions/draft-ERC20VotesUpgradeable.sol b/contracts/token/ERC20/extensions/draft-ERC20VotesUpgradeable.sol
diff --git a/contracts/token/ERC20/extensions/ERC20VotesUpgradeable.sol b/contracts/token/ERC20/extensions/ERC20VotesUpgradeable.sol
index a7a9af54..0b7f838d 100644
--- a/contracts/token/ERC20/extensions/draft-ERC20VotesUpgradeable.sol
+++ b/contracts/token/ERC20/extensions/draft-ERC20VotesUpgradeable.sol
--- a/contracts/token/ERC20/extensions/ERC20VotesUpgradeable.sol
+++ b/contracts/token/ERC20/extensions/ERC20VotesUpgradeable.sol
@@ -24,12 +24,6 @@ import "../../../proxy/utils/Initializable.sol";
* _Available since v4.2._
*/
......
......@@ -61,4 +61,24 @@ contract('Counters', function (accounts) {
});
});
});
describe('reset', function () {
context('null counter', function () {
it('does not throw', async function () {
await this.counter.reset();
expect(await this.counter.current()).to.be.bignumber.equal('0');
});
});
context('non null counter', function () {
beforeEach(async function () {
await this.counter.increment();
expect(await this.counter.current()).to.be.bignumber.equal('1');
});
it('reset to 0', async function () {
await this.counter.reset();
expect(await this.counter.current()).to.be.bignumber.equal('0');
});
});
});
});
const { BN } = require('@openzeppelin/test-helpers');
const { BN, constants } = require('@openzeppelin/test-helpers');
const { expect } = require('chai');
const { MAX_UINT256 } = constants;
const MathMock = artifacts.require('MathMock');
......@@ -55,4 +55,29 @@ contract('Math', function (accounts) {
expect(await this.math.average(a, b)).to.be.bignumber.equal(bnAverage(a, b));
});
});
describe('ceilDiv', function () {
it('does not round up on exact division', async function () {
const a = new BN('10');
const b = new BN('5');
expect(await this.math.ceilDiv(a, b)).to.be.bignumber.equal('2');
});
it('rounds up on division with remainders', async function () {
const a = new BN('42');
const b = new BN('13');
expect(await this.math.ceilDiv(a, b)).to.be.bignumber.equal('4');
});
it('does not overflow', async function () {
const b = new BN('2');
const result = new BN('1').shln(255);
expect(await this.math.ceilDiv(MAX_UINT256, b)).to.be.bignumber.equal(result);
});
it('correctly computes max uint256 divided by 1', async function () {
const b = new BN('1');
expect(await this.math.ceilDiv(MAX_UINT256, b)).to.be.bignumber.equal(MAX_UINT256);
});
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment