pragmasolidity 0.5.8;import"./ERC777ERC20Compat.sol";
import"./SafeGuard.sol";
import { CStore } from"./CStore.sol"; //TODO: Convert all imports like thiscontractCALLisERC777ERC20Compat, SafeGuard{
constructor(stringmemory _name,
stringmemory _symbol,
uint256 _granularity,
uint256 _totalSupply,
address _initialOwner,
address[] memory _defaultOperators
)
publicERC777ERC20Compat(_name, _symbol, _granularity, _totalSupply, _initialOwner, _defaultOperators)
{
requireMultiple(_totalSupply);
require(balancesDB.setModule(address(this), true), "Cannot enable access to the database.");
balancesDB.transferOwnership(_initialOwner);
callRecipient(msg.sender, address(0), _initialOwner, _totalSupply, "", "", true);
emit Minted(msg.sender, _initialOwner, _totalSupply, "", "");
if (mErc20compatible) { emit Transfer(address(0), _initialOwner, _totalSupply); }
}
/**
* @notice change the balances database to `_newDB`
* @param _newDB The new balances database address
*/functionchangeBalancesDB(address _newDB) publiconlyOwner{
balancesDB = CStore(_newDB);
}
/**
* @notice Disables the ERC20 interface. This function can only be called
* by the owner.
*/functiondisableERC20() publiconlyOwner{
mErc20compatible =false;
setInterfaceImplementation("ERC20Token", address(0));
}
/**
* @notice Re enables the ERC20 interface. This function can only be called
* by the owner.
*/functionenableERC20() publiconlyOwner{
mErc20compatible =true;
setInterfaceImplementation("ERC20Token", address(this));
}
/**
* @dev Transfer the specified amounts of tokens to the specified addresses.
* @dev Be aware that there is no check for duplicate recipients.
* @param _toAddresses Receiver addresses.
* @param _amounts Amounts of tokens that will be transferred.
*/functionmultiPartyTransfer(address[] calldata _toAddresses, uint256[] calldata _amounts) externalerc20{
/* Ensures _toAddresses array is less than or equal to 255 */require(_toAddresses.length<=255, "Unsupported number of addresses.");
/* Ensures _toAddress and _amounts have the same number of entries. */require(_toAddresses.length== _amounts.length, "Provided addresses does not equal to provided sums.");
for (uint8 i =0; i < _toAddresses.length; i++) {
transfer(_toAddresses[i], _amounts[i]);
}
}
/**
* @dev Transfer the specified amounts of tokens to the specified addresses from authorized balance of sender.
* @dev Be aware that there is no check for duplicate recipients.
* @param _from The address of the sender
* @param _toAddresses The addresses of the recipients (MAX 255)
* @param _amounts The amounts of tokens to be transferred
*/functionmultiPartyTransferFrom(address _from, address[] calldata _toAddresses, uint256[] calldata _amounts) externalerc20{
/* Ensures _toAddresses array is less than or equal to 255 */require(_toAddresses.length<=255, "Unsupported number of addresses.");
/* Ensures _toAddress and _amounts have the same number of entries. */require(_toAddresses.length== _amounts.length, "Provided addresses does not equal to provided sums.");
for (uint8 i =0; i < _toAddresses.length; i++) {
transferFrom(_from, _toAddresses[i], _amounts[i]);
}
}
/**
* @dev Transfer the specified amounts of tokens to the specified addresses.
* @dev Be aware that there is no check for duplicate recipients.
* @param _toAddresses Receiver addresses.
* @param _amounts Amounts of tokens that will be transferred.
* @param _userData User supplied data
*/functionmultiPartySend(address[] memory _toAddresses, uint256[] memory _amounts, bytesmemory _userData) public{
/* Ensures _toAddresses array is less than or equal to 255 */require(_toAddresses.length<=255, "Unsupported number of addresses.");
/* Ensures _toAddress and _amounts have the same number of entries. */require(_toAddresses.length== _amounts.length, "Provided addresses does not equal to provided sums.");
for (uint8 i =0; i < _toAddresses.length; i++) {
doSend(msg.sender, msg.sender, _toAddresses[i], _amounts[i], _userData, "", true);
}
}
/**
* @dev Transfer the specified amounts of tokens to the specified addresses as `_from`.
* @dev Be aware that there is no check for duplicate recipients.
* @param _from Address to use as sender
* @param _to Receiver addresses.
* @param _amounts Amounts of tokens that will be transferred.
* @param _userData User supplied data
* @param _operatorData Operator supplied data
*/functionmultiOperatorSend(address _from, address[] calldata _to, uint256[] calldata _amounts, bytescalldata _userData, bytescalldata _operatorData)
external{
/* Ensures _toAddresses array is less than or equal to 255 */require(_to.length<=255, "Unsupported number of addresses.");
/* Ensures _toAddress and _amounts have the same number of entries. */require(_to.length== _amounts.length, "Provided addresses does not equal to provided sums.");
for (uint8 i =0; i < _to.length; i++) {
require(isOperatorFor(msg.sender, _from), "Not an operator"); //TODO check for denial of service
doSend(msg.sender, _from, _to[i], _amounts[i], _userData, _operatorData, true);
}
}
}
Contract Source Code
File 2 of 16: CStore.sol
pragmasolidity 0.5.8;import"./ERC644Balances.sol";
import { ERC1820Client } from"./ERC1820Client.sol";
/**
* @title ERC644 Database Contract
* @author Panos
*/contractCStoreisERC644Balances, ERC1820Client{
address[] internal mDefaultOperators;
mapping(address=>bool) internal mIsDefaultOperator;
mapping(address=>mapping(address=>bool)) internal mRevokedDefaultOperator;
mapping(address=>mapping(address=>bool)) internal mAuthorizedOperators;
/**
* @notice Database construction
* @param _totalSupply The total supply of the token
*/constructor(uint256 _totalSupply, address _initialOwner, address[] memory _defaultOperators) public{
balances[_initialOwner] = _totalSupply;
totalSupply = _totalSupply;
mDefaultOperators = _defaultOperators;
for (uint256 i =0; i < mDefaultOperators.length; i++) { mIsDefaultOperator[mDefaultOperators[i]] =true; }
setInterfaceImplementation("ERC644Balances", address(this));
}
/**
* @notice Increase total supply by `_val`
* @param _val Value to increase
* @return Operation status
*/// solhint-disable-next-line no-unused-varsfunctionincTotalSupply(uint _val) externalonlyModulereturns (bool) {
returnfalse;
}
/**
* @notice Decrease total supply by `_val`
* @param _val Value to decrease
* @return Operation status
*/// solhint-disable-next-line no-unused-varsfunctiondecTotalSupply(uint _val) externalonlyModulereturns (bool) {
returnfalse;
}
/**
* @notice moving `_amount` from `_from` to `_to`
* @param _from The sender address
* @param _to The receiving address
* @param _amount The moving amount
* @return bool The move result
*/functionmove(address _from, address _to, uint256 _amount) externalonlyModulereturns (bool) {
balances[_from] = balances[_from].sub(_amount);
emit BalanceAdj(msg.sender, _from, _amount, "-");
balances[_to] = balances[_to].add(_amount);
emit BalanceAdj(msg.sender, _to, _amount, "+");
returntrue;
}
/**
* @notice Setting operator `_operator` for `_tokenHolder`
* @param _operator The operator to set status
* @param _tokenHolder The token holder to set operator
* @param _status The operator status
* @return bool Status of operation
*/functionsetAuthorizedOperator(address _operator, address _tokenHolder, bool _status) externalonlyModulereturns (bool) {
mAuthorizedOperators[_operator][_tokenHolder] = _status;
returntrue;
}
/**
* @notice Set revoke status for default operator `_operator` for `_tokenHolder`
* @param _operator The default operator to set status
* @param _tokenHolder The token holder to set operator
* @param _status The operator status
* @return bool Status of operation
*/functionsetRevokedDefaultOperator(address _operator, address _tokenHolder, bool _status) externalonlyModulereturns (bool) {
mRevokedDefaultOperator[_operator][_tokenHolder] = _status;
returntrue;
}
/**
* @notice Getting operator `_operator` for `_tokenHolder`
* @param _operator The operator address to get status
* @param _tokenHolder The token holder address
* @return bool Operator status
*/functiongetAuthorizedOperator(address _operator, address _tokenHolder) externalviewreturns (bool) {
return mAuthorizedOperators[_operator][_tokenHolder];
}
/**
* @notice Getting default operator `_operator`
* @param _operator The default operator address to get status
* @return bool Default operator status
*/functiongetDefaultOperator(address _operator) externalviewreturns (bool) {
return mIsDefaultOperator[_operator];
}
/**
* @notice Getting default operators
* @return address[] Default operator addresses
*/functiongetDefaultOperators() externalviewreturns (address[] memory) {
return mDefaultOperators;
}
functiongetRevokedDefaultOperator(address _operator, address _tokenHolder) externalviewreturns (bool) {
return mRevokedDefaultOperator[_operator][_tokenHolder];
}
/**
* @notice Increment `_acct` balance by `_val`
* @param _acct Target account to increment balance.
* @param _val Value to increment
* @return Operation status
*/// solhint-disable-next-line no-unused-varsfunctionincBalance(address _acct, uint _val) publiconlyModulereturns (bool) {
returnfalse;
}
/**
* @notice Decrement `_acct` balance by `_val`
* @param _acct Target account to decrement balance.
* @param _val Value to decrement
* @return Operation status
*/// solhint-disable-next-line no-unused-varsfunctiondecBalance(address _acct, uint _val) publiconlyModulereturns (bool) {
returnfalse;
}
}
Contract Source Code
File 3 of 16: Context.sol
pragmasolidity ^0.5.0;/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/contractContext{
// Empty internal constructor, to prevent people from mistakenly deploying// an instance of this contract, which should be used via inheritance.constructor () internal{ }
// solhint-disable-previous-line no-empty-blocksfunction_msgSender() internalviewreturns (addresspayable) {
returnmsg.sender;
}
function_msgData() internalviewreturns (bytesmemory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691returnmsg.data;
}
}
pragmasolidity 0.5.8;import"./SafeMath.sol";
import"./SafeGuard.sol";
import"./IERC644.sol";
/**
* @title ERC644 Standard Balances Contract
* @author chrisfranko
*/contractERC644BalancesisIERC644, SafeGuard{
usingSafeMathforuint256;
uint256public totalSupply;
eventBalanceAdj(addressindexed module, addressindexed account, uint amount, string polarity);
eventModuleSet(addressindexed module, boolindexed set);
mapping(address=>bool) public modules;
mapping(address=>uint256) public balances;
mapping(address=>mapping(address=>uint256)) public allowed;
modifieronlyModule() {
require(modules[msg.sender], "ERC644Balances: caller is not a module");
_;
}
/**
* @notice Set allowance of `_spender` in behalf of `_sender` at `_value`
* @param _sender Owner account
* @param _spender Spender account
* @param _value Value to approve
* @return Operation status
*/functionsetApprove(address _sender, address _spender, uint256 _value) externalonlyModulereturns (bool) {
allowed[_sender][_spender] = _value;
returntrue;
}
/**
* @notice Decrease allowance of `_spender` in behalf of `_from` at `_value`
* @param _from Owner account
* @param _spender Spender account
* @param _value Value to decrease
* @return Operation status
*/functiondecApprove(address _from, address _spender, uint _value) externalonlyModulereturns (bool) {
allowed[_from][_spender] = allowed[_from][_spender].sub(_value);
returntrue;
}
/**
* @notice Increase total supply by `_val`
* @param _val Value to increase
* @return Operation status
*/functionincTotalSupply(uint _val) externalonlyModulereturns (bool) {
totalSupply = totalSupply.add(_val);
returntrue;
}
/**
* @notice Decrease total supply by `_val`
* @param _val Value to decrease
* @return Operation status
*/functiondecTotalSupply(uint _val) externalonlyModulereturns (bool) {
totalSupply = totalSupply.sub(_val);
returntrue;
}
/**
* @notice Set/Unset `_acct` as an authorized module
* @param _acct Module address
* @param _set Module set status
* @return Operation status
*/functionsetModule(address _acct, bool _set) externalonlyOwnerreturns (bool) {
modules[_acct] = _set;
emit ModuleSet(_acct, _set);
returntrue;
}
/**
* @notice Get `_acct` balance
* @param _acct Target account to get balance.
* @return The account balance
*/functiongetBalance(address _acct) externalviewreturns (uint256) {
return balances[_acct];
}
/**
* @notice Get allowance of `_spender` in behalf of `_owner`
* @param _owner Owner account
* @param _spender Spender account
* @return Allowance
*/functiongetAllowance(address _owner, address _spender) externalviewreturns (uint256) {
return allowed[_owner][_spender];
}
/**
* @notice Get if `_acct` is an authorized module
* @param _acct Module address
* @return Operation status
*/functiongetModule(address _acct) externalviewreturns (bool) {
return modules[_acct];
}
/**
* @notice Get total supply
* @return Total supply
*/functiongetTotalSupply() externalviewreturns (uint256) {
return totalSupply;
}
/**
* @notice Increment `_acct` balance by `_val`
* @param _acct Target account to increment balance.
* @param _val Value to increment
* @return Operation status
*/functionincBalance(address _acct, uint _val) publiconlyModulereturns (bool) {
balances[_acct] = balances[_acct].add(_val);
emit BalanceAdj(msg.sender, _acct, _val, "+");
returntrue;
}
/**
* @notice Decrement `_acct` balance by `_val`
* @param _acct Target account to decrement balance.
* @param _val Value to decrement
* @return Operation status
*/functiondecBalance(address _acct, uint _val) publiconlyModulereturns (bool) {
balances[_acct] = balances[_acct].sub(_val);
emit BalanceAdj(msg.sender, _acct, _val, "-");
returntrue;
}
functiontransferRoot(address _new) externalreturns (bool) {
returnfalse;
}
}
Contract Source Code
File 6 of 16: ERC777.sol
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */pragmasolidity 0.5.8;import { ERC1820Client } from"./ERC1820Client.sol";
import { SafeMath } from"./SafeMath.sol";
import { IERC777 } from"./IERC777.sol";
import { IERC777TokensSender } from"./IERC777TokensSender.sol";
import { IERC777TokensRecipient } from"./IERC777TokensRecipient.sol";
contractERC777isIERC777, ERC1820Client{
usingSafeMathforuint256;
stringinternal mName;
stringinternal mSymbol;
uint256internal mGranularity;
uint256internal mTotalSupply;
mapping(address=>uint) internal mBalances;
address[] internal mDefaultOperators;
mapping(address=>bool) internal mIsDefaultOperator;
mapping(address=>mapping(address=>bool)) internal mRevokedDefaultOperator;
mapping(address=>mapping(address=>bool)) internal mAuthorizedOperators;
/* -- Constructor -- *////// @notice Constructor to create a ReferenceToken/// @param _name Name of the new token/// @param _symbol Symbol of the new token./// @param _granularity Minimum transferable chunk.constructor(stringmemory _name,
stringmemory _symbol,
uint256 _granularity,
address[] memory _defaultOperators
) internal{
mName = _name;
mSymbol = _symbol;
mTotalSupply =0;
require(_granularity >=1, "Granularity must be > 1");
mGranularity = _granularity;
mDefaultOperators = _defaultOperators;
for (uint256 i =0; i < mDefaultOperators.length; i++) { mIsDefaultOperator[mDefaultOperators[i]] =true; }
setInterfaceImplementation("ERC777Token", address(this));
}
/* -- ERC777 Interface Implementation -- *////// @return the name of the tokenfunctionname() publicviewreturns (stringmemory) { return mName; }
/// @return the symbol of the tokenfunctionsymbol() publicviewreturns (stringmemory) { return mSymbol; }
/// @return the granularity of the tokenfunctiongranularity() publicviewreturns (uint256) { return mGranularity; }
/// @return the total supply of the tokenfunctiontotalSupply() publicviewreturns (uint256) { return mTotalSupply; }
/// @notice Return the account balance of some account/// @param _tokenHolder Address for which the balance is returned/// @return the balance of `_tokenAddress`.functionbalanceOf(address _tokenHolder) publicviewreturns (uint256) { return mBalances[_tokenHolder]; }
/// @notice Return the list of default operators/// @return the list of all the default operatorsfunctiondefaultOperators() publicviewreturns (address[] memory) { return mDefaultOperators; }
/// @notice Send `_amount` of tokens to address `_to` passing `_data` to the recipient/// @param _to The address of the recipient/// @param _amount The number of tokens to be sentfunctionsend(address _to, uint256 _amount, bytescalldata _data) external{
doSend(msg.sender, msg.sender, _to, _amount, _data, "", true);
}
/// @notice Authorize a third party `_operator` to manage (send) `msg.sender`'s tokens./// @param _operator The operator that wants to be AuthorizedfunctionauthorizeOperator(address _operator) external{
require(_operator !=msg.sender, "Cannot authorize yourself as an operator");
if (mIsDefaultOperator[_operator]) {
mRevokedDefaultOperator[_operator][msg.sender] =false;
} else {
mAuthorizedOperators[_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 RevokedfunctionrevokeOperator(address _operator) external{
require(_operator !=msg.sender, "Cannot revoke yourself as an operator");
if (mIsDefaultOperator[_operator]) {
mRevokedDefaultOperator[_operator][msg.sender] =true;
} else {
mAuthorizedOperators[_operator][msg.sender] =false;
}
emit RevokedOperator(_operator, msg.sender);
}
/// @notice Check whether the `_operator` address is allowed to manage the tokens held by `_tokenHolder` address./// @param _operator address to check if it has the right to manage the tokens/// @param _tokenHolder address which holds the tokens to be managed/// @return `true` if `_operator` is authorized for `_tokenHolder`functionisOperatorFor(address _operator, address _tokenHolder) publicviewreturns (bool) {
return (_operator == _tokenHolder // solium-disable-line operator-whitespace|| mAuthorizedOperators[_operator][_tokenHolder]
|| (mIsDefaultOperator[_operator] &&!mRevokedDefaultOperator[_operator][_tokenHolder]));
}
/// @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 _data Data generated by the user to be sent to the recipient/// @param _operatorData Data generated by the operator to be sent to the recipientfunctionoperatorSend(address _from,
address _to,
uint256 _amount,
bytescalldata _data,
bytescalldata _operatorData
)
external{
require(isOperatorFor(msg.sender, _from), "Not an operator.");
doSend(msg.sender, _from, _to, _amount, _data, _operatorData, true);
}
functionburn(uint256 _amount, bytescalldata _data) external{
doBurn(msg.sender, msg.sender, _amount, _data, "");
}
functionoperatorBurn(address _tokenHolder,
uint256 _amount,
bytescalldata _data,
bytescalldata _operatorData
)
external{
require(isOperatorFor(msg.sender, _tokenHolder), "Not an operator");
doBurn(msg.sender, _tokenHolder, _amount, _data, _operatorData);
}
/* -- Helper Functions -- *////// @notice Internal function that ensures `_amount` is multiple of the granularity/// @param _amount The quantity that want's to be checkedfunctionrequireMultiple(uint256 _amount) internalview{
require(_amount % mGranularity ==0, "Amount is not a multiple of granularity");
}
/// @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)functionisRegularAddress(address _addr) internalviewreturns(bool) {
if (_addr ==address(0)) { returnfalse; }
uint size;
assembly { size :=extcodesize(_addr) } // solium-disable-line security/no-inline-assemblyreturn size ==0;
}
/// @notice Helper function actually performing the sending of tokens./// @param _operator The address performing the send/// @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 _data 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`.functiondoSend(address _operator,
address _from,
address _to,
uint256 _amount,
bytesmemory _data,
bytesmemory _operatorData,
bool _preventLocking
)
internal{
requireMultiple(_amount);
callSender(_operator, _from, _to, _amount, _data, _operatorData);
require(_to !=address(0), "Cannot send to 0x0");
require(mBalances[_from] >= _amount, "Not enough funds");
mBalances[_from] = mBalances[_from].sub(_amount);
mBalances[_to] = mBalances[_to].add(_amount);
callRecipient(_operator, _from, _to, _amount, _data, _operatorData, _preventLocking);
emit Sent(_operator, _from, _to, _amount, _data, _operatorData);
}
/// @notice Helper function actually performing the burning of tokens./// @param _operator The address performing the burn/// @param _tokenHolder The address holding the tokens being burn/// @param _amount The number of tokens to be burnt/// @param _data Data generated by the token holder/// @param _operatorData Data generated by the operatorfunctiondoBurn(address _operator,
address _tokenHolder,
uint256 _amount,
bytesmemory _data,
bytesmemory _operatorData
)
internal{
callSender(_operator, _tokenHolder, address(0), _amount, _data, _operatorData);
requireMultiple(_amount);
require(balanceOf(_tokenHolder) >= _amount, "Not enough funds");
mBalances[_tokenHolder] = mBalances[_tokenHolder].sub(_amount);
mTotalSupply = mTotalSupply.sub(_amount);
emit Burned(_operator, _tokenHolder, _amount, _data, _operatorData);
}
/// @notice Helper function that checks for ERC777TokensRecipient on the recipient and calls it./// May throw according to `_preventLocking`/// @param _operator The address performing the send or mint/// @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 _data 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`.functioncallRecipient(address _operator,
address _from,
address _to,
uint256 _amount,
bytesmemory _data,
bytesmemory _operatorData,
bool _preventLocking
)
internal{
address recipientImplementation = interfaceAddr(_to, "ERC777TokensRecipient");
if (recipientImplementation !=address(0)) {
IERC777TokensRecipient(recipientImplementation).tokensReceived(
_operator, _from, _to, _amount, _data, _operatorData);
} elseif (_preventLocking) {
require(isRegularAddress(_to), "Cannot send to contract without ERC777TokensRecipient");
}
}
/// @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 _data 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`.functioncallSender(address _operator,
address _from,
address _to,
uint256 _amount,
bytesmemory _data,
bytesmemory _operatorData
)
internal{
address senderImplementation = interfaceAddr(_from, "ERC777TokensSender");
if (senderImplementation ==address(0)) { return; }
IERC777TokensSender(senderImplementation).tokensToSend(
_operator, _from, _to, _amount, _data, _operatorData);
}
}
Contract Source Code
File 7 of 16: ERC777ERC20Compat.sol
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */pragmasolidity 0.5.8;import { IERC20 } from"./IERC20.sol";
import { ERC777RemoteBridge } from"./ERC777RemoteBridge.sol";
contractERC777ERC20CompatisIERC20, ERC777RemoteBridge{
boolinternal mErc20compatible;
mapping(address=>mapping(address=>uint256)) internal mAllowed;
constructor(stringmemory _name,
stringmemory _symbol,
uint256 _granularity,
uint256 _totalSupply,
address _initialOwner,
address[] memory _defaultOperators
)
internalERC777RemoteBridge(_name, _symbol, _granularity, _totalSupply, _initialOwner, _defaultOperators)
{
mErc20compatible =true;
setInterfaceImplementation("ERC20Token", address(this));
}
/// @notice This modifier is applied to erc20 obsolete methods that are/// implemented only to maintain backwards compatibility. When the erc20/// compatibility is disabled, this methods will fail.modifiererc20 () {
require(mErc20compatible, "ERC20 is disabled");
_;
}
/// @notice For Backwards compatibility/// @return The decimals of the token. Forced to 18 in ERC777.functiondecimals() publicerc20viewreturns (uint8) { returnuint8(18); }
/// @notice ERC20 backwards compatible transfer./// @param _to The address of the recipient/// @param _amount The number of tokens to be transferred/// @return `true`, if the transfer can't be done, it should fail.functiontransfer(address _to, uint256 _amount) publicerc20returns (bool success) {
doSend(msg.sender, msg.sender, _to, _amount, "", "", false);
returntrue;
}
/// @notice ERC20 backwards compatible transferFrom./// @param _from The address holding the tokens being transferred/// @param _to The address of the recipient/// @param _amount The number of tokens to be transferred/// @return `true`, if the transfer can't be done, it should fail.functiontransferFrom(address _from, address _to, uint256 _amount) publicerc20returns (bool success) {
uint256 allowance = balancesDB.getAllowance(_from, msg.sender);
require(_amount <= allowance, "Not enough allowance.");
// Cannot be after doSend because of tokensReceived re-entryrequire(balancesDB.decApprove(_from, msg.sender, _amount));
doSend(msg.sender, _from, _to, _amount, "", "", false);
returntrue;
}
/// @notice ERC20 backwards compatible approve./// `msg.sender` approves `_spender` to spend `_amount` tokens on its behalf./// @param _spender The address of the account able to transfer the tokens/// @param _amount The number of tokens to be approved for transfer/// @return `true`, if the approve can't be done, it should fail.functionapprove(address _spender, uint256 _amount) publicerc20returns (bool success) {
require(balancesDB.setApprove(msg.sender, _spender, _amount));
emit Approval(msg.sender, _spender, _amount);
returntrue;
}
/// @notice ERC20 backwards compatible allowance./// This function makes it easy to read the `allowed[]` map/// @param _owner The address of the account that owns the token/// @param _spender The address of the account able to transfer the tokens/// @return Amount of remaining tokens of _owner that _spender is allowed/// to spendfunctionallowance(address _owner, address _spender) publicerc20viewreturns (uint256 remaining) {
return balancesDB.getAllowance(_owner, _spender);
}
functiondoSend(address _operator,
address _from,
address _to,
uint256 _amount,
bytesmemory _data,
bytesmemory _operatorData,
bool _preventLocking
)
internal{
super.doSend(_operator, _from, _to, _amount, _data, _operatorData, _preventLocking);
if (mErc20compatible) { emit Transfer(_from, _to, _amount); }
}
functiondoBurn(address _operator,
address _tokenHolder,
uint256 _amount,
bytesmemory _data,
bytesmemory _operatorData
)
internal{
super.doBurn(_operator, _tokenHolder, _amount, _data, _operatorData);
if (mErc20compatible) { emit Transfer(_tokenHolder, address(0), _amount); }
}
}
Contract Source Code
File 8 of 16: ERC777RemoteBridge.sol
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */pragmasolidity 0.5.8;import { ERC777 } from"./ERC777.sol";
import { CStore } from"./CStore.sol";
contractERC777RemoteBridgeisERC777{
CStore public balancesDB;
constructor(stringmemory _name,
stringmemory _symbol,
uint256 _granularity,
uint256 _totalSupply,
address _initialOwner,
address[] memory _defaultOperators
)
publicERC777(_name, _symbol, _granularity, newaddress[](0))
{
balancesDB =new CStore(_totalSupply, _initialOwner, _defaultOperators);
}
/**
* @return the total supply of the token
*/functiontotalSupply() publicviewreturns (uint256) {
return balancesDB.getTotalSupply();
}
/**
* @notice Return the account balance of some account
* @param _tokenHolder Address for which the balance is returned
* @return the balance of `_tokenAddress`.
*/functionbalanceOf(address _tokenHolder) publicviewreturns (uint256) {
return balancesDB.getBalance(_tokenHolder);
}
/**
* @notice Return the list of default operators
* @return the list of all the default operators
*/functiondefaultOperators() publicviewreturns (address[] memory) {
return balancesDB.getDefaultOperators();
}
/**
* @notice Authorize a third party `_operator` to manage (send) `msg.sender`'s tokens at remote database.
* @param _operator The operator that wants to be Authorized
*/functionauthorizeOperator(address _operator) external{
require(_operator !=msg.sender, "Cannot authorize yourself as an operator");
if (balancesDB.getDefaultOperator(_operator)) {
require(balancesDB.setRevokedDefaultOperator(_operator, msg.sender, false));
} else {
require(balancesDB.setAuthorizedOperator(_operator, msg.sender, true));
}
emit AuthorizedOperator(_operator, msg.sender);
}
/**
* @notice Revoke a third party `_operator`'s rights to manage (send) `msg.sender`'s tokens at remote database.
* @param _operator The operator that wants to be Revoked
*/functionrevokeOperator(address _operator) external{
require(_operator !=msg.sender, "Cannot revoke yourself as an operator");
if (balancesDB.getDefaultOperator(_operator)) {
require(balancesDB.setRevokedDefaultOperator(_operator, msg.sender, true));
} else {
require(balancesDB.setAuthorizedOperator(_operator, msg.sender, false));
}
emit RevokedOperator(_operator, msg.sender);
}
/**
* @notice Check whether the `_operator` address is allowed to manage the tokens held by `_tokenHolder`
* address at remote database.
* @param _operator address to check if it has the right to manage the tokens
* @param _tokenHolder address which holds the tokens to be managed
* @return `true` if `_operator` is authorized for `_tokenHolder`
*/functionisOperatorFor(address _operator, address _tokenHolder) publicviewreturns (bool) {
return _operator == _tokenHolder || balancesDB.getAuthorizedOperator(_operator, _tokenHolder);
return (_operator == _tokenHolder // solium-disable-line operator-whitespace|| balancesDB.getAuthorizedOperator(_operator, _tokenHolder)
|| (balancesDB.getDefaultOperator(_operator) &&!balancesDB.getRevokedDefaultOperator(_operator, _tokenHolder)));
}
/**
* @notice Helper function actually performing the sending of tokens using a backend database.
* @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 _data 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`.
*/functiondoSend(address _operator,
address _from,
address _to,
uint256 _amount,
bytesmemory _data,
bytesmemory _operatorData,
bool _preventLocking
)
internal{
requireMultiple(_amount);
callSender(_operator, _from, _to, _amount, _data, _operatorData);
require(_to !=address(0), "Cannot send to 0x0"); // forbid sending to 0x0 (=burning)// require(mBalances[_from] >= _amount); // ensure enough funds// (Not Required due to SafeMath throw if underflow in database and false check)require(balancesDB.move(_from, _to, _amount));
callRecipient(_operator, _from, _to, _amount, _data, _operatorData, _preventLocking);
emit Sent(_operator, _from, _to, _amount, _data, _operatorData);
//if (mErc20compatible) { emit Transfer(_from, _to, _amount); }
}
/**
* @notice Helper function actually performing the burning of tokens.
* @param _operator The address performing the burn
* @param _tokenHolder The address holding the tokens being burn
* @param _amount The number of tokens to be burnt
* @param _data Data generated by the token holder
* @param _operatorData Data generated by the operator
*/functiondoBurn(address _operator,
address _tokenHolder,
uint256 _amount,
bytesmemory _data,
bytesmemory _operatorData
)
internal{
revert("Burning functionality is disabled.");
}
}
Contract Source Code
File 9 of 16: IERC20.sol
pragmasolidity ^0.5.0;/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see {ERC20Detailed}.
*/interfaceIERC20{
/**
* @dev Returns the amount of tokens in existence.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/functionbalanceOf(address account) externalviewreturns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransfer(address recipient, uint256 amount) externalreturns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/functionallowance(address owner, address spender) externalviewreturns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: 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
*
* Emits an {Approval} event.
*/functionapprove(address spender, uint256 amount) externalreturns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransferFrom(address sender, address recipient, uint256 amount) externalreturns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/eventApproval(addressindexed owner, addressindexed spender, uint256 value);
}
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This code has not been reviewed.
* Do not use or deploy this code before reviewing it personally first.
*/// solhint-disable-next-line compiler-fixedpragmasolidity 0.5.8;interfaceIERC777{
functionname() externalviewreturns (stringmemory);
functionsymbol() externalviewreturns (stringmemory);
functiontotalSupply() externalviewreturns (uint256);
functionbalanceOf(address owner) externalviewreturns (uint256);
functiongranularity() externalviewreturns (uint256);
functiondefaultOperators() externalviewreturns (address[] memory);
functionisOperatorFor(address operator, address tokenHolder) externalviewreturns (bool);
functionauthorizeOperator(address operator) external;
functionrevokeOperator(address operator) external;
functionsend(address to, uint256 amount, bytescalldata data) external;
functionoperatorSend(addressfrom,
address to,
uint256 amount,
bytescalldata data,
bytescalldata operatorData
) external;
functionburn(uint256 amount, bytescalldata data) external;
functionoperatorBurn(addressfrom, uint256 amount, bytescalldata data, bytescalldata operatorData) external;
eventSent(addressindexed operator,
addressindexedfrom,
addressindexed to,
uint256 amount,
bytes data,
bytes operatorData
);
eventMinted(addressindexed operator, addressindexed to, uint256 amount, bytes data, bytes operatorData);
eventBurned(addressindexed operator, addressindexedfrom, uint256 amount, bytes data, bytes operatorData);
eventAuthorizedOperator(addressindexed operator, addressindexed tokenHolder);
eventRevokedOperator(addressindexed operator, addressindexed tokenHolder);
}
Contract Source Code
File 12 of 16: IERC777TokensRecipient.sol
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This code has not been reviewed.
* Do not use or deploy this code before reviewing it personally first.
*/// solhint-disable-next-line compiler-fixedpragmasolidity 0.5.8;interfaceIERC777TokensRecipient{
functiontokensReceived(address operator,
addressfrom,
address to,
uint256 amount,
bytescalldata data,
bytescalldata operatorData
) external;
}
Contract Source Code
File 13 of 16: IERC777TokensSender.sol
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This code has not been reviewed.
* Do not use or deploy this code before reviewing it personally first.
*/// solhint-disable-next-line compiler-fixedpragmasolidity 0.5.8;interfaceIERC777TokensSender{
functiontokensToSend(address operator,
addressfrom,
address to,
uint amount,
bytescalldata data,
bytescalldata operatorData
) external;
}
Contract Source Code
File 14 of 16: Ownable.sol
pragmasolidity ^0.5.0;import"./Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/contractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/constructor () internal{
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewreturns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Returns true if the caller is the current owner.
*/functionisOwner() publicviewreturns (bool) {
return _msgSender() == _owner;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/functionrenounceOwnership() publiconlyOwner{
emit OwnershipTransferred(_owner, address(0));
_owner =address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publiconlyOwner{
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/function_transferOwnership(address newOwner) internal{
require(newOwner !=address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
Contract Source Code
File 15 of 16: SafeGuard.sol
pragmasolidity 0.5.8;import"./Ownable.sol";
/**
* @title Safe Guard Contract
* @author Panos
*/contractSafeGuardisOwnable{
eventTransaction(addressindexed destination, uint value, bytes data);
/**
* @dev Allows owner to execute a transaction.
*/functionexecuteTransaction(address destination, uint value, bytesmemory data)
publiconlyOwner{
require(externalCall(destination, value, data.length, data));
emit Transaction(destination, value, data);
}
/**
* @dev call has been separated into its own function in order to take advantage
* of the Solidity's code generator to produce a loop that copies tx.data into memory.
*/functionexternalCall(address destination, uint value, uint dataLength, bytesmemory data)
privatereturns (bool) {
bool result;
assembly { // solhint-disable-line no-inline-assemblylet x :=mload(0x40) // "Allocate" memory for output// (0x40 is where "free memory" pointer is stored by convention)let d :=add(data, 32) // First 32 bytes are the padded length of data, so exclude that
result :=call(
sub(gas, 34710), // 34710 is the value that solidity is currently emitting// It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) +// callNewAccountGas (25000, in case the destination address does not exist and needs creating)
destination,
value,
d,
dataLength, // Size of the input (in bytes) - this is what fixes the padding problem
x,
0// Output is ignored, therefore the output size is zero
)
}
return result;
}
}
Contract Source Code
File 16 of 16: SafeMath.sol
pragmasolidity ^0.5.0;/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/librarySafeMath{
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/functionadd(uint256 a, uint256 b) internalpurereturns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/functionsub(uint256 a, uint256 b) internalpurereturns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* NOTE: This is a feature of the next version of OpenZeppelin Contracts.
* @dev Get it via `npm install @openzeppelin/contracts@next`.
*/functionsub(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/functionmul(uint256 a, uint256 b) internalpurereturns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the// benefit is lost if 'b' is also tested.// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522if (a ==0) {
return0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/functiondiv(uint256 a, uint256 b) internalpurereturns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
* NOTE: This is a feature of the next version of OpenZeppelin Contracts.
* @dev Get it via `npm install @openzeppelin/contracts@next`.
*/functiondiv(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
// Solidity only automatically asserts when dividing by 0require(b >0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't holdreturn c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/functionmod(uint256 a, uint256 b) internalpurereturns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* NOTE: This is a feature of the next version of OpenZeppelin Contracts.
* @dev Get it via `npm install @openzeppelin/contracts@next`.
*/functionmod(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
require(b !=0, errorMessage);
return a % b;
}
}