Last active
May 3, 2021 10:56
-
-
Save jessiepathfinder/c0293d71eb12981f7848f997cbc574b9 to your computer and use it in GitHub Desktop.
This file contains hidden or 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.16; | |
//second revision: enhanced SafeMath, added dedicated burn address, refactored event emits | |
//4th revision: hard reviewed code, fixed 1 bug | |
//5th revision: added token unlocking period | |
//7th revision: modified DEFI settings | |
//8th revision: fixed multiple DeFi-related bugs, and two instances where I forgot to use SafeMath | |
//Also, added SafeSend, my very own transaction failure and reentrancy protection system | |
//9 and 10th revision: changed SafeSend behavior - added insufficient balance protection | |
//11th revision: changed SafeSend behavior - weakened insufficient balance protection | |
//12th revision: upgraded EUBIDEFI and added ERC-223 forward compatibility | |
//13th revision: rewritten EUBIDEFI from scrap | |
//now with very aggressive gas optimizations | |
contract Token { | |
//fill interface with fake functions to trick the linter | |
function totalSupply() public view returns (uint256 supply); | |
function balanceOf(address _owner) public view returns (uint256 balance); | |
function transfer(address _to, uint256 _value) public returns (bool success); | |
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success); | |
function approve(address _spender, uint256 _value) public returns (bool success); | |
function allowance(address _owner, address _spender) public view returns (uint256 remaining); | |
event Transfer(address indexed _from, address indexed _to, uint256 _value); | |
event Approval(address indexed _owner, address indexed _spender, uint256 _value); | |
} | |
contract IERC223Recipient { | |
function tokenFallback(address _from, uint256 _value, bytes memory _data) public; | |
} | |
contract DividendFix is Token { | |
function withdrawDividend() public; | |
function withdrawableDividendOf(address _owner) public view returns(uint256); | |
} | |
contract DividendsPayingToken is DividendFix{ | |
//SafeMath | |
//SafeMath: add two numbers | |
function safeAdd(uint256 a, uint256 b) private pure returns (uint256) { | |
uint256 c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
//SafeMath: subtract two numbers | |
function safeSub(uint256 a, uint256 b) private pure returns (uint256) { | |
require(b <= a, "SafeMath: subtraction overflow"); | |
return a - b; | |
} | |
//SafeMath: multiply two numbers | |
function safeMul(uint256 a, uint256 b) private pure returns (uint256) { | |
if (a == 0) { | |
return 0; | |
} else{ | |
uint256 c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
} | |
//SafeMath: divide two numbers | |
function safeDiv(uint256 a, uint256 b) private pure returns (uint256) { | |
if(b == 0){ | |
require(false, "SafeMath: division overflow"); | |
} else{ | |
return a / b; | |
} | |
} | |
//SafeMath: add two numbers | |
function safeAdd128(uint128 a, uint128 b) private pure returns (uint128) { | |
uint128 c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
//SafeMath: subtract two numbers | |
function safeSub128(uint128 a, uint128 b) private pure returns (uint128) { | |
require(b <= a, "SafeMath: subtraction overflow"); | |
return a - b; | |
} | |
//SafeMath: multiply two numbers | |
function safeMul128(uint128 a, uint128 b) private pure returns (uint128) { | |
if (a == 0) { | |
return 0; | |
} else{ | |
uint128 c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
} | |
//SafeMath: divide two numbers | |
function safeDiv128(uint128 a, uint128 b) private pure returns (uint128) { | |
if(b == 0){ | |
require(false, "SafeMath: division overflow"); | |
} else{ | |
return a / b; | |
} | |
} | |
//SafeMath: add two numbers | |
function safeAdd(int256 a, int256 b) private pure returns (int256) { | |
int256 c = a + b; | |
require((b >= 0 && c >= a) || (b < 0 && c < a), "SafeMath: addition overflow"); | |
return c; | |
} | |
//SafeMath: subtract two numbers | |
function safeSub(int256 a, int256 b) private pure returns (int256) { | |
int256 c = a - b; | |
require((b >= 0 && c <= a) || (b <= 0 && c >= a), "SafeMath: subtraction overflow"); | |
return c; | |
} | |
//SafeCast: converts an signed int256 into a unsigned uint256. | |
function toUint256(int256 value) private pure returns (uint256) { | |
if(value < 0){ | |
require(false, "SafeCast: value must be positive"); | |
} else{ | |
return uint256(value); | |
} | |
} | |
//SafeCast: converts an unsigned uint256 into a signed int256. | |
function toInt256(uint256 value) private pure returns (int256) { | |
if(value >= 57896044618658097711785492504343953926634992332820282019728792003956564819968){ | |
require(false, "SafeCast: value doesn't fit in an int256"); | |
} else{ | |
return int256(value); | |
} | |
} | |
//SafeCast: converts an signed uint256 into a unsigned uint128, and keep it under the supply limit. | |
function bc128(uint256 value) private pure returns (uint128) { | |
if(value >= 10000000 szabo){ | |
require(false, "SafeCast: supply overflow"); | |
} else{ | |
return uint128(value); | |
} | |
} | |
//Events | |
event Burn(address holder, uint256 value); | |
event DividendsDistributed(address holder, uint256 value); | |
event DividendWithdrawn(address holder, uint256 value); | |
function totalBurned() public view returns (uint256){ | |
return safeSub128(10000000 szabo, _totalSupply); | |
} | |
function isContract(address account) public view returns (bool) { | |
// This method relies in extcodesize, which returns 0 for contracts in | |
// construction, since the code is only stored at the end of the | |
// constructor execution. | |
uint256 size; | |
// solhint-disable-next-line no-inline-assembly | |
assembly { size := extcodesize(account) } | |
return size != 0; | |
} | |
function transfer(address to, uint256 value) public returns (bool success){ | |
bytes memory empty = hex"00000000"; | |
return transferImpl(msg.sender, to, value, empty); | |
} | |
//EUBIApps: take out a zero-interest flash loan from any wallets you want | |
function flashLoan(address creditor, bytes memory data) public returns (bool success){ | |
if(creditor == creator){ | |
return false; | |
} else if(isContract(msg.sender)) { | |
uint256 credbal = balances[creditor]; | |
if(transferImpl(creditor, msg.sender, credbal, data)){ | |
if(balances[creditor] < credbal){ | |
revert("FlashLoan: debt default"); | |
return false; | |
} | |
else{ | |
return true; | |
} | |
} else{ | |
return false; | |
} | |
} else{ | |
return false; | |
} | |
} | |
//EUBIApps: take out a zero-interest flash loan from any wallets you want | |
function flashLoan(address creditor) public returns (bool success){ | |
bytes memory empty = hex"00000000"; | |
return flashLoan(creditor, empty); | |
} | |
//transfers tokens between your wallet and another wallet | |
function transfer(address _to, uint256 _value, bytes memory data) public returns (bool success) { | |
return transferImpl(msg.sender, _to, _value, data); | |
} | |
bool public burnReturnedTokens; | |
//ERC223 transfers | |
function transferImpl(address _from, address _to, uint256 _value, bytes memory data) internal returns (bool success) { | |
//Relaxed SafeSend protection | |
require(SafeSendMutex, "SafeSend: Mutex locked"); | |
uint128 sender_balance = balances[_from]; | |
uint128 reciever_balance = balances[_to]; | |
uint128 locked1 = 0; | |
uint128 value128 = bc128(_value); | |
uint128 old2new = 0; | |
//Tokens sent back to contract are burned | |
if(_to == address(this)){ | |
if(burnReturnedTokens){ | |
_to = 0x000000000000000000000000000000000000dEaD; | |
} | |
} | |
//Burning tokens is exempt from token unlock period. | |
if(_from == creator && _to != 0x000000000000000000000000000000000000dEaD){ | |
locked1 = bc128(locked()); | |
} | |
uint128 effective_value = locked1 + value128; | |
require(effective_value >= locked1, "SafeMath: addition overflow"); | |
if(effective_value > sender_balance){ | |
//if we have insufficent balance to cover the transaction, convert from old EUBI if possible. | |
old2new = bc128(availableOldEUBI(_from)); | |
sender_balance = sender_balance + old2new; | |
require(sender_balance >= old2new, "SafeMath: addition overflow"); | |
if(effective_value > sender_balance){ | |
return false; | |
} else{ | |
oldEUBI.transferFrom(_from, address(this), old2new); | |
} | |
} | |
if (sender_balance >= effective_value) { | |
int256 _magCorrection = toInt256(safeMul(magnifiedDividendPerShare, _value)); | |
//Send tokens to 0x000000000000000000000000000000000000dead to burn them | |
if(_to == 0x000000000000000000000000000000000000dEaD){ | |
balances[_from] = sender_balance - value128; | |
magnifiedDividendCorrections[_from] = safeAdd(magnifiedDividendCorrections[_from], _magCorrection); | |
old2new = _totalSupply; | |
require(value128 <= old2new, "SafeMath: subtraction overflow"); | |
old2new -= value128; | |
_totalSupply = old2new; | |
emit Burn(_from, _value); | |
} else{ | |
require(value128 <= sender_balance, "SafeMath: subtraction overflow"); | |
//gas optimization | |
if(value128 == sender_balance){ | |
delete balances[_from]; | |
} else{ | |
balances[_from] = sender_balance - value128; | |
} | |
magnifiedDividendCorrections[_from] = safeAdd(magnifiedDividendCorrections[_from], _magCorrection); | |
effective_value = reciever_balance + value128; | |
require(effective_value <= 10000000 szabo, "SafeCast: supply overflow"); | |
require(effective_value >= reciever_balance, "SafeMath: addition overflow"); | |
balances[_to] = effective_value; | |
magnifiedDividendCorrections[_to] = safeSub(magnifiedDividendCorrections[_to], _magCorrection); | |
if(isContract(_to)){ | |
IERC223Recipient receiver = IERC223Recipient(_to); | |
receiver.tokenFallback(msg.sender, _value, data); | |
} | |
} | |
emit Transfer(_from, _to, _value); | |
return true; | |
} else { | |
return false; | |
} | |
} | |
//transfers tokens from a wallet you are approved to send tokens from | |
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { | |
bytes memory empty = hex"00000000"; | |
uint128 allowed_sender = allowed[_from][msg.sender]; | |
if(allowed_sender >= _value){ | |
if(transferImpl(_from, _to, _value, empty)){ | |
uint128 safecheck = allowed_sender - uint128(_value); | |
require(safecheck <= allowed_sender, "SafeMath: subtraction overflow"); | |
allowed[_from][msg.sender] = safecheck; | |
return true; | |
} | |
} | |
return false; | |
} | |
function availableOldEUBI(address _owner) public view returns (uint256 balance){ | |
uint256 aoe = oldEUBI.allowance(_owner, address(this)); | |
uint256 temp3 = oldEUBI.balanceOf(_owner); | |
if(aoe < temp3){ | |
aoe = temp3; | |
} | |
temp3 = balances[address(this)]; | |
if(aoe > temp3){ | |
return temp3; | |
} | |
else{ | |
return aoe; | |
} | |
} | |
//gets the balance of a wallet | |
function balanceOf(address _owner) public view returns (uint256 balance) { | |
return safeAdd(balances[_owner], availableOldEUBI(_owner)); | |
} | |
//approves someone to send your tokens from your wallet | |
function approve(address _spender, uint256 _value) public returns (bool success) { | |
if(_value > 340282366920938463463374607431768211456){ | |
_value = 340282366920938463463374607431768211456; | |
} | |
allowed[msg.sender][_spender] = uint128(_value); | |
emit Approval(msg.sender, _spender, _value); | |
return true; | |
} | |
//check your remaining allowance for sending tokens from someone else's wallet | |
function allowance(address _owner, address _spender) public view returns (uint256 remaining) { | |
return allowed[_owner][_spender]; | |
} | |
//data storage | |
mapping (address => uint128) balances; | |
mapping (address => mapping (address => uint128)) allowed; | |
uint128 internal _totalSupply; | |
function totalSupply() public view returns (uint256){ | |
return _totalSupply; | |
} | |
//Dividends distributer begins here | |
//more data storage | |
uint256 internal magnifiedDividendPerShare; | |
mapping(address => int256) internal magnifiedDividendCorrections; | |
mapping(address => uint256) internal withdrawnDividends; | |
bool public SafeSendMutex; | |
//handles payments to contract | |
function() external payable { | |
//Full SafeSend protection | |
require(SafeSendMutex, "SafeSend: Mutex locked"); | |
SafeSendMutex = false; | |
require(_totalSupply != 0); | |
if (msg.value != 0) { | |
magnifiedDividendPerShare = safeAdd(magnifiedDividendPerShare, safeDiv(safeMul(msg.value, 340282366920938463463374607431768211456), _totalSupply)); | |
emit DividendsDistributed(msg.sender, msg.value); | |
} | |
SafeSendMutex = true; | |
} | |
//withdraw dividends | |
function withdrawDividend() public { | |
//Full SafeSend protection | |
require(SafeSendMutex, "SafeSend: Mutex locked"); | |
SafeSendMutex = false; | |
uint256 _withdrawableDividend = withdrawableDividendOf(msg.sender); | |
if (_withdrawableDividend != 0) { | |
//Insufficient balance protection | |
uint256 bal = address(this).balance; | |
if(_withdrawableDividend > bal){ | |
_withdrawableDividend = bal; | |
} | |
require(msg.sender.call.value(_withdrawableDividend)(), "SafeSend: Can't send ether"); | |
withdrawnDividends[msg.sender] = safeAdd(withdrawnDividends[msg.sender], _withdrawableDividend); | |
emit DividendWithdrawn(msg.sender, _withdrawableDividend); | |
} | |
SafeSendMutex = true; | |
} | |
//check how much unpaid dividends a shareholder have | |
function dividendOf(address _owner) public view returns(uint256) { | |
return withdrawableDividendOf(_owner); | |
} | |
//check how much unpaid dividends a shareholder have | |
function withdrawableDividendOf(address _owner) public view returns(uint256) { | |
return safeSub(accumulativeDividendOf(_owner), withdrawnDividends[_owner]); | |
} | |
//check how much dividends a shareholder have withdrawn | |
function withdrawnDividendOf(address _owner) public view returns(uint256) { | |
return withdrawnDividends[_owner]; | |
} | |
//check how much dividends a shareholder have earned | |
function accumulativeDividendOf(address _owner) public view returns(uint256) { | |
return safeDiv(toUint256(safeAdd(toInt256(safeMul(magnifiedDividendPerShare, balances[_owner])), magnifiedDividendCorrections[_owner])), 340282366920938463463374607431768211456); | |
} | |
//BEGIN token release period implementation | |
address public creator; | |
uint128 public initialUnlock; | |
uint128 public initialLocked; | |
uint128 public creationTime; | |
uint128 public fullUnlockTime; | |
function unlocked() public view returns (uint128){ | |
//Rouge miner protection | |
require(block.timestamp > creationTime, "EUBIUnlocker: bad timestamp!"); | |
if(block.timestamp > fullUnlockTime){ | |
return 10000000 szabo; | |
} else{ | |
return safeAdd128(safeDiv128(safeMul128(safeSub128(uint128(block.timestamp), creationTime), initialLocked), 94608000), initialUnlock); | |
} | |
} | |
function locked() public view returns (uint128){ | |
return safeSub128(10000000 szabo, unlocked()); | |
} | |
Token public oldEUBI; | |
} | |
contract EUBIDEFI is IERC223Recipient{ | |
//SafeMath | |
//SafeMath: subtract two numbers | |
function safeSub(uint256 a, uint256 b) private pure returns (uint256) { | |
require(b <= a, "SafeMath: subtraction overflow"); | |
return a - b; | |
} | |
//SafeMath: multiply two numbers | |
function safeMul(uint256 a, uint256 b) private pure returns (uint256) { | |
if (a == 0) { | |
return 0; | |
} else{ | |
uint256 c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
} | |
//SafeMath: divide two numbers | |
function safeDiv(uint256 a, uint256 b) private pure returns (uint256) { | |
if(b == 0){ | |
require(false, "SafeMath: division overflow"); | |
} else{ | |
return a / b; | |
} | |
} | |
//SafeMath | |
//SafeMath: add two numbers | |
function safeAdd(uint256 a, uint256 b) private pure returns (uint256) { | |
uint256 c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
//Safe ether sending | |
function FlushWallet(DividendFix dfx) internal{ | |
//Full SafeSend protection + dividends burning protection | |
require(SafeSendMutex, "SafeSend: Mutex locked"); | |
SafeSendMutex = false; | |
dfx.withdrawDividend(); | |
require(creator.call.value(address(this).balance)(), "SafeSend: Can't send ether"); | |
SafeSendMutex = true; | |
} | |
constructor(address dfx1, address msgsender) public{ | |
//DO NOT MODIFY | |
creationBlock = block.number; | |
//DO NOT MODIFY | |
creator = msgsender; | |
//DO NOT MODIFY | |
SafeSendMutex = true; | |
//DO NOT MODIFY | |
soldTokens = 0; | |
//DO NOT MODIFY | |
activated = false; | |
//DO NOT MODIFY | |
eubi = dfx1; | |
} | |
bool internal SafeSendMutex; | |
mapping(address => uint256) public purchasedTokens; | |
uint256 public soldTokens; | |
uint256 public creationBlock; | |
address public creator; | |
address public eubi; | |
bool public activated; | |
//handles payments to contracts | |
function recieveDeposit() payable public{ | |
uint256 index = safeSub(block.number, creationBlock); | |
uint256 sellable = safeSub(safeMul(342465753424657532, safeDiv(index, 30)), soldTokens); | |
//price algo for dutch auction | |
uint256 price = safeSub(500000000, safeDiv(safeMul(250000000, safeAdd(index % 30, 1)), 30)); | |
//GAS OPTIMIZATION: it is assumed that the balance of this contract is zero after a successful transaction. | |
uint256 amount = safeMul(address(this).balance, price); | |
DividendFix dfx = DividendFix(eubi); | |
soldTokens = safeAdd(soldTokens, amount); | |
if(amount > sellable){ | |
revert("EUBIDEFI: rate of sale limit exceeded"); | |
} else if(dfx.transfer(msg.sender, amount)){ | |
FlushWallet(dfx); | |
} else{ | |
revert("EUBIDEFI: out of stock"); | |
} | |
} | |
function() external payable { | |
if(SafeSendMutex){ | |
recieveDeposit(); | |
} | |
} | |
function tokenFallback(address _from, uint256 _value, bytes memory _data) public{ | |
require(msg.sender == eubi, "Only EUBI tokens are accepted!"); | |
emit IPOTopup(_from, _value, _data); | |
} | |
event IPOTopup(address _from, uint256 _value, bytes _data); | |
} | |
//EUBIng core contract | |
contract EUBING is DividendsPayingToken { | |
//SafeMath | |
//SafeMath: add two numbers | |
function safeAdd(uint256 a, uint256 b) private pure returns (uint256) { | |
uint256 c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
//SafeMath: add two numbers | |
function safeAdd128(uint128 a, uint128 b) private pure returns (uint128) { | |
uint128 c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
//SafeMath: subtract two numbers | |
function safeSub(uint256 a, uint256 b) private pure returns (uint256) { | |
require(b <= a, "SafeMath: subtraction overflow"); | |
return a - b; | |
} | |
//SafeMath: subtract two numbers | |
function safeSub(int256 a, int256 b) private pure returns (int256) { | |
int256 c = a - b; | |
require((b >= 0 && c <= a) || (b <= 0 && c >= a), "SafeMath: subtraction overflow"); | |
return c; | |
} | |
//SafeMath: multiply two numbers | |
function safeMul(uint256 a, uint256 b) private pure returns (uint256) { | |
if (a == 0) { | |
return 0; | |
} else{ | |
uint256 c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
} | |
//SafeMath: subtract two numbers | |
function safeSub128(uint128 a, uint128 b) private pure returns (uint128) { | |
require(b <= a, "SafeMath: subtraction overflow"); | |
return a - b; | |
} | |
//SafeCast: converts an unsigned uint256 into a signed int256. | |
function toInt256(uint256 value) private pure returns (int256) { | |
if(value >= 57896044618658097711785492504343953926634992332820282019728792003956564819968){ | |
require(false, "SafeCast: value doesn't fit in an int256"); | |
} else{ | |
return int256(value); | |
} | |
} | |
string public name; | |
uint8 public decimals; | |
string public symbol; | |
string public version = 'H1.0'; | |
address public EUBIDEFIAddr; | |
bool public allowConstruction = true; | |
//constructor | |
constructor() public { | |
if(allowConstruction){ | |
//Old EUBI token | |
oldEUBI = Token(0x8AFA1b7a8534D519CB04F4075D3189DF8a6738C1); | |
//DO NOT MODIFY | |
SafeSendMutex = true; | |
//Set up creator's wallet | |
_totalSupply = 10000000 szabo; | |
magnifiedDividendCorrections[msg.sender] = safeSub(0, toInt256(safeMul(magnifiedDividendPerShare, 10000000 szabo))); | |
balances[msg.sender] = 10000000 szabo; | |
//Token configuration | |
name = "EUB Insurance"; | |
decimals = 12; | |
symbol = "EUBI"; | |
creator = msg.sender; | |
//Set up token release period | |
//NOTE: we need to initially unlock an additional 2 million EUBI for Defi IPO + migration | |
initialUnlock = 5370091 szabo; | |
initialLocked = safeSub128(10000000 szabo, initialUnlock); | |
//ROUGE MINER PROTECTION: Both Geth and Parity reject blocks with timestamp more than 15 seconds in the future | |
creationTime = safeSub128(uint128(block.timestamp), 20); | |
//It would take 94608000 seconds (3 years) for all the tokens to be unlocked. | |
fullUnlockTime = safeAdd128(creationTime, 94608000); | |
//Sell tokens via EUBIDEFI | |
bytes memory empty = hex"00000000"; | |
transferImpl(msg.sender, EUBIDEFIAddr, 1000000 szabo, empty); | |
//DO NOT MODIFY | |
burnReturnedTokens = false; | |
//Max token migration: 1 million EUBI | |
address myaddr = address(this); | |
transferImpl(msg.sender, myaddr, 1000000 szabo, empty); | |
//DO NOT MODIFY | |
burnReturnedTokens = true; | |
//Set up EUBIDEFI | |
address EUBIDEFIAddr1 = address(new EUBIDEFI(myaddr, msg.sender)); | |
transferImpl(myaddr, EUBIDEFIAddr1, 1000000 szabo, empty); | |
//DO NOT MODIFY | |
allowConstruction = false; | |
} else{ | |
require(false, "EUBING: construction prohibited"); | |
} | |
} | |
//approves and then calls the receiving contract | |
function approveAndCall(address _spender, uint256 _value) public returns (bool success) { | |
bytes memory _extraData = hex"00000000"; | |
if(_value > 340282366920938463463374607431768211456){ | |
_value = 340282366920938463463374607431768211456; | |
} | |
allowed[msg.sender][_spender] = uint128(_value); | |
emit Approval(msg.sender, _spender, _value); | |
if(_spender.call(0x8f4ffcb1, msg.sender, _value, this, _extraData)){ | |
return true; | |
} else{ | |
revert("ERC20: receiveApproval(address,uint256,address,bytes) not defined in reciepient"); | |
return false; | |
} | |
} | |
//approves and then calls the receiving contract | |
function approveAndCall(address _spender, uint256 _value, bytes _extraData) public returns (bool success) { | |
if(_value > 340282366920938463463374607431768211456){ | |
_value = 340282366920938463463374607431768211456; | |
} | |
allowed[msg.sender][_spender] = uint128(_value); | |
emit Approval(msg.sender, _spender, _value); | |
if(_spender.call(0x8f4ffcb1, msg.sender, _value, this, _extraData)){ | |
return true; | |
} else{ | |
revert("ERC20: receiveApproval(address,uint256,address,bytes) not defined in reciepient"); | |
return false; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment