Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
May 16, 2019
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 44 additions & 39 deletions contracts/token/ERC777/ERC777.sol
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ contract ERC777 is IERC777, IERC20 {
* @param data bytes information attached to the send, and intended for the recipient (to)
*/
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);
}

/**
Expand All @@ -95,7 +95,7 @@ contract ERC777 is IERC777, IERC20 {
external
{
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);
}

/**
Expand All @@ -106,7 +106,16 @@ contract ERC777 is IERC777, IERC20 {
* @param value The amount to be transferred.
*/
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;
}

Expand All @@ -121,8 +130,18 @@ contract ERC777 is IERC777, IERC20 {
* @param value uint256 the amount of tokens to be transferred
*/
function transferFrom(address from, address to, uint256 value) external returns (bool) {
_transfer(msg.sender, from, to, value);
_approve(from, msg.sender, _allowances[from][msg.sender].sub(value));
require(to != address(0), "ERC777: transfer to the zero address");
require(from != address(0), "ERC777: transfer from the zero address");

address operator = msg.sender;

_callTokensToSend(operator, from, to, value, "", "");
nventuro marked this conversation as resolved.
Show resolved Hide resolved

_move(operator, from, to, value, "", "");
_approve(from, operator, _allowances[from][operator].sub(value));

_callTokensReceived(from, from, to, value, "", "", false);
nventuro marked this conversation as resolved.
Show resolved Hide resolved

return true;
}

Expand Down Expand Up @@ -306,32 +325,6 @@ contract ERC777 is IERC777, IERC20 {
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
* @param operator address operator requesting the transfer
Expand All @@ -353,19 +346,14 @@ contract ERC777 is IERC777, IERC20 {
)
private
{
require(from != address(0), "ERC777: transfer from the zero address");
require(to != address(0), "ERC777: transfer to the zero address");
require(from != address(0), "ERC777: send from the zero address");
nventuro marked this conversation as resolved.
Show resolved Hide resolved
require(to != address(0), "ERC777: send to the zero address");

_callTokensToSend(operator, from, to, amount, userData, operatorData);

// Update state variables
_balances[from] = _balances[from].sub(amount);
_balances[to] = _balances[to].add(amount);
_move(operator, from, to, amount, userData, operatorData);

_callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck);

emit Sent(operator, from, to, amount, userData, operatorData);
emit Transfer(from, to, amount);
}

/**
Expand Down Expand Up @@ -397,6 +385,23 @@ contract ERC777 is IERC777, IERC20 {
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);
nventuro marked this conversation as resolved.
Show resolved Hide resolved
emit Transfer(from, to, amount);
}

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
// currently unnecessary.
Expand Down