Skip to content

Commit

Permalink
Merge e53a14a into 2ccc12b
Browse files Browse the repository at this point in the history
  • Loading branch information
Augusto Lemble committed May 21, 2019
2 parents 2ccc12b + e53a14a commit b7abe27
Show file tree
Hide file tree
Showing 6 changed files with 406 additions and 0 deletions.
98 changes: 98 additions & 0 deletions contracts/drafts/ERC827/ERC827.sol
@@ -0,0 +1,98 @@
/* solium-disable security/no-low-level-calls */

pragma solidity ^0.5.2;

import "../../token/ERC20/ERC20.sol";
import "./ERC827Proxy.sol";


/**
* @title ERC827, an extension of ERC20 token standard
*
* @dev Implementation the ERC827, following the ERC20 standard with extra
* methods to transfer value, data and execute calls inside transfers and
* approvals. Uses OpenZeppelin ERC20.
*/
contract ERC827 is ERC20 {

ERC827Proxy public proxy;

/**
* @dev Constructor
*/
constructor() public {
proxy = new ERC827Proxy();
}

/**
* @dev Addition to ERC20 token methods. It allows to
* approve the transfer of value and execute a call with the sent data.
* 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:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
* @param _spender The address that will spend the funds.
* @param _value The amount of tokens to be spent.
* @param _data ABI-encoded contract call to call `_spender` address.
* @return true if the call function was executed successfully
*/
function approveAndCall(
address _spender, uint256 _value, bytes memory _data
) public payable returns (bool) {
super.approve(_spender, _value);
// solhint-disable-next-line avoid-low-level-calls
_call(_spender, _data);
return true;
}

/**
* @dev Addition to ERC20 token methods. Transfer tokens to a specified
* address and execute a call with the sent data on the same transaction
* @param _to address The address which you want to transfer to
* @param _value uint256 the amout of tokens to be transfered
* @param _data ABI-encoded contract call to call `_to` address.
* @return true if the call function was executed successfully
*/
function transferAndCall(
address _to, uint256 _value, bytes memory _data
) public payable returns (bool) {
super.transfer(_to, _value);
// solhint-disable-next-line avoid-low-level-calls
_call(_to, _data);
return true;
}

/**
* @dev Addition to ERC20 token methods. Transfer tokens from one address to
* another and make a contract call on the same transaction
* @param _from The address which you want to send tokens from
* @param _to The address which you want to transfer to
* @param _value The amout of tokens to be transferred
* @param _data ABI-encoded contract call to call `_to` address.
* @return true if the call function was executed successfully
*/
function transferFromAndCall(
address _from, address _to, uint256 _value, bytes memory _data
) public payable returns (bool) {
super.transferFrom(_from, _to, _value);
// solhint-disable-next-line avoid-low-level-calls
_call(_to, _data);
return true;
}

/**
* @dev Call a external contract
* @param _to The address of the contract to call
* @param _data ABI-encoded contract call to call `_to` address.
*/
function _call(address _to, bytes memory _data) internal {
// solhint-disable-next-line avoid-call-value, no-unused-vars
(bool success, bytes memory data) = address(proxy).call.value(msg.value)(
abi.encodeWithSelector(proxy.callContractFunctionSignature(), _to, _data)
);
require(success, "Call to external contract failed");
}

}
44 changes: 44 additions & 0 deletions contracts/drafts/ERC827/ERC827Proxy.sol
@@ -0,0 +1,44 @@
/* solium-disable security/no-low-level-calls */

pragma solidity ^0.5.2;


/**
* @title ERC827Proxy
*
* @dev Proxy to forward contract calls from token contract to any other
* contract.
*/
contract ERC827Proxy {

address public token;
bytes4 public callContractFunctionSignature = bytes4(
keccak256("callContract(address,bytes)")
);

/**
* @dev constructor, executed by the ERC827 token when it is deployed.
*/
constructor() public {
token = address(msg.sender);
}

/**
* @dev Forward calls only from the token contract that created it
* @param _target address The address which you want to transfer to
* @param _data bytes The data to be executed in the call
*/
function callContract(
address _target, bytes memory _data
) public payable returns (bool) {
require(
msg.sender == address(token),
"Proxy cant execute calls to the token contract"
);
// solhint-disable-next-line avoid-call-value, no-unused-vars
(bool success, bytes memory data) = _target.call.value(msg.value)(_data);
require(success, "Proxy call failed");
return true;
}

}
38 changes: 38 additions & 0 deletions contracts/drafts/ERC827/IERC827.sol
@@ -0,0 +1,38 @@
pragma solidity ^0.5.2;


/**
* @title ERC827 interface, an extension of ERC20 token standard
*
* @dev Interface of a ERC827 token, following the ERC20 standard with extra
* methods to transfer value and data and execute calls in transfers and
* approvals.
*/
interface IERC827 {

function transfer(address to, uint256 value) external returns (bool);

function approve(address spender, uint256 value) external returns (bool);

function transferFrom(address from, address to, uint256 value) external returns (bool);

function approveAndCall(address _spender, uint256 _value, bytes calldata _data)
external payable returns (bool);

function transferAndCall(address _to, uint256 _value, bytes calldata _data)
external payable returns (bool);

function transferFromAndCall(
address _from, address _to, uint256 _value, bytes calldata _data
) external payable returns (bool);

function totalSupply() external view returns (uint256);

function balanceOf(address who) external view returns (uint256);

function allowance(address owner, address spender) external view returns (uint256);

event Transfer(address indexed from, address indexed to, uint256 value);

event Approval(address indexed owner, address indexed spender, uint256 value);
}
14 changes: 14 additions & 0 deletions contracts/mocks/ERC827TokenMock.sol
@@ -0,0 +1,14 @@
pragma solidity ^0.5.0;


import "../drafts/ERC827/ERC827.sol";


// mock class using ERC827 Token
contract ERC827TokenMock is ERC827 {

constructor(address initialAccount, uint256 initialBalance) public ERC827() {
_mint(initialAccount, initialBalance);
}

}
19 changes: 19 additions & 0 deletions contracts/mocks/MessageHelper.sol
@@ -0,0 +1,19 @@
pragma solidity ^0.5.0;


contract MessageHelper {

event Show(bytes32 b32, uint256 number, string text);

function showMessage(bytes32 b32, uint256 number, string memory text)
public payable returns (bool)
{
emit Show(b32, number, text);
return true;
}

function fail() public {
revert("MessageHelper fail function failed");
}

}

0 comments on commit b7abe27

Please sign in to comment.