-
-
Save KotNaplakal/8daa20b1ec9b5a2f515e75be4b64dc2a to your computer and use it in GitHub Desktop.
DEC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity 0.4.25; | |
library SafeMath { | |
/** | |
* @dev Multiplies two numbers, throws on overflow. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (uint256) { | |
if (a == 0) { | |
return 0; | |
} | |
uint256 c = a * b; | |
assert(c / a == b); | |
return c; | |
} | |
/** | |
* @dev Integer division of two numbers, truncating the quotient. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
/** | |
* @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
assert(b <= a); | |
return a - b; | |
} | |
/** | |
* @dev Adds two numbers, throws on overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (uint256) { | |
uint256 c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
} | |
contract Ownable { | |
address private _owner; | |
event OwnershipTransferred( | |
address indexed previousOwner, | |
address indexed newOwner | |
); | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
constructor() internal { | |
_owner = msg.sender; | |
emit OwnershipTransferred(address(0), _owner); | |
} | |
/** | |
* @return the address of the owner. | |
*/ | |
function owner() public view returns(address) { | |
return _owner; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(isOwner()); | |
_; | |
} | |
/** | |
* @return true if `msg.sender` is the owner of the contract. | |
*/ | |
function isOwner() public view returns(bool) { | |
return msg.sender == _owner; | |
} | |
/** | |
* @dev Allows the current owner to relinquish control of the contract. | |
* @notice Renouncing to ownership will leave the contract without an owner. | |
* It will not be possible to call the functions with the `onlyOwner` | |
* modifier anymore. | |
*/ | |
function renounceOwnership() public onlyOwner { | |
emit OwnershipTransferred(_owner, address(0)); | |
_owner = address(0); | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
*/ | |
function transferOwnership(address newOwner) public onlyOwner { | |
_transferOwnership(newOwner); | |
} | |
/** | |
* @dev Transfers control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
*/ | |
function _transferOwnership(address newOwner) internal { | |
require(newOwner != address(0)); | |
emit OwnershipTransferred(_owner, newOwner); | |
_owner = newOwner; | |
} | |
} | |
contract ERC820Registry { | |
function getManager(address addr) public view returns(address); | |
function setManager(address addr, address newManager) public; | |
function getInterfaceImplementer(address addr, bytes32 iHash) public constant returns (address); | |
function setInterfaceImplementer(address addr, bytes32 iHash, address implementer) public; | |
} | |
contract ERC820Implementer { | |
ERC820Registry erc820Registry = ERC820Registry(0x991a1bcb077599290d7305493c9A630c20f8b798); | |
function setInterfaceImplementation(string ifaceLabel, address impl) internal { | |
bytes32 ifaceHash = keccak256(abi.encodePacked(ifaceLabel)); | |
erc820Registry.setInterfaceImplementer(this, ifaceHash, impl); | |
} | |
function interfaceAddr(address addr, string ifaceLabel) internal constant returns(address) { | |
bytes32 ifaceHash = keccak256(abi.encodePacked(ifaceLabel)); | |
return erc820Registry.getInterfaceImplementer(addr, ifaceHash); | |
} | |
function delegateManagement(address newManager) internal { | |
erc820Registry.setManager(this, newManager); | |
} | |
} | |
interface ERC777TokensSender { | |
function tokensToSend(address operator, address from, address to, uint amount, bytes userData,bytes operatorData) external; | |
} | |
interface ERC777TokensRecipient { | |
function tokensReceived(address operator, address from, address to, uint amount, bytes userData, bytes operatorData) external; | |
} | |
interface DECAirdropInterface{ | |
function pushTokens( uint256, address ) external; | |
function pullTokens( address ) external; | |
function nodeBlockedBalance( address ) external returns( uint256 ); | |
} | |
contract DEC is ERC820Implementer, Ownable { | |
using SafeMath for uint256; | |
DECAirdropInterface DECAirdrop; | |
address DECAirdropAddress; | |
string public name = "Dec Nodes"; | |
string public symbol = "DEC"; | |
uint8 public decimals = 18; | |
uint256 public granularity = 1; | |
uint256 public totalSupply; | |
event Transfer(address indexed from, address indexed to, uint256 value); | |
event Sent(address indexed operator, address indexed from, address indexed to, uint256 amount, bytes userData, bytes operatorData); | |
event AuthorizedOperator(address indexed operator, address indexed tokenHolder); | |
event RevokedOperator(address indexed operator, address indexed tokenHolder); | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
mapping (address => uint256) public balanceOf; | |
mapping (address => mapping (address => bool)) public isOperatorFor; | |
function setDECAirdropContract( address _address ) public onlyOwner | |
{ | |
DECAirdrop = DECAirdropInterface( _address ); | |
DECAirdropAddress = _address; | |
} | |
function DECAirdropSend( address _from, address _to, uint256 _amount ) public | |
{ | |
require( msg.sender == DECAirdropAddress ); | |
_transfer( _from, _to, _amount ); | |
} | |
function pushTokens( uint256 _amount ) public | |
{ | |
DECAirdrop.pushTokens( _amount, msg.sender ); | |
} | |
function pullTokens() public | |
{ | |
DECAirdrop.pullTokens( msg.sender ); | |
} | |
/** | |
* @notice Send `_amount` of tokens to address `_to` passing `_userData` to the recipient | |
* @param _to The address of the recipient | |
* @param _amount The number of tokens to be sent | |
* @param _userData Data generated by the user to be sent to the recipient | |
*/ | |
function send(address _to, uint256 _amount, bytes _userData) public { | |
doSend(msg.sender, _to, _amount, _userData, msg.sender, "", true); | |
} | |
/** | |
* @notice Authorize a third party `_operator` to manage (send) `msg.sender`'s tokens. | |
* @param _operator The operator that wants to be Authorized | |
*/ | |
function authorizeOperator(address _operator) public { | |
require(_operator != msg.sender); | |
isOperatorFor[_operator][msg.sender] = true; | |
emit AuthorizedOperator(_operator, msg.sender); | |
} | |
/** | |
* @notice Revoke a third party `_operator`'s rights to manage (send) `msg.sender`'s tokens. | |
* @param _operator The operator that wants to be Revoked | |
*/ | |
function revokeOperator(address _operator) public { | |
require(_operator != msg.sender); | |
isOperatorFor[_operator][msg.sender] = false; | |
emit RevokedOperator(_operator, msg.sender); | |
} | |
/** | |
* @notice Send `_amount` of tokens on behalf of the address `from` to the address `to`. | |
* @param _from The address holding the tokens being sent | |
* @param _to The address of the recipient | |
* @param _amount The number of tokens to be sent | |
* @param _userData Data generated by the user to be sent to the recipient | |
* @param _operatorData Data generated by the operator to be sent to the recipient | |
*/ | |
function operatorSend(address _from, address _to, uint256 _amount, bytes _userData, bytes _operatorData) public { | |
require(isOperatorFor[msg.sender][_from]); | |
doSend(_from, _to, _amount, _userData, msg.sender, _operatorData, true); | |
} | |
/* -- Helper Functions -- */ | |
/** | |
* @notice Internal function that ensures `_amount` is multiple of the granularity | |
* @param _amount The quantity that want's to be checked | |
*/ | |
function requireMultiple(uint256 _amount) internal view { | |
require(_amount.div(granularity).mul(granularity) == _amount); | |
} | |
/** | |
* @notice Check whether an address is a regular address or not. | |
* @param _addr Address of the contract that has to be checked | |
* @return `true` if `_addr` is a regular address (not a contract) | |
*/ | |
function isRegularAddress(address _addr) internal constant returns(bool) { | |
if (_addr == 0) { return false; } | |
uint size; | |
assembly { size := extcodesize(_addr) } // solhint-disable-line no-inline-assembly | |
return size == 0; | |
} | |
/** | |
* @notice Helper function that checks for ERC777TokensSender on the sender and calls it. | |
* May throw according to `_preventLocking` | |
* @param _from The address holding the tokens being sent | |
* @param _to The address of the recipient | |
* @param _amount The amount of tokens to be sent | |
* @param _userData Data generated by the user to be passed to the recipient | |
* @param _operatorData Data generated by the operator to be passed to the recipient | |
* implementing `ERC777TokensSender`. | |
* ERC777 native Send functions MUST set this parameter to `true`, and backwards compatible ERC20 transfer | |
* functions SHOULD set this parameter to `false`. | |
*/ | |
function callSender( | |
address _operator, | |
address _from, | |
address _to, | |
uint256 _amount, | |
bytes _userData, | |
bytes _operatorData | |
) private { | |
address senderImplementation = interfaceAddr(_from, "ERC777TokensSender"); | |
if (senderImplementation != 0) { | |
ERC777TokensSender(senderImplementation).tokensToSend( | |
_operator, _from, _to, _amount, _userData, _operatorData); | |
} | |
} | |
/** | |
* @notice Helper function that checks for ERC777TokensRecipient on the recipient and calls it. | |
* May throw according to `_preventLocking` | |
* @param _from The address holding the tokens being sent | |
* @param _to The address of the recipient | |
* @param _amount The number of tokens to be sent | |
* @param _userData Data generated by the user to be passed to the recipient | |
* @param _operatorData Data generated by the operator to be passed to the recipient | |
* @param _preventLocking `true` if you want this function to throw when tokens are sent to a contract not | |
* implementing `ERC777TokensRecipient`. | |
* ERC777 native Send functions MUST set this parameter to `true`, and backwards compatible ERC20 transfer | |
* functions SHOULD set this parameter to `false`. | |
*/ | |
function callRecipient( | |
address _operator, | |
address _from, | |
address _to, | |
uint256 _amount, | |
bytes _userData, | |
bytes _operatorData, | |
bool _preventLocking | |
) private { | |
address recipientImplementation = interfaceAddr(_to, "ERC777TokensRecipient"); | |
if (recipientImplementation != 0) { | |
ERC777TokensRecipient(recipientImplementation).tokensReceived( | |
_operator, _from, _to, _amount, _userData, _operatorData); | |
} else if (_preventLocking) { | |
require(isRegularAddress(_to)); | |
} | |
} | |
/** | |
* @notice Helper function actually performing the sending of tokens. | |
* @param _from The address holding the tokens being sent | |
* @param _to The address of the recipient | |
* @param _amount The number of tokens to be sent | |
* @param _userData Data generated by the user to be passed to the recipient | |
* @param _operatorData Data generated by the operator to be passed to the recipient | |
* @param _preventLocking `true` if you want this function to throw when tokens are sent to a contract not | |
* implementing `erc777_tokenHolder`. | |
* ERC777 native Send functions MUST set this parameter to `true`, and backwards compatible ERC20 transfer | |
* functions SHOULD set this parameter to `false`. | |
*/ | |
function doSend( | |
address _from, | |
address _to, | |
uint256 _amount, | |
bytes _userData, | |
address _operator, | |
bytes _operatorData, | |
bool _preventLocking | |
) | |
private | |
{ | |
requireMultiple(_amount); | |
require( DECAirdrop.nodeBlockedBalance(_to) <= 0 ); | |
callSender(_operator, _from, _to, _amount, _userData, _operatorData); | |
require(_to != 0x0); | |
require(balanceOf[_from] >= _amount); | |
balanceOf[_from] = balanceOf[_from].sub(_amount); | |
balanceOf[_to] = balanceOf[_to].add(_amount); | |
callRecipient(_operator, _from, _to, _amount, _userData, _operatorData, _preventLocking); | |
emit Sent(_operator, _from, _to, _amount, _userData, _operatorData); | |
emit Transfer(_from, _to, _amount); | |
} | |
function _transfer(address _from, address _to, uint256 _value) internal { | |
doSend(_from, _to, _value, "", _from, "", false); | |
} | |
/** | |
* @dev transfer token for a specified address | |
* @param _to The address to transfer to. | |
* @param _value The amount to be transferred. | |
*/ | |
function transfer(address _to, uint256 _value) public returns (bool) { | |
doSend(msg.sender, _to, _value, "", msg.sender, "", false); | |
return true; | |
} | |
/** | |
* @dev Transfer tokens from one address to another. Technically this is not ERC20 transferFrom but more ERC777 operatorSend. | |
* @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 | |
*/ | |
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { | |
require(isOperatorFor[msg.sender][_from]); | |
doSend(_from, _to, _value, "", msg.sender, "", true); | |
emit Transfer(_from, _to, _value); | |
return true; | |
} | |
/** | |
* @dev Originally in ERC20 this function to check the amount of tokens that an owner allowed to a spender. | |
* | |
* Function was added purly for backward compatibility with ERC20. Use operator logic from ERC777 instead. | |
* @param _owner address The address which owns the funds. | |
* @param _spender address The address which will spend the funds. | |
* @return A returning uint256 balanceOf _spender if it's active operator and 0 if not. | |
*/ | |
function allowance(address _owner, address _spender) public view returns (uint256 _amount) { | |
if (isOperatorFor[_spender][_owner]) { | |
_amount = balanceOf[_owner]; | |
} else { | |
_amount = 0; | |
} | |
} | |
/** | |
* @dev Approve the passed address to spend tokens on behalf of msg.sender. | |
* | |
* This function is more authorizeOperator and revokeOperator from ERC777 that Approve from ERC20. | |
* Approve concept has several issues (e.g. https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729), | |
* so I prefer to use operator concept. If you want to revoke approval, just put 0 into _value. | |
* @param _spender The address which will spend the funds. | |
* @param _value Fake value to be compatible with ERC20 requirements. | |
*/ | |
function approve(address _spender, uint256 _value) public returns (bool) { | |
require(_spender != msg.sender); | |
if (_value > 0) { | |
// Authorizing operator | |
isOperatorFor[_spender][msg.sender] = true; | |
emit AuthorizedOperator(_spender, msg.sender); | |
} else { | |
// Revoking operator | |
isOperatorFor[_spender][msg.sender] = false; | |
emit RevokedOperator(_spender, msg.sender); | |
} | |
emit Approval(msg.sender, _spender, _value); | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment