Skip to content

Commit

Permalink
Make ERC777 operator the caller (#2134)
Browse files Browse the repository at this point in the history
* Make the sender the operator

* Make hook methods private

* Add changelog entry
  • Loading branch information
nventuro authored Mar 16, 2020
1 parent 9005804 commit e7b2248
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 19 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
5 changes: 2 additions & 3 deletions contracts/mocks/ERC777Mock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
23 changes: 12 additions & 11 deletions contracts/token/ERC777/ERC777.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -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, "");
}

/**
Expand Down Expand Up @@ -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);
}

/**
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -311,7 +311,6 @@ contract ERC777 is Context, IERC777, IERC20 {
* interface.
*/
function _mint(
address operator,
address account,
uint256 amount,
bytes memory userData,
Expand All @@ -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);
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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)) {
Expand Down
10 changes: 6 additions & 4 deletions test/token/ERC777/ERC777.behavior.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 })
);
});
}

Expand All @@ -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,
Expand Down Expand Up @@ -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 })
);
});
});
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion test/token/ERC777/ERC777.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
);
});
Expand Down

0 comments on commit e7b2248

Please sign in to comment.