Skip to content

Commit

Permalink
ERC777 Add burn functions and fix send functions (OpenZeppelin#1159)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bertrand Masius committed Oct 27, 2018
1 parent 73ac6af commit 9a6ed29
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 45 deletions.
118 changes: 77 additions & 41 deletions contracts/token/ERC777/ERC777.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import "../../math/SafeMath.sol";
import "../../introspection/IERC820.sol";


@title ERC777 token implementation
@author etsvigun <utgarda@gmail.com>, Bertrand Masius <github@catageeks.tk>
@dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-777.md
contract ERC777 is IERC777 {
using SafeMath for uint256;

Expand All @@ -22,7 +25,7 @@ contract ERC777 is IERC777 {

address[] private _defaultOpsArray;

IERC820 constant ERC820Registry = IERC820(0x820A8Cfd018b159837d50656c49d28983f18f33c);
IERC820 constant ERC820Registry = IERC820(0x820A8Cfd018b159837d50656c49d28983f18f33c); //TODO: move to other contract
bytes32 constant sendHash = keccak256(abi.encodePacked('tokensToSend'));
bytes32 constant receivedHash = keccak256(abi.encodePacked('tokensReceived'));

Expand Down Expand Up @@ -135,7 +138,36 @@ contract ERC777 is IERC777 {
_ops[tokenHolder][operator];
}

/**
* @dev Send the amount of tokens from the address msg.sender to the address to
* @param to address recipient address
* @param amount uint256 amount of tokens to transfer
* @param data bytes information attached to the send, and intended for the recipient (to)
*/
function send(address to, uint256 amount, bytes data) external {
_send(msg.sender, msg.sender, to, amount, data, "");
}

/**
* @dev Send the amount of tokens on behalf of the address from to the address to
* @param from address token holder address. Set to 0x0 to use msg.sender as token holder
* @param to address recipient address
* @param amount uint256 amount of tokens to transfer
* @param data bytes information attached to the send, and intended for the recipient (to)
* @param operatorData bytes extra information provided by the operator (if any)
*/
function operatorSend(
address from,
address to,
uint256 amount,
bytes data,
bytes operatorData
)
external
{
address holder = from == address(0) ? msg.sender : from;
_send(msg.sender, holder, to, amount, data, operatorData);
}

/**
* @dev Authorize an operator for the sender
Expand Down Expand Up @@ -173,8 +205,46 @@ contract ERC777 is IERC777 {
emit RevokedOperator(operator, msg.sender);
}

/**
* @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 operatorData bytes extra information provided by the operator (if any)
*/
function _burn(
address operator,
address from,
uint256 amount,
bytes operatorData
)
internal
{
require(from != address(0));
require(isOperatorFor(msg.sender, from));

// Call from.tokensToSend(...) if it is registered
address implementer = ERC820Registry.getInterfaceImplementer(from, sendHash);
if (implementer != address(0)) {
IERC777TokensSender(implementer).tokensToSend(
operator,
from,
address(0),
amount,
"",
operatorData
);
}

// Update state variables
_balances[from] = _balances[from].sub(amount);
require((_balances[from] % _granularity) == 0);

emit Burned(msg.sender, from, amount, operatorData);
}

/**
* @dev Send tokens without checking operator authorization
* @dev Send tokens
* @param operator address operator requesting the transfer
* @param from address token holder address
* @param to address recipient address
Expand All @@ -192,7 +262,9 @@ contract ERC777 is IERC777 {
)
private
{
require((amount % _granularity) == 0);
require(from != address(0));
require(to != address(0));
require(isOperatorFor(msg.sender, from));

// Call from.tokensToSend(...) if it is registered
address implementer = ERC820Registry.getInterfaceImplementer(from, sendHash);
Expand All @@ -210,6 +282,8 @@ contract ERC777 is IERC777 {
// Update state variables
_balances[from] = _balances[from].sub(amount);
_balances[to] = _balances[to].add(amount);
require((_balances[from] % _granularity) == 0);
require((_balances[to] % _granularity) == 0);

// Call to.tokensReceived(...) if it is registered
implementer = ERC820Registry.getInterfaceImplementer(to, receivedHash);
Expand All @@ -226,42 +300,4 @@ contract ERC777 is IERC777 {

emit Sent(msg.sender, from, to, amount, userData, operatorData);
}

/**
* @dev Send the amount of tokens from the address msg.sender to the address to
* @param to address recipient address
* @param amount uint256 amount of tokens to transfer
* @param data bytes information attached to the send, and intended for the recipient (to)
*/
function send(address to, uint256 amount, bytes data) external {
require(to != address(0));
_send(msg.sender, msg.sender, to, amount, data, "");
}

/**
* @dev Send the amount of tokens on behalf of the address from to the address to
* @param from address token holder address. Set to 0x0 to use msg.sender as token holder
* @param to address recipient address
* @param amount uint256 amount of tokens to transfer
* @param data bytes information attached to the send, and intended for the recipient (to)
* @param operatorData bytes extra information provided by the operator (if any)
*/
function operatorSend(
address from,
address to,
uint256 amount,
bytes data,
bytes operatorData
)
external
{
require(to != address(0));
address holder = from == address(0) ? msg.sender : from;
require(isOperatorFor(msg.sender, holder));
_send(msg.sender, holder, to, amount, data, operatorData);
}

function burn(uint256 amount, bytes data) external {} //TODO

function operatorBurn(address from, uint256 amount, bytes data, bytes operatorData) external {} //TODO
}
29 changes: 29 additions & 0 deletions contracts/token/ERC777/ERC777Burnable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
pragma solidity ^0.4.24;

import "./ERC777.sol";


@title ERC777 burnable token implementation
@author Bertrand Masius <github@catageeks.tk>
@dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-777.md
contract ERC777Burnable is ERC777 {

/**
* @dev Burn the amount of tokens from the address msg.sender
* @param amount uint256 amount of tokens to transfer
*/
function burn(uint256 amount) external {
_burn(msg.sender, msg.sender, amount, "");
}

/**
* @dev Burn the amount of tokens on behalf of the address from
* @param from address token holder address. Set to 0x0 to use msg.sender as token holder
* @param amount uint256 amount of tokens to transfer
* @param operatorData bytes extra information provided by the operator (if any)
*/
function operatorBurn(address from, uint256 amount, bytes operatorData) external {
address holder = from == address(0) ? msg.sender : from;
_burn(msg.sender, holder, amount, operatorData);
}
}
4 changes: 0 additions & 4 deletions contracts/token/ERC777/IERC777.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ interface IERC777 {

function operatorSend(address from, address to, uint256 amount, bytes data, bytes operatorData) external;

function burn(uint256 amount, bytes data) external;

function operatorBurn(address from, uint256 amount, bytes data, bytes operatorData) external;

event Sent(
address indexed operator,
address indexed from,
Expand Down

0 comments on commit 9a6ed29

Please sign in to comment.