Update transferFrom to modify allowance in-between hook calls. (#1751)

* Fix transferFrom not updating allowance before calling receiver.

* Fix from being passed as operator.
pull/1764/head
Nicolás Venturo 6 years ago committed by GitHub
parent ad18098d65
commit 2ccc12b328
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 83
      contracts/token/ERC777/ERC777.sol

@ -74,7 +74,7 @@ contract ERC777 is IERC777, IERC20 {
* @param data bytes information attached to the send, and intended for the recipient (to) * @param data bytes information attached to the send, and intended for the recipient (to)
*/ */
function send(address to, uint256 amount, bytes calldata data) external { function send(address to, uint256 amount, bytes calldata data) external {
_sendRequiringReceptionAck(msg.sender, msg.sender, to, amount, data, ""); _send(msg.sender, msg.sender, to, amount, data, "", true);
} }
/** /**
@ -95,7 +95,7 @@ contract ERC777 is IERC777, IERC20 {
external external
{ {
require(isOperatorFor(msg.sender, from), "ERC777: caller is not an operator for holder"); require(isOperatorFor(msg.sender, from), "ERC777: caller is not an operator for holder");
_sendRequiringReceptionAck(msg.sender, from, to, amount, data, operatorData); _send(msg.sender, from, to, amount, data, operatorData, true);
} }
/** /**
@ -106,7 +106,16 @@ contract ERC777 is IERC777, IERC20 {
* @param value The amount to be transferred. * @param value The amount to be transferred.
*/ */
function transfer(address to, uint256 value) external returns (bool) { function transfer(address to, uint256 value) external returns (bool) {
_transfer(msg.sender, msg.sender, to, value); require(to != address(0), "ERC777: transfer to the zero address");
address from = msg.sender;
_callTokensToSend(from, from, to, value, "", "");
_move(from, from, to, value, "", "");
_callTokensReceived(from, from, to, value, "", "", false);
return true; return true;
} }
@ -121,8 +130,18 @@ contract ERC777 is IERC777, IERC20 {
* @param value uint256 the amount of tokens to be transferred * @param value uint256 the amount of tokens to be transferred
*/ */
function transferFrom(address from, address to, uint256 value) external returns (bool) { function transferFrom(address from, address to, uint256 value) external returns (bool) {
_transfer(msg.sender, from, to, value); require(to != address(0), "ERC777: transfer to the zero address");
_approve(from, msg.sender, _allowances[from][msg.sender].sub(value)); require(from != address(0), "ERC777: transfer from the zero address");
address operator = msg.sender;
_callTokensToSend(operator, from, to, value, "", "");
_move(operator, from, to, value, "", "");
_approve(from, operator, _allowances[from][operator].sub(value));
_callTokensReceived(operator, from, to, value, "", "", false);
return true; return true;
} }
@ -306,32 +325,6 @@ contract ERC777 is IERC777, IERC20 {
emit Transfer(address(0), to, amount); emit Transfer(address(0), to, amount);
} }
function _transfer(address operator, address from, address to, uint256 amount) private {
_sendAllowingNoReceptionAck(operator, from, to, amount, "", "");
}
function _sendRequiringReceptionAck(
address operator,
address from,
address to,
uint256 amount,
bytes memory userData,
bytes memory operatorData
) private {
_send(operator, from, to, amount, userData, operatorData, true);
}
function _sendAllowingNoReceptionAck(
address operator,
address from,
address to,
uint256 amount,
bytes memory userData,
bytes memory operatorData
) private {
_send(operator, from, to, amount, userData, operatorData, false);
}
/** /**
* @dev Send tokens * @dev Send tokens
* @param operator address operator requesting the transfer * @param operator address operator requesting the transfer
@ -353,19 +346,14 @@ contract ERC777 is IERC777, IERC20 {
) )
private private
{ {
require(from != address(0), "ERC777: transfer from the zero address"); require(from != address(0), "ERC777: send from the zero address");
require(to != address(0), "ERC777: transfer to the zero address"); require(to != address(0), "ERC777: send to the zero address");
_callTokensToSend(operator, from, to, amount, userData, operatorData); _callTokensToSend(operator, from, to, amount, userData, operatorData);
// Update state variables _move(operator, from, to, amount, userData, operatorData);
_balances[from] = _balances[from].sub(amount);
_balances[to] = _balances[to].add(amount);
_callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck); _callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck);
emit Sent(operator, from, to, amount, userData, operatorData);
emit Transfer(from, to, amount);
} }
/** /**
@ -397,6 +385,23 @@ contract ERC777 is IERC777, IERC20 {
emit Transfer(from, address(0), amount); emit Transfer(from, address(0), amount);
} }
function _move(
address operator,
address from,
address to,
uint256 amount,
bytes memory userData,
bytes memory operatorData
)
private
{
_balances[from] = _balances[from].sub(amount);
_balances[to] = _balances[to].add(amount);
emit Sent(operator, from, to, amount, userData, operatorData);
emit Transfer(from, to, amount);
}
function _approve(address owner, address spender, uint256 value) private { function _approve(address owner, address spender, uint256 value) private {
// TODO: restore this require statement if this function becomes internal, or is called at a new callsite. It is // TODO: restore this require statement if this function becomes internal, or is called at a new callsite. It is
// currently unnecessary. // currently unnecessary.

Loading…
Cancel
Save