소스 검색

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

* Fix transferFrom not updating allowance before calling receiver.

* Fix from being passed as operator.

(cherry picked from commit 2ccc12b328e6d5d1d3faa5b99bec8d1de8b92fea)
Nicolás Venturo 6 년 전
부모
커밋
9ab93f8ae4
1개의 변경된 파일44개의 추가작업 그리고 39개의 파일을 삭제
  1. 44 39
      contracts/token/ERC777/ERC777.sol

+ 44 - 39
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)
      */
     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
     {
         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.
      */
     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;
     }
 
@@ -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, "", "");
+
+        _move(operator, from, to, value, "", "");
+        _approve(from, operator, _allowances[from][operator].sub(value));
+
+        _callTokensReceived(operator, from, to, value, "", "", false);
+
         return true;
     }
 
@@ -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
@@ -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");
+        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);
     }
 
     /**
@@ -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);
+        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.