Skip to content

Commit

Permalink
Merge 0bdbfbc into cc19ccf
Browse files Browse the repository at this point in the history
  • Loading branch information
nventuro committed May 14, 2019
2 parents cc19ccf + 0bdbfbc commit 29a3196
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 105 deletions.
123 changes: 80 additions & 43 deletions contracts/token/ERC777/ERC777.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,42 +71,42 @@ contract ERC777 is IERC777, IERC20 {
* @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)
* @param userData 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, "");
function send(address to, uint256 amount, bytes calldata userData) external {
_sendRequiringReceptionAck(msg.sender, msg.sender, to, amount, userData, "");
}

/**
* @dev Send the amount of tokens on behalf of the address from to the address to
* @param from address token holder address.
* @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 userData 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 calldata data,
bytes calldata userData,
bytes calldata operatorData
)
external
{
require(isOperatorFor(msg.sender, from), "ERC777: caller is not an operator for holder");
_sendRequiringReceptionAck(msg.sender, from, to, amount, data, operatorData);
_sendRequiringReceptionAck(msg.sender, from, to, amount, userData, operatorData);
}

/**
* @dev Transfer token to a specified address.
* Required for ERC20 compatiblity. Note that transferring tokens this way may result in locked tokens (i.e. tokens
* can be sent to a contract that does not implement the ERC777TokensRecipient interface).
* @param to The address to transfer to.
* @param value The amount to be transferred.
* @param amount The amount to be transferred.
*/
function transfer(address to, uint256 value) external returns (bool) {
_transfer(msg.sender, msg.sender, to, value);
function transfer(address to, uint256 amount) external returns (bool) {
_transfer(msg.sender, to, amount);
return true;
}

Expand All @@ -118,33 +118,32 @@ contract ERC777 is IERC777, IERC20 {
* can be sent to a contract that does not implement the ERC777TokensRecipient interface).
* @param from address The address which you want to send tokens from
* @param to address The address which you want to transfer to
* @param value uint256 the amount of tokens to be transferred
* @param amount 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));
function transferFrom(address from, address to, uint256 amount) external returns (bool) {
_transferFrom(msg.sender, from, to, amount);
return true;
}

/**
* @dev Burn the amount of tokens from the address msg.sender
* @param amount uint256 amount of tokens to transfer
* @param data bytes extra information provided by the token holder
* @param userData bytes extra information provided by the token holder
*/
function burn(uint256 amount, bytes calldata data) external {
_burn(msg.sender, msg.sender, amount, data, "");
function burn(uint256 amount, bytes calldata userData) external {
_burn(msg.sender, msg.sender, amount, userData, "");
}

/**
* @dev Burn the amount of tokens on behalf of the address from
* @param from address token holder address.
* @param amount uint256 amount of tokens to transfer
* @param data bytes extra information provided by the token holder
* @param userData bytes extra information provided by the token holder
* @param operatorData bytes extra information provided by the operator (if any)
*/
function operatorBurn(address from, uint256 amount, bytes calldata data, bytes calldata operatorData) external {
function operatorBurn(address from, uint256 amount, bytes calldata userData, bytes calldata operatorData) external {
require(isOperatorFor(msg.sender, from), "ERC777: caller is not an operator for holder");
_burn(msg.sender, from, amount, data, operatorData);
_burn(msg.sender, from, amount, userData, operatorData);
}

/**
Expand Down Expand Up @@ -183,14 +182,14 @@ contract ERC777 is IERC777, IERC20 {
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
* Beware that changing an allowance with this method brings the risk that someone may use both the old
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
* race condition is to first reduce the spender's allowance to 0 and set the desired amount afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
* Required for ERC20 compatilibity.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param amount The amount of tokens to be spent.
*/
function approve(address spender, uint256 value) external returns (bool) {
_approve(msg.sender, spender, value);
function approve(address spender, uint256 amount) external returns (bool) {
_approve(msg.sender, spender, amount);
return true;
}

Expand Down Expand Up @@ -306,10 +305,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,
Expand All @@ -332,6 +327,22 @@ contract ERC777 is IERC777, IERC20 {
_send(operator, from, to, amount, userData, operatorData, false);
}

function _transfer(address from, address to, uint256 amount) private {
_sendAllowingNoReceptionAck(from, from, to, amount, "", "");
}

function _transferFrom(address spender, address from, address to, uint256 amount) private {
require(from != address(0), "ERC777: transfer from the zero address");
require(to != address(0), "ERC777: transfer to the zero address");

_callTokensToSend(spender, from, to, amount, "", "");

_move(spender, from, to, amount, "", "");
_approve(from, spender, _allowances[from][spender].sub(amount));

_callTokensReceived(spender, from, to, amount, "", "", false);
}

/**
* @dev Send tokens
* @param operator address operator requesting the transfer
Expand All @@ -358,53 +369,79 @@ contract ERC777 is IERC777, IERC20 {

_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);
}

/**
* @dev Burn tokens
* @param operator address operator requesting the operation
* @dev Burn (destroy) tokens from a holder, decreasing total supply.
* @param operator address operator performing 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)
* @param userData bytes extra information provided by the token holder
* @param operatorData bytes extra information provided by the operator
*/
function _burn(
address operator,
address from,
uint256 amount,
bytes memory data,
bytes memory userData,
bytes memory operatorData
)
private
{
require(from != address(0), "ERC777: burn from the zero address");

_callTokensToSend(operator, from, address(0), amount, data, operatorData);
_callTokensToSend(operator, from, address(0), amount, userData, operatorData);

// Update state variables
_totalSupply = _totalSupply.sub(amount);
_balances[from] = _balances[from].sub(amount);

emit Burned(operator, from, amount, data, operatorData);
emit Burned(operator, from, amount, userData, operatorData);
emit Transfer(from, address(0), amount);
}

function _approve(address owner, address spender, uint256 value) private {
/**
* @dev Move tokens from a holder to another, keeping total supply constant.
* @param operator address operator performing the operation
* @param from address token holder address
* @param amount uint256 amount of tokens to move
* @param userData bytes extra information provided by the token holder
* @param operatorData bytes extra information provided by the operator
*/
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);
}

/**
* @dev Approve a spender address to transfer tokens on behalf of their owner.
* @param owner address token holder address
* @param spender address address that will spend the tokens
* @param amount uint256 amount of tokens to approve
*/
function _approve(address owner, address spender, uint256 amount) private {
// TODO: restore this require statement if this function becomes internal, or is called at a new callsite. It is
// currently unnecessary.
//require(owner != address(0), "ERC777: approve from the zero address");
require(spender != address(0), "ERC777: approve to the zero address");

_allowances[owner][spender] = value;
emit Approval(owner, spender, value);
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}

/**
Expand Down

0 comments on commit 29a3196

Please sign in to comment.