Make ERC777 operator the caller (#2134)
* Make the sender the operator * Make hook methods private * Add changelog entry
This commit is contained in:
@ -22,6 +22,8 @@
|
||||
* `Escrow`, `ConditionalEscrow`, `RefundEscrow`: these now use `Ownable` instead of `Secondary`, their external API changed accordingly. ([#2120](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2120))
|
||||
* `ERC20`: removed `_burnFrom`. ([#2119](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2119))
|
||||
* `Address`: removed `toPayable`, use `payable(address)` instead. ([#2133](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2133))
|
||||
* `ERC777`: `_send`, `_mint` and `_burn` now use the caller as the operator. ([#2134](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2134))
|
||||
* `ERC777`: removed `_callsTokensToSend` and `_callTokensReceived`. ([#2134](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2134))
|
||||
|
||||
## 2.5.0 (2020-02-04)
|
||||
|
||||
|
||||
@ -11,16 +11,15 @@ contract ERC777Mock is Context, ERC777 {
|
||||
string memory symbol,
|
||||
address[] memory defaultOperators
|
||||
) public ERC777(name, symbol, defaultOperators) {
|
||||
_mint(_msgSender(), initialHolder, initialBalance, "", "");
|
||||
_mint(initialHolder, initialBalance, "", "");
|
||||
}
|
||||
|
||||
function mintInternal (
|
||||
address operator,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes memory userData,
|
||||
bytes memory operatorData
|
||||
) public {
|
||||
_mint(operator, to, amount, userData, operatorData);
|
||||
_mint(to, amount, userData, operatorData);
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,7 +135,7 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
* Also emits a {IERC20-Transfer} event for ERC20 compatibility.
|
||||
*/
|
||||
function send(address recipient, uint256 amount, bytes memory data) public override {
|
||||
_send(_msgSender(), _msgSender(), recipient, amount, data, "", true);
|
||||
_send(_msgSender(), recipient, amount, data, "", true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,7 +166,7 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
* Also emits a {IERC20-Transfer} event for ERC20 compatibility.
|
||||
*/
|
||||
function burn(uint256 amount, bytes memory data) public override {
|
||||
_burn(_msgSender(), _msgSender(), amount, data, "");
|
||||
_burn(_msgSender(), amount, data, "");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -233,7 +233,7 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
public override
|
||||
{
|
||||
require(isOperatorFor(_msgSender(), sender), "ERC777: caller is not an operator for holder");
|
||||
_send(_msgSender(), sender, recipient, amount, data, operatorData, true);
|
||||
_send(sender, recipient, amount, data, operatorData, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -243,7 +243,7 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
*/
|
||||
function operatorBurn(address account, uint256 amount, bytes memory data, bytes memory operatorData) public override {
|
||||
require(isOperatorFor(_msgSender(), account), "ERC777: caller is not an operator for holder");
|
||||
_burn(_msgSender(), account, amount, data, operatorData);
|
||||
_burn(account, amount, data, operatorData);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -311,7 +311,6 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
* interface.
|
||||
*/
|
||||
function _mint(
|
||||
address operator,
|
||||
address account,
|
||||
uint256 amount,
|
||||
bytes memory userData,
|
||||
@ -321,6 +320,8 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
{
|
||||
require(account != address(0), "ERC777: mint to the zero address");
|
||||
|
||||
address operator = _msgSender();
|
||||
|
||||
// Update state variables
|
||||
_totalSupply = _totalSupply.add(amount);
|
||||
_balances[account] = _balances[account].add(amount);
|
||||
@ -333,7 +334,6 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
|
||||
/**
|
||||
* @dev Send tokens
|
||||
* @param operator address operator requesting the transfer
|
||||
* @param from address token holder address
|
||||
* @param to address recipient address
|
||||
* @param amount uint256 amount of tokens to transfer
|
||||
@ -342,7 +342,6 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
* @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
|
||||
*/
|
||||
function _send(
|
||||
address operator,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
@ -355,6 +354,8 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
require(from != address(0), "ERC777: send from the zero address");
|
||||
require(to != address(0), "ERC777: send to the zero address");
|
||||
|
||||
address operator = _msgSender();
|
||||
|
||||
_callTokensToSend(operator, from, to, amount, userData, operatorData);
|
||||
|
||||
_move(operator, from, to, amount, userData, operatorData);
|
||||
@ -364,14 +365,12 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
|
||||
/**
|
||||
* @dev Burn tokens
|
||||
* @param operator address operator requesting the operation
|
||||
* @param from address token holder address
|
||||
* @param amount uint256 amount of tokens to burn
|
||||
* @param data bytes extra information provided by the token holder
|
||||
* @param operatorData bytes extra information provided by the operator (if any)
|
||||
*/
|
||||
function _burn(
|
||||
address operator,
|
||||
address from,
|
||||
uint256 amount,
|
||||
bytes memory data,
|
||||
@ -381,6 +380,8 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
{
|
||||
require(from != address(0), "ERC777: burn from the zero address");
|
||||
|
||||
address operator = _msgSender();
|
||||
|
||||
_callTokensToSend(operator, from, address(0), amount, data, operatorData);
|
||||
|
||||
// Update state variables
|
||||
@ -437,7 +438,7 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
bytes memory userData,
|
||||
bytes memory operatorData
|
||||
)
|
||||
internal
|
||||
private
|
||||
{
|
||||
address implementer = ERC1820_REGISTRY.getInterfaceImplementer(from, TOKENS_SENDER_INTERFACE_HASH);
|
||||
if (implementer != address(0)) {
|
||||
@ -465,7 +466,7 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
bytes memory operatorData,
|
||||
bool requireReceptionAck
|
||||
)
|
||||
internal
|
||||
private
|
||||
{
|
||||
address implementer = ERC1820_REGISTRY.getInterfaceImplementer(to, TOKENS_RECIPIENT_INTERFACE_HASH);
|
||||
if (implementer != address(0)) {
|
||||
|
||||
@ -281,7 +281,9 @@ function shouldBehaveLikeERC777InternalMint (recipient, operator, amount, data,
|
||||
shouldInternalMintTokens(operator, recipient, amount, data, operatorData);
|
||||
|
||||
it('reverts when minting tokens for the zero address', async function () {
|
||||
await expectRevert.unspecified(this.token.mintInternal(operator, ZERO_ADDRESS, amount, data, operatorData));
|
||||
await expectRevert.unspecified(
|
||||
this.token.mintInternal(ZERO_ADDRESS, amount, data, operatorData, { from: operator })
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -290,7 +292,7 @@ function shouldInternalMintTokens (operator, to, amount, data, operatorData) {
|
||||
const initialTotalSupply = await this.token.totalSupply();
|
||||
const initialToBalance = await this.token.balanceOf(to);
|
||||
|
||||
const { logs } = await this.token.mintInternal(operator, to, amount, data, operatorData);
|
||||
const { logs } = await this.token.mintInternal(to, amount, data, operatorData, { from: operator });
|
||||
|
||||
expectEvent.inLogs(logs, 'Minted', {
|
||||
operator,
|
||||
@ -332,7 +334,7 @@ function shouldBehaveLikeERC777SendBurnMintInternalWithReceiveHook (operator, am
|
||||
|
||||
it('mint (internal) reverts', async function () {
|
||||
await expectRevert.unspecified(
|
||||
this.token.mintInternal(operator, this.recipient, amount, data, operatorData)
|
||||
this.token.mintInternal(this.recipient, amount, data, operatorData, { from: operator })
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -387,7 +389,7 @@ function shouldBehaveLikeERC777SendBurnMintInternalWithReceiveHook (operator, am
|
||||
|
||||
it('TokensRecipient receives mint (internal) data and is called after state mutation', async function () {
|
||||
const { tx } = await this.token.mintInternal(
|
||||
operator, this.recipient, amount, data, operatorData,
|
||||
this.recipient, amount, data, operatorData, { from: operator }
|
||||
);
|
||||
|
||||
const postRecipientBalance = await this.token.balanceOf(this.recipient);
|
||||
|
||||
@ -300,7 +300,7 @@ describe('ERC777', function () {
|
||||
|
||||
it('mint (internal) reverts', async function () {
|
||||
await expectRevert(
|
||||
this.token.mintInternal(operator, this.recipient, amount, data, operatorData),
|
||||
this.token.mintInternal(this.recipient, amount, data, operatorData, { from: operator }),
|
||||
'ERC777: token recipient contract has no implementer for ERC777TokensRecipient',
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user