Created
January 28, 2021 18:39
-
-
Save shahzaintariq/532aa2d9aca985be77902876c95601b7 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.4.25+commit.59dbf8f1.js&optimize=false&runs=200&gist=
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
/** | |
*Submitted for verification at Etherscan.io on 2020-04-28 | |
*/ | |
// BUILT FOR FREE ON https://vittominacori.github.io/erc20-generator | |
// File: @openzeppelin/contracts/GSN/Context.sol | |
pragma solidity ^0.6.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. | |
*/ | |
contract Context { | |
// Empty internal constructor, to prevent people from mistakenly deploying | |
// an instance of this contract, which should be used via inheritance. | |
constructor () internal { } | |
function _msgSender() internal view virtual returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view virtual returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Interface of the ERC20 standard as defined in the EIP. | |
*/ | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
// File: @openzeppelin/contracts/math/SafeMath.sol | |
pragma solidity ^0.6.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. | |
*/ | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
// Solidity only automatically asserts when dividing by 0 | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
// File: @openzeppelin/contracts/utils/Address.sol | |
pragma solidity ^0.6.2; | |
/** | |
* @dev Collection of functions related to the address type | |
*/ | |
library Address { | |
/** | |
* @dev Returns true if `account` is a contract. | |
* | |
* [IMPORTANT] | |
* ==== | |
* It is unsafe to assume that an address for which this function returns | |
* false is an externally-owned account (EOA) and not a contract. | |
* | |
* Among others, `isContract` will return false for the following | |
* types of addresses: | |
* | |
* - an externally-owned account | |
* - a contract in construction | |
* - an address where a contract will be created | |
* - an address where a contract lived, but was destroyed | |
* ==== | |
*/ | |
function isContract(address account) internal view returns (bool) { | |
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts | |
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned | |
// for accounts without code, i.e. `keccak256('')` | |
bytes32 codehash; | |
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; | |
// solhint-disable-next-line no-inline-assembly | |
assembly { codehash := extcodehash(account) } | |
return (codehash != accountHash && codehash != 0x0); | |
} | |
/** | |
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to | |
* `recipient`, forwarding all available gas and reverting on errors. | |
* | |
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost | |
* of certain opcodes, possibly making contracts go over the 2300 gas limit | |
* imposed by `transfer`, making them unable to receive funds via | |
* `transfer`. {sendValue} removes this limitation. | |
* | |
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. | |
* | |
* IMPORTANT: because control is transferred to `recipient`, care must be | |
* taken to not create reentrancy vulnerabilities. Consider using | |
* {ReentrancyGuard} or the | |
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. | |
*/ | |
function sendValue(address payable recipient, uint256 amount) internal { | |
require(address(this).balance >= amount, "Address: insufficient balance"); | |
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value | |
(bool success, ) = recipient.call{ value: amount }(""); | |
require(success, "Address: unable to send value, recipient may have reverted"); | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/ERC20.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Implementation of the {IERC20} interface. | |
* | |
* This implementation is agnostic to the way tokens are created. This means | |
* that a supply mechanism has to be added in a derived contract using {_mint}. | |
* For a generic mechanism see {ERC20MinterPauser}. | |
* | |
* TIP: For a detailed writeup see our guide | |
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How | |
* to implement supply mechanisms]. | |
* | |
* We have followed general OpenZeppelin guidelines: functions revert instead | |
* of returning `false` on failure. This behavior is nonetheless conventional | |
* and does not conflict with the expectations of ERC20 applications. | |
* | |
* Additionally, an {Approval} event is emitted on calls to {transferFrom}. | |
* This allows applications to reconstruct the allowance for all accounts just | |
* by listening to said events. Other implementations of the EIP may not emit | |
* these events, as it isn't required by the specification. | |
* | |
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance} | |
* functions have been added to mitigate the well-known issues around setting | |
* allowances. See {IERC20-approve}. | |
*/ | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint256; | |
using Address for address; | |
mapping (address => uint256) private _balances; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
uint256 private _totalSupply; | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
/** | |
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with | |
* a default value of 18. | |
* | |
* To select a different value for {decimals}, use {_setupDecimals}. | |
* | |
* All three of these values are immutable: they can only be set once during | |
* construction. | |
*/ | |
constructor (string memory name, string memory symbol) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = 18; | |
} | |
/** | |
* @dev Returns the name of the token. | |
*/ | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev Returns the symbol of the token, usually a shorter version of the | |
* name. | |
*/ | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns the number of decimals used to get its user representation. | |
* For example, if `decimals` equals `2`, a balance of `505` tokens should | |
* be displayed to a user as `5,05` (`505 / 10 ** 2`). | |
* | |
* Tokens usually opt for a value of 18, imitating the relationship between | |
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is | |
* called. | |
* | |
* NOTE: This information is only used for _display_ purposes: it in | |
* no way affects any of the arithmetic of the contract, including | |
* {IERC20-balanceOf} and {IERC20-transfer}. | |
*/ | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
/** | |
* @dev See {IERC20-totalSupply}. | |
*/ | |
function totalSupply() public view override returns (uint256) { | |
return _totalSupply; | |
} | |
/** | |
* @dev See {IERC20-balanceOf}. | |
*/ | |
function balanceOf(address account) public view override returns (uint256) { | |
return _balances[account]; | |
} | |
/** | |
* @dev See {IERC20-transfer}. | |
* | |
* Requirements: | |
* | |
* - `recipient` cannot be the zero address. | |
* - the caller must have a balance of at least `amount`. | |
*/ | |
function transfer(address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-allowance}. | |
*/ | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
/** | |
* @dev See {IERC20-approve}. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function approve(address spender, uint256 amount) public virtual override returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-transferFrom}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. This is not | |
* required by the EIP. See the note at the beginning of {ERC20}; | |
* | |
* Requirements: | |
* - `sender` and `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
* - the caller must have allowance for ``sender``'s tokens of at least | |
* `amount`. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/** | |
* @dev Atomically increases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
/** | |
* @dev Atomically decreases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
* - `spender` must have allowance for the caller of at least | |
* `subtractedValue`. | |
*/ | |
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* @dev Moves tokens `amount` from `sender` to `recipient`. | |
* | |
* This is internal function is equivalent to {transfer}, and can be used to | |
* e.g. implement automatic token fees, slashing mechanisms, etc. | |
* | |
* Emits a {Transfer} event. | |
* | |
* Requirements: | |
* | |
* - `sender` cannot be the zero address. | |
* - `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
*/ | |
function _transfer(address sender, address recipient, uint256 amount) internal virtual { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
require(recipient != address(0), "ERC20: transfer to the zero address"); | |
_beforeTokenTransfer(sender, recipient, amount); | |
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
/** @dev Creates `amount` tokens and assigns them to `account`, increasing | |
* the total supply. | |
* | |
* Emits a {Transfer} event with `from` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `to` cannot be the zero address. | |
*/ | |
function _mint(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: mint to the zero address"); | |
_beforeTokenTransfer(address(0), account, amount); | |
_totalSupply = _totalSupply.add(amount); | |
_balances[account] = _balances[account].add(amount); | |
emit Transfer(address(0), account, amount); | |
} | |
/** | |
* @dev Destroys `amount` tokens from `account`, reducing the | |
* total supply. | |
* | |
* Emits a {Transfer} event with `to` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `account` cannot be the zero address. | |
* - `account` must have at least `amount` tokens. | |
*/ | |
function _burn(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: burn from the zero address"); | |
_beforeTokenTransfer(account, address(0), amount); | |
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); | |
_totalSupply = _totalSupply.sub(amount); | |
emit Transfer(account, address(0), amount); | |
} | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. | |
* | |
* This is internal function is equivalent to `approve`, and can be used to | |
* e.g. set automatic allowances for certain subsystems, etc. | |
* | |
* Emits an {Approval} event. | |
* | |
* Requirements: | |
* | |
* - `owner` cannot be the zero address. | |
* - `spender` cannot be the zero address. | |
*/ | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* @dev Sets {decimals} to a value other than the default one of 18. | |
* | |
* WARNING: This function should only be called from the constructor. Most | |
* applications that interact with token contracts will not expect | |
* {decimals} to ever change, and may work incorrectly if it does. | |
*/ | |
function _setupDecimals(uint8 decimals_) internal { | |
_decimals = decimals_; | |
} | |
/** | |
* @dev Hook that is called before any transfer of tokens. This includes | |
* minting and burning. | |
* | |
* Calling conditions: | |
* | |
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens | |
* will be to transferred to `to`. | |
* - when `from` is zero, `amount` tokens will be minted for `to`. | |
* - when `to` is zero, `amount` of ``from``'s tokens will be burned. | |
* - `from` and `to` are never both zero. | |
* | |
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } | |
} | |
// File: @openzeppelin/contracts/token/ERC20/ERC20Capped.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Extension of {ERC20} that adds a cap to the supply of tokens. | |
*/ | |
abstract contract ERC20Capped is ERC20 { | |
uint256 private _cap; | |
/** | |
* @dev Sets the value of the `cap`. This value is immutable, it can only be | |
* set once during construction. | |
*/ | |
constructor (uint256 cap) public { | |
require(cap > 0, "ERC20Capped: cap is 0"); | |
_cap = cap; | |
} | |
/** | |
* @dev Returns the cap on the token's total supply. | |
*/ | |
function cap() public view returns (uint256) { | |
return _cap; | |
} | |
/** | |
* @dev See {ERC20-_beforeTokenTransfer}. | |
* | |
* Requirements: | |
* | |
* - minted tokens must not cause the total supply to go over the cap. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override { | |
super._beforeTokenTransfer(from, to, amount); | |
if (from == address(0)) { // When minting tokens | |
require(totalSupply().add(amount) <= _cap, "ERC20Capped: cap exceeded"); | |
} | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/ERC20Burnable.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Extension of {ERC20} that allows token holders to destroy both their own | |
* tokens and those that they have an allowance for, in a way that can be | |
* recognized off-chain (via event analysis). | |
*/ | |
abstract contract ERC20Burnable is Context, ERC20 { | |
/** | |
* @dev Destroys `amount` tokens from the caller. | |
* | |
* See {ERC20-_burn}. | |
*/ | |
function burn(uint256 amount) public virtual { | |
_burn(_msgSender(), amount); | |
} | |
/** | |
* @dev Destroys `amount` tokens from `account`, deducting from the caller's | |
* allowance. | |
* | |
* See {ERC20-_burn} and {ERC20-allowance}. | |
* | |
* Requirements: | |
* | |
* - the caller must have allowance for ``accounts``'s tokens of at least | |
* `amount`. | |
*/ | |
function burnFrom(address account, uint256 amount) public virtual { | |
uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, "ERC20: burn amount exceeds allowance"); | |
_approve(account, _msgSender(), decreasedAllowance); | |
_burn(account, amount); | |
} | |
} | |
// File: @openzeppelin/contracts/introspection/IERC165.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Interface of the ERC165 standard, as defined in the | |
* https://eips.ethereum.org/EIPS/eip-165[EIP]. | |
* | |
* Implementers can declare support of contract interfaces, which can then be | |
* queried by others ({ERC165Checker}). | |
* | |
* For an implementation, see {ERC165}. | |
*/ | |
interface IERC165 { | |
/** | |
* @dev Returns true if this contract implements the interface defined by | |
* `interfaceId`. See the corresponding | |
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] | |
* to learn more about how these ids are created. | |
* | |
* This function call must use less than 30 000 gas. | |
*/ | |
function supportsInterface(bytes4 interfaceId) external view returns (bool); | |
} | |
// File: erc-payable-token/contracts/token/ERC1363/IERC1363.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @title IERC1363 Interface | |
* @author Vittorio Minacori (https://github.com/vittominacori) | |
* @dev Interface for a Payable Token contract as defined in | |
* https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1363.md | |
*/ | |
interface IERC1363 is IERC20, IERC165 { | |
/* | |
* Note: the ERC-165 identifier for this interface is 0x4bbee2df. | |
* 0x4bbee2df === | |
* bytes4(keccak256('transferAndCall(address,uint256)')) ^ | |
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ | |
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ | |
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) | |
*/ | |
/* | |
* Note: the ERC-165 identifier for this interface is 0xfb9ec8ce. | |
* 0xfb9ec8ce === | |
* bytes4(keccak256('approveAndCall(address,uint256)')) ^ | |
* bytes4(keccak256('approveAndCall(address,uint256,bytes)')) | |
*/ | |
/** | |
* @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver | |
* @param to address The address which you want to transfer to | |
* @param value uint256 The amount of tokens to be transferred | |
* @return true unless throwing | |
*/ | |
function transferAndCall(address to, uint256 value) external returns (bool); | |
/** | |
* @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver | |
* @param to address The address which you want to transfer to | |
* @param value uint256 The amount of tokens to be transferred | |
* @param data bytes Additional data with no specified format, sent in call to `to` | |
* @return true unless throwing | |
*/ | |
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); | |
/** | |
* @notice Transfer tokens from one address to another and then call `onTransferReceived` on receiver | |
* @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 | |
* @return true unless throwing | |
*/ | |
function transferFromAndCall(address from, address to, uint256 value) external returns (bool); | |
/** | |
* @notice Transfer tokens from one address to another and then call `onTransferReceived` on receiver | |
* @param from address The address which you want to send tokens from | |
* @param to address The address which you want to transfer to | |
* @param value uint256 The amount of tokens to be transferred | |
* @param data bytes Additional data with no specified format, sent in call to `to` | |
* @return true unless throwing | |
*/ | |
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); | |
/** | |
* @notice Approve the passed address to spend the specified amount of tokens on behalf of msg.sender | |
* and then call `onApprovalReceived` on spender. | |
* 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 address The address which will spend the funds | |
* @param value uint256 The amount of tokens to be spent | |
*/ | |
function approveAndCall(address spender, uint256 value) external returns (bool); | |
/** | |
* @notice Approve the passed address to spend the specified amount of tokens on behalf of msg.sender | |
* and then call `onApprovalReceived` on spender. | |
* 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 address The address which will spend the funds | |
* @param value uint256 The amount of tokens to be spent | |
* @param data bytes Additional data with no specified format, sent in call to `spender` | |
*/ | |
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); | |
} | |
// File: erc-payable-token/contracts/token/ERC1363/IERC1363Receiver.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @title IERC1363Receiver Interface | |
* @author Vittorio Minacori (https://github.com/vittominacori) | |
* @dev Interface for any contract that wants to support transferAndCall or transferFromAndCall | |
* from ERC1363 token contracts as defined in | |
* https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1363.md | |
*/ | |
interface IERC1363Receiver { | |
/* | |
* Note: the ERC-165 identifier for this interface is 0x88a7ca5c. | |
* 0x88a7ca5c === bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)")) | |
*/ | |
/** | |
* @notice Handle the receipt of ERC1363 tokens | |
* @dev Any ERC1363 smart contract calls this function on the recipient | |
* after a `transfer` or a `transferFrom`. This function MAY throw to revert and reject the | |
* transfer. Return of other than the magic value MUST result in the | |
* transaction being reverted. | |
* Note: the token contract address is always the message sender. | |
* @param operator address The address which called `transferAndCall` or `transferFromAndCall` function | |
* @param from address The address which are token transferred from | |
* @param value uint256 The amount of tokens transferred | |
* @param data bytes Additional data with no specified format | |
* @return `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))` | |
* unless throwing | |
*/ | |
function onTransferReceived(address operator, address from, uint256 value, bytes calldata data) external returns (bytes4); // solhint-disable-line max-line-length | |
} | |
// File: erc-payable-token/contracts/token/ERC1363/IERC1363Spender.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @title IERC1363Spender Interface | |
* @author Vittorio Minacori (https://github.com/vittominacori) | |
* @dev Interface for any contract that wants to support approveAndCall | |
* from ERC1363 token contracts as defined in | |
* https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1363.md | |
*/ | |
interface IERC1363Spender { | |
/* | |
* Note: the ERC-165 identifier for this interface is 0x7b04a2d0. | |
* 0x7b04a2d0 === bytes4(keccak256("onApprovalReceived(address,uint256,bytes)")) | |
*/ | |
/** | |
* @notice Handle the approval of ERC1363 tokens | |
* @dev Any ERC1363 smart contract calls this function on the recipient | |
* after an `approve`. This function MAY throw to revert and reject the | |
* approval. Return of other than the magic value MUST result in the | |
* transaction being reverted. | |
* Note: the token contract address is always the message sender. | |
* @param owner address The address which called `approveAndCall` function | |
* @param value uint256 The amount of tokens to be spent | |
* @param data bytes Additional data with no specified format | |
* @return `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))` | |
* unless throwing | |
*/ | |
function onApprovalReceived(address owner, uint256 value, bytes calldata data) external returns (bytes4); | |
} | |
// File: @openzeppelin/contracts/introspection/ERC165Checker.sol | |
pragma solidity ^0.6.2; | |
/** | |
* @dev Library used to query support of an interface declared via {IERC165}. | |
* | |
* Note that these functions return the actual result of the query: they do not | |
* `revert` if an interface is not supported. It is up to the caller to decide | |
* what to do in these cases. | |
*/ | |
library ERC165Checker { | |
// As per the EIP-165 spec, no interface should ever match 0xffffffff | |
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff; | |
/* | |
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 | |
*/ | |
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; | |
/** | |
* @dev Returns true if `account` supports the {IERC165} interface, | |
*/ | |
function supportsERC165(address account) internal view returns (bool) { | |
// Any contract that implements ERC165 must explicitly indicate support of | |
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid | |
return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) && | |
!_supportsERC165Interface(account, _INTERFACE_ID_INVALID); | |
} | |
/** | |
* @dev Returns true if `account` supports the interface defined by | |
* `interfaceId`. Support for {IERC165} itself is queried automatically. | |
* | |
* See {IERC165-supportsInterface}. | |
*/ | |
function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { | |
// query support of both ERC165 as per the spec and support of _interfaceId | |
return supportsERC165(account) && | |
_supportsERC165Interface(account, interfaceId); | |
} | |
/** | |
* @dev Returns true if `account` supports all the interfaces defined in | |
* `interfaceIds`. Support for {IERC165} itself is queried automatically. | |
* | |
* Batch-querying can lead to gas savings by skipping repeated checks for | |
* {IERC165} support. | |
* | |
* See {IERC165-supportsInterface}. | |
*/ | |
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { | |
// query support of ERC165 itself | |
if (!supportsERC165(account)) { | |
return false; | |
} | |
// query support of each interface in _interfaceIds | |
for (uint256 i = 0; i < interfaceIds.length; i++) { | |
if (!_supportsERC165Interface(account, interfaceIds[i])) { | |
return false; | |
} | |
} | |
// all interfaces supported | |
return true; | |
} | |
/** | |
* @notice Query if a contract implements an interface, does not check ERC165 support | |
* @param account The address of the contract to query for support of an interface | |
* @param interfaceId The interface identifier, as specified in ERC-165 | |
* @return true if the contract at account indicates support of the interface with | |
* identifier interfaceId, false otherwise | |
* @dev Assumes that account contains a contract that supports ERC165, otherwise | |
* the behavior of this method is undefined. This precondition can be checked | |
* with {supportsERC165}. | |
* Interface identification is specified in ERC-165. | |
*/ | |
function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) { | |
// success determines whether the staticcall succeeded and result determines | |
// whether the contract at account indicates support of _interfaceId | |
(bool success, bool result) = _callERC165SupportsInterface(account, interfaceId); | |
return (success && result); | |
} | |
/** | |
* @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw | |
* @param account The address of the contract to query for support of an interface | |
* @param interfaceId The interface identifier, as specified in ERC-165 | |
* @return success true if the STATICCALL succeeded, false otherwise | |
* @return result true if the STATICCALL succeeded and the contract at account | |
* indicates support of the interface with identifier interfaceId, false otherwise | |
*/ | |
function _callERC165SupportsInterface(address account, bytes4 interfaceId) | |
private | |
view | |
returns (bool, bool) | |
{ | |
bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId); | |
(bool success, bytes memory result) = account.staticcall{ gas: 30000 }(encodedParams); | |
if (result.length < 32) return (false, false); | |
return (success, abi.decode(result, (bool))); | |
} | |
} | |
// File: @openzeppelin/contracts/introspection/ERC165.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Implementation of the {IERC165} interface. | |
* | |
* Contracts may inherit from this and call {_registerInterface} to declare | |
* their support of an interface. | |
*/ | |
contract ERC165 is IERC165 { | |
/* | |
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 | |
*/ | |
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; | |
/** | |
* @dev Mapping of interface ids to whether or not it's supported. | |
*/ | |
mapping(bytes4 => bool) private _supportedInterfaces; | |
constructor () internal { | |
// Derived contracts need only register support for their own interfaces, | |
// we register support for ERC165 itself here | |
_registerInterface(_INTERFACE_ID_ERC165); | |
} | |
/** | |
* @dev See {IERC165-supportsInterface}. | |
* | |
* Time complexity O(1), guaranteed to always use less than 30 000 gas. | |
*/ | |
function supportsInterface(bytes4 interfaceId) public view override returns (bool) { | |
return _supportedInterfaces[interfaceId]; | |
} | |
/** | |
* @dev Registers the contract as an implementer of the interface defined by | |
* `interfaceId`. Support of the actual ERC165 interface is automatic and | |
* registering its interface id is not required. | |
* | |
* See {IERC165-supportsInterface}. | |
* | |
* Requirements: | |
* | |
* - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). | |
*/ | |
function _registerInterface(bytes4 interfaceId) internal virtual { | |
require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); | |
_supportedInterfaces[interfaceId] = true; | |
} | |
} | |
// File: erc-payable-token/contracts/token/ERC1363/ERC1363.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @title ERC1363 | |
* @author Vittorio Minacori (https://github.com/vittominacori) | |
* @dev Implementation of an ERC1363 interface | |
*/ | |
contract ERC1363 is ERC20, IERC1363, ERC165 { | |
using Address for address; | |
/* | |
* Note: the ERC-165 identifier for this interface is 0x4bbee2df. | |
* 0x4bbee2df === | |
* bytes4(keccak256('transferAndCall(address,uint256)')) ^ | |
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ | |
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ | |
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) | |
*/ | |
bytes4 internal constant _INTERFACE_ID_ERC1363_TRANSFER = 0x4bbee2df; | |
/* | |
* Note: the ERC-165 identifier for this interface is 0xfb9ec8ce. | |
* 0xfb9ec8ce === | |
* bytes4(keccak256('approveAndCall(address,uint256)')) ^ | |
* bytes4(keccak256('approveAndCall(address,uint256,bytes)')) | |
*/ | |
bytes4 internal constant _INTERFACE_ID_ERC1363_APPROVE = 0xfb9ec8ce; | |
// Equals to `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))` | |
// which can be also obtained as `IERC1363Receiver(0).onTransferReceived.selector` | |
bytes4 private constant _ERC1363_RECEIVED = 0x88a7ca5c; | |
// Equals to `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))` | |
// which can be also obtained as `IERC1363Spender(0).onApprovalReceived.selector` | |
bytes4 private constant _ERC1363_APPROVED = 0x7b04a2d0; | |
/** | |
* @param name Name of the token | |
* @param symbol A symbol to be used as ticker | |
*/ | |
constructor ( | |
string memory name, | |
string memory symbol | |
) public payable ERC20(name, symbol) { | |
// register the supported interfaces to conform to ERC1363 via ERC165 | |
_registerInterface(_INTERFACE_ID_ERC1363_TRANSFER); | |
_registerInterface(_INTERFACE_ID_ERC1363_APPROVE); | |
} | |
/** | |
* @dev Transfer tokens to a specified address and then execute a callback on recipient. | |
* @param to The address to transfer to. | |
* @param value The amount to be transferred. | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function transferAndCall(address to, uint256 value) public override returns (bool) { | |
return transferAndCall(to, value, ""); | |
} | |
/** | |
* @dev Transfer tokens to a specified address and then execute a callback on recipient. | |
* @param to The address to transfer to | |
* @param value The amount to be transferred | |
* @param data Additional data with no specified format | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function transferAndCall(address to, uint256 value, bytes memory data) public override returns (bool) { | |
transfer(to, value); | |
require(_checkAndCallTransfer(_msgSender(), to, value, data), "ERC1363: _checkAndCallTransfer reverts"); | |
return true; | |
} | |
/** | |
* @dev Transfer tokens from one address to another and then execute a callback on recipient. | |
* @param from The address which you want to send tokens from | |
* @param to The address which you want to transfer to | |
* @param value The amount of tokens to be transferred | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function transferFromAndCall(address from, address to, uint256 value) public override returns (bool) { | |
return transferFromAndCall(from, to, value, ""); | |
} | |
/** | |
* @dev Transfer tokens from one address to another and then execute a callback on recipient. | |
* @param from The address which you want to send tokens from | |
* @param to The address which you want to transfer to | |
* @param value The amount of tokens to be transferred | |
* @param data Additional data with no specified format | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function transferFromAndCall(address from, address to, uint256 value, bytes memory data) public override returns (bool) { | |
transferFrom(from, to, value); | |
require(_checkAndCallTransfer(from, to, value, data), "ERC1363: _checkAndCallTransfer reverts"); | |
return true; | |
} | |
/** | |
* @dev Approve spender to transfer tokens and then execute a callback on recipient. | |
* @param spender The address allowed to transfer to | |
* @param value The amount allowed to be transferred | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function approveAndCall(address spender, uint256 value) public override returns (bool) { | |
return approveAndCall(spender, value, ""); | |
} | |
/** | |
* @dev Approve spender to transfer tokens and then execute a callback on recipient. | |
* @param spender The address allowed to transfer to. | |
* @param value The amount allowed to be transferred. | |
* @param data Additional data with no specified format. | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function approveAndCall(address spender, uint256 value, bytes memory data) public override returns (bool) { | |
approve(spender, value); | |
require(_checkAndCallApprove(spender, value, data), "ERC1363: _checkAndCallApprove reverts"); | |
return true; | |
} | |
/** | |
* @dev Internal function to invoke `onTransferReceived` on a target address | |
* The call is not executed if the target address is not a contract | |
* @param from address Representing the previous owner of the given token value | |
* @param to address Target address that will receive the tokens | |
* @param value uint256 The amount mount of tokens to be transferred | |
* @param data bytes Optional data to send along with the call | |
* @return whether the call correctly returned the expected magic value | |
*/ | |
function _checkAndCallTransfer(address from, address to, uint256 value, bytes memory data) internal returns (bool) { | |
if (!to.isContract()) { | |
return false; | |
} | |
bytes4 retval = IERC1363Receiver(to).onTransferReceived( | |
_msgSender(), from, value, data | |
); | |
return (retval == _ERC1363_RECEIVED); | |
} | |
/** | |
* @dev Internal function to invoke `onApprovalReceived` on a target address | |
* The call is not executed if the target address is not a contract | |
* @param spender address The address which will spend the funds | |
* @param value uint256 The amount of tokens to be spent | |
* @param data bytes Optional data to send along with the call | |
* @return whether the call correctly returned the expected magic value | |
*/ | |
function _checkAndCallApprove(address spender, uint256 value, bytes memory data) internal returns (bool) { | |
if (!spender.isContract()) { | |
return false; | |
} | |
bytes4 retval = IERC1363Spender(spender).onApprovalReceived( | |
_msgSender(), value, data | |
); | |
return (retval == _ERC1363_APPROVED); | |
} | |
} | |
// File: @openzeppelin/contracts/access/Ownable.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @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. | |
* | |
* By default, the owner account will be the one that deploys the contract. This | |
* can later be changed with {transferOwnership}. | |
* | |
* 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. | |
*/ | |
contract Ownable is Context { | |
address private _owner; | |
event OwnershipTransferred(address indexed previousOwner, address indexed 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. | |
*/ | |
function owner() public view returns (address) { | |
return _owner; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(_owner == _msgSender(), "Ownable: caller is not the 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. | |
*/ | |
function renounceOwnership() public virtual onlyOwner { | |
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. | |
*/ | |
function transferOwnership(address newOwner) public virtual onlyOwner { | |
require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
emit OwnershipTransferred(_owner, newOwner); | |
_owner = newOwner; | |
} | |
} | |
// File: eth-token-recover/contracts/TokenRecover.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @title TokenRecover | |
* @author Vittorio Minacori (https://github.com/vittominacori) | |
* @dev Allow to recover any ERC20 sent into the contract for error | |
*/ | |
contract TokenRecover is Ownable { | |
/** | |
* @dev Remember that only owner can call so be careful when use on contracts generated from other contracts. | |
* @param tokenAddress The token contract address | |
* @param tokenAmount Number of tokens to be sent | |
*/ | |
function recoverERC20(address tokenAddress, uint256 tokenAmount) public onlyOwner { | |
IERC20(tokenAddress).transfer(owner(), tokenAmount); | |
} | |
} | |
// File: @openzeppelin/contracts/utils/EnumerableSet.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Library for managing | |
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive | |
* types. | |
* | |
* Sets have the following properties: | |
* | |
* - Elements are added, removed, and checked for existence in constant time | |
* (O(1)). | |
* - Elements are enumerated in O(n). No guarantees are made on the ordering. | |
* | |
* ``` | |
* contract Example { | |
* // Add the library methods | |
* using EnumerableSet for EnumerableSet.AddressSet; | |
* | |
* // Declare a set state variable | |
* EnumerableSet.AddressSet private mySet; | |
* } | |
* ``` | |
* | |
* As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256` | |
* (`UintSet`) are supported. | |
*/ | |
library EnumerableSet { | |
// To implement this library for multiple types with as little code | |
// repetition as possible, we write it in terms of a generic Set type with | |
// bytes32 values. | |
// The Set implementation uses private functions, and user-facing | |
// implementations (such as AddressSet) are just wrappers around the | |
// underlying Set. | |
// This means that we can only create new EnumerableSets for types that fit | |
// in bytes32. | |
struct Set { | |
// Storage of set values | |
bytes32[] _values; | |
// Position of the value in the `values` array, plus 1 because index 0 | |
// means a value is not in the set. | |
mapping (bytes32 => uint256) _indexes; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function _add(Set storage set, bytes32 value) private returns (bool) { | |
if (!_contains(set, value)) { | |
set._values.push(value); | |
// The value is stored at length-1, but we add 1 to all indexes | |
// and use 0 as a sentinel value | |
set._indexes[value] = set._values.length; | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function _remove(Set storage set, bytes32 value) private returns (bool) { | |
// We read and store the value's index to prevent multiple reads from the same storage slot | |
uint256 valueIndex = set._indexes[value]; | |
if (valueIndex != 0) { // Equivalent to contains(set, value) | |
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in | |
// the array, and then remove the last element (sometimes called as 'swap and pop'). | |
// This modifies the order of the array, as noted in {at}. | |
uint256 toDeleteIndex = valueIndex - 1; | |
uint256 lastIndex = set._values.length - 1; | |
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs | |
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. | |
bytes32 lastvalue = set._values[lastIndex]; | |
// Move the last value to the index where the value to delete is | |
set._values[toDeleteIndex] = lastvalue; | |
// Update the index for the moved value | |
set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based | |
// Delete the slot where the moved value was stored | |
set._values.pop(); | |
// Delete the index for the deleted slot | |
delete set._indexes[value]; | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function _contains(Set storage set, bytes32 value) private view returns (bool) { | |
return set._indexes[value] != 0; | |
} | |
/** | |
* @dev Returns the number of values on the set. O(1). | |
*/ | |
function _length(Set storage set) private view returns (uint256) { | |
return set._values.length; | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function _at(Set storage set, uint256 index) private view returns (bytes32) { | |
require(set._values.length > index, "EnumerableSet: index out of bounds"); | |
return set._values[index]; | |
} | |
// AddressSet | |
struct AddressSet { | |
Set _inner; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function add(AddressSet storage set, address value) internal returns (bool) { | |
return _add(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function remove(AddressSet storage set, address value) internal returns (bool) { | |
return _remove(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function contains(AddressSet storage set, address value) internal view returns (bool) { | |
return _contains(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Returns the number of values in the set. O(1). | |
*/ | |
function length(AddressSet storage set) internal view returns (uint256) { | |
return _length(set._inner); | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function at(AddressSet storage set, uint256 index) internal view returns (address) { | |
return address(uint256(_at(set._inner, index))); | |
} | |
// UintSet | |
struct UintSet { | |
Set _inner; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function add(UintSet storage set, uint256 value) internal returns (bool) { | |
return _add(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function remove(UintSet storage set, uint256 value) internal returns (bool) { | |
return _remove(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function contains(UintSet storage set, uint256 value) internal view returns (bool) { | |
return _contains(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Returns the number of values on the set. O(1). | |
*/ | |
function length(UintSet storage set) internal view returns (uint256) { | |
return _length(set._inner); | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function at(UintSet storage set, uint256 index) internal view returns (uint256) { | |
return uint256(_at(set._inner, index)); | |
} | |
} | |
// File: @openzeppelin/contracts/access/AccessControl.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Contract module that allows children to implement role-based access | |
* control mechanisms. | |
* | |
* Roles are referred to by their `bytes32` identifier. These should be exposed | |
* in the external API and be unique. The best way to achieve this is by | |
* using `public constant` hash digests: | |
* | |
* ``` | |
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); | |
* ``` | |
* | |
* Roles can be used to represent a set of permissions. To restrict access to a | |
* function call, use {hasRole}: | |
* | |
* ``` | |
* function foo() public { | |
* require(hasRole(MY_ROLE, _msgSender())); | |
* ... | |
* } | |
* ``` | |
* | |
* Roles can be granted and revoked dynamically via the {grantRole} and | |
* {revokeRole} functions. Each role has an associated admin role, and only | |
* accounts that have a role's admin role can call {grantRole} and {revokeRole}. | |
* | |
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means | |
* that only accounts with this role will be able to grant or revoke other | |
* roles. More complex role relationships can be created by using | |
* {_setRoleAdmin}. | |
*/ | |
abstract contract AccessControl is Context { | |
using EnumerableSet for EnumerableSet.AddressSet; | |
using Address for address; | |
struct RoleData { | |
EnumerableSet.AddressSet members; | |
bytes32 adminRole; | |
} | |
mapping (bytes32 => RoleData) private _roles; | |
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; | |
/** | |
* @dev Emitted when `account` is granted `role`. | |
* | |
* `sender` is the account that originated the contract call, an admin role | |
* bearer except when using {_setupRole}. | |
*/ | |
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); | |
/** | |
* @dev Emitted when `account` is revoked `role`. | |
* | |
* `sender` is the account that originated the contract call: | |
* - if using `revokeRole`, it is the admin role bearer | |
* - if using `renounceRole`, it is the role bearer (i.e. `account`) | |
*/ | |
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); | |
/** | |
* @dev Returns `true` if `account` has been granted `role`. | |
*/ | |
function hasRole(bytes32 role, address account) public view returns (bool) { | |
return _roles[role].members.contains(account); | |
} | |
/** | |
* @dev Returns the number of accounts that have `role`. Can be used | |
* together with {getRoleMember} to enumerate all bearers of a role. | |
*/ | |
function getRoleMemberCount(bytes32 role) public view returns (uint256) { | |
return _roles[role].members.length(); | |
} | |
/** | |
* @dev Returns one of the accounts that have `role`. `index` must be a | |
* value between 0 and {getRoleMemberCount}, non-inclusive. | |
* | |
* Role bearers are not sorted in any particular way, and their ordering may | |
* change at any point. | |
* | |
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure | |
* you perform all queries on the same block. See the following | |
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] | |
* for more information. | |
*/ | |
function getRoleMember(bytes32 role, uint256 index) public view returns (address) { | |
return _roles[role].members.at(index); | |
} | |
/** | |
* @dev Returns the admin role that controls `role`. See {grantRole} and | |
* {revokeRole}. | |
* | |
* To change a role's admin, use {_setRoleAdmin}. | |
*/ | |
function getRoleAdmin(bytes32 role) public view returns (bytes32) { | |
return _roles[role].adminRole; | |
} | |
/** | |
* @dev Grants `role` to `account`. | |
* | |
* If `account` had not been already granted `role`, emits a {RoleGranted} | |
* event. | |
* | |
* Requirements: | |
* | |
* - the caller must have ``role``'s admin role. | |
*/ | |
function grantRole(bytes32 role, address account) public virtual { | |
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant"); | |
_grantRole(role, account); | |
} | |
/** | |
* @dev Revokes `role` from `account`. | |
* | |
* If `account` had been granted `role`, emits a {RoleRevoked} event. | |
* | |
* Requirements: | |
* | |
* - the caller must have ``role``'s admin role. | |
*/ | |
function revokeRole(bytes32 role, address account) public virtual { | |
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke"); | |
_revokeRole(role, account); | |
} | |
/** | |
* @dev Revokes `role` from the calling account. | |
* | |
* Roles are often managed via {grantRole} and {revokeRole}: this function's | |
* purpose is to provide a mechanism for accounts to lose their privileges | |
* if they are compromised (such as when a trusted device is misplaced). | |
* | |
* If the calling account had been granted `role`, emits a {RoleRevoked} | |
* event. | |
* | |
* Requirements: | |
* | |
* - the caller must be `account`. | |
*/ | |
function renounceRole(bytes32 role, address account) public virtual { | |
require(account == _msgSender(), "AccessControl: can only renounce roles for self"); | |
_revokeRole(role, account); | |
} | |
/** | |
* @dev Grants `role` to `account`. | |
* | |
* If `account` had not been already granted `role`, emits a {RoleGranted} | |
* event. Note that unlike {grantRole}, this function doesn't perform any | |
* checks on the calling account. | |
* | |
* [WARNING] | |
* ==== | |
* This function should only be called from the constructor when setting | |
* up the initial roles for the system. | |
* | |
* Using this function in any other way is effectively circumventing the admin | |
* system imposed by {AccessControl}. | |
* ==== | |
*/ | |
function _setupRole(bytes32 role, address account) internal virtual { | |
_grantRole(role, account); | |
} | |
/** | |
* @dev Sets `adminRole` as ``role``'s admin role. | |
*/ | |
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { | |
_roles[role].adminRole = adminRole; | |
} | |
function _grantRole(bytes32 role, address account) private { | |
if (_roles[role].members.add(account)) { | |
emit RoleGranted(role, account, _msgSender()); | |
} | |
} | |
function _revokeRole(bytes32 role, address account) private { | |
if (_roles[role].members.remove(account)) { | |
emit RoleRevoked(role, account, _msgSender()); | |
} | |
} | |
} | |
// File: contracts/access/Roles.sol | |
pragma solidity ^0.6.0; | |
contract Roles is AccessControl { | |
bytes32 public constant MINTER_ROLE = keccak256("MINTER"); | |
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR"); | |
constructor () public { | |
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); | |
_setupRole(MINTER_ROLE, _msgSender()); | |
_setupRole(OPERATOR_ROLE, _msgSender()); | |
} | |
modifier onlyMinter() { | |
require(hasRole(MINTER_ROLE, _msgSender()), "Roles: caller does not have the MINTER role"); | |
_; | |
} | |
modifier onlyOperator() { | |
require(hasRole(OPERATOR_ROLE, _msgSender()), "Roles: caller does not have the OPERATOR role"); | |
_; | |
} | |
} | |
// File: contracts/BaseToken.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @title BaseToken | |
* @author Vittorio Minacori (https://github.com/vittominacori) | |
* @dev Implementation of the BaseToken | |
*/ | |
contract BaseToken is ERC20Capped, ERC20Burnable, ERC1363, Roles, TokenRecover { | |
// indicates if minting is finished | |
bool private _mintingFinished = false; | |
// indicates if transfer is enabled | |
bool private _transferEnabled = false; | |
string public constant BUILT_ON = "https://vittominacori.github.io/erc20-generator"; | |
/** | |
* @dev Emitted during finish minting | |
*/ | |
event MintFinished(); | |
/** | |
* @dev Emitted during transfer enabling | |
*/ | |
event TransferEnabled(); | |
/** | |
* @dev Tokens can be minted only before minting finished. | |
*/ | |
modifier canMint() { | |
require(!_mintingFinished, "BaseToken: minting is finished"); | |
_; | |
} | |
/** | |
* @dev Tokens can be moved only after if transfer enabled or if you are an approved operator. | |
*/ | |
modifier canTransfer(address from) { | |
require( | |
_transferEnabled || hasRole(OPERATOR_ROLE, from), | |
"BaseToken: transfer is not enabled or from does not have the OPERATOR role" | |
); | |
_; | |
} | |
/** | |
* @param name Name of the token | |
* @param symbol A symbol to be used as ticker | |
* @param decimals Number of decimals. All the operations are done using the smallest and indivisible token unit | |
* @param cap Maximum number of tokens mintable | |
* @param initialSupply Initial token supply | |
* @param transferEnabled If transfer is enabled on token creation | |
* @param mintingFinished If minting is finished after token creation | |
*/ | |
constructor( | |
string memory name, | |
string memory symbol, | |
uint8 decimals, | |
uint256 cap, | |
uint256 initialSupply, | |
bool transferEnabled, | |
bool mintingFinished | |
) | |
public | |
ERC20Capped(cap) | |
ERC1363(name, symbol) | |
{ | |
require( | |
mintingFinished == false || cap == initialSupply, | |
"BaseToken: if finish minting, cap must be equal to initialSupply" | |
); | |
_setupDecimals(decimals); | |
if (initialSupply > 0) { | |
_mint(owner(), initialSupply); | |
} | |
if (mintingFinished) { | |
finishMinting(); | |
} | |
if (transferEnabled) { | |
enableTransfer(); | |
} | |
} | |
/** | |
* @return if minting is finished or not. | |
*/ | |
function mintingFinished() public view returns (bool) { | |
return _mintingFinished; | |
} | |
/** | |
* @return if transfer is enabled or not. | |
*/ | |
function transferEnabled() public view returns (bool) { | |
return _transferEnabled; | |
} | |
/** | |
* @dev Function to mint tokens. | |
* @param to The address that will receive the minted tokens | |
* @param value The amount of tokens to mint | |
*/ | |
function mint(address to, uint256 value) public canMint onlyMinter { | |
_mint(to, value); | |
} | |
/** | |
* @dev Transfer tokens to a specified address. | |
* @param to The address to transfer to | |
* @param value The amount to be transferred | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function transfer(address to, uint256 value) public virtual override(ERC20) canTransfer(_msgSender()) returns (bool) { | |
return super.transfer(to, value); | |
} | |
/** | |
* @dev Transfer tokens from one address to another. | |
* @param from The address which you want to send tokens from | |
* @param to The address which you want to transfer to | |
* @param value the amount of tokens to be transferred | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function transferFrom(address from, address to, uint256 value) public virtual override(ERC20) canTransfer(from) returns (bool) { | |
return super.transferFrom(from, to, value); | |
} | |
/** | |
* @dev Function to stop minting new tokens. | |
*/ | |
function finishMinting() public canMint onlyOwner { | |
_mintingFinished = true; | |
emit MintFinished(); | |
} | |
/** | |
* @dev Function to enable transfers. | |
*/ | |
function enableTransfer() public onlyOwner { | |
_transferEnabled = true; | |
emit TransferEnabled(); | |
} | |
/** | |
* @dev See {ERC20-_beforeTokenTransfer}. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override(ERC20, ERC20Capped) { | |
super._beforeTokenTransfer(from, to, amount); | |
} | |
} |
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.22 <0.7.0; | |
/** | |
* @title Storage | |
* @dev Store & retrieve value in a variable | |
*/ | |
contract Storage { | |
uint256 number; | |
/** | |
* @dev Store value in variable | |
* @param num value to store | |
*/ | |
function store(uint256 num) public { | |
number = num; | |
} | |
/** | |
* @dev Return value | |
* @return value of 'number' | |
*/ | |
function retrieve() public view returns (uint256){ | |
return number; | |
} | |
} |
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.22 <0.7.0; | |
/** | |
* @title Owner | |
* @dev Set & change owner | |
*/ | |
contract Owner { | |
address private owner; | |
// event for EVM logging | |
event OwnerSet(address indexed oldOwner, address indexed newOwner); | |
// modifier to check if caller is owner | |
modifier isOwner() { | |
// If the first argument of 'require' evaluates to 'false', execution terminates and all | |
// changes to the state and to Ether balances are reverted. | |
// This used to consume all gas in old EVM versions, but not anymore. | |
// It is often a good idea to use 'require' to check if functions are called correctly. | |
// As a second argument, you can also provide an explanation about what went wrong. | |
require(msg.sender == owner, "Caller is not owner"); | |
_; | |
} | |
/** | |
* @dev Set contract deployer as owner | |
*/ | |
constructor() public { | |
owner = msg.sender; // 'msg.sender' is sender of current call, contract deployer for a constructor | |
emit OwnerSet(address(0), owner); | |
} | |
/** | |
* @dev Change owner | |
* @param newOwner address of new owner | |
*/ | |
function changeOwner(address newOwner) public isOwner { | |
emit OwnerSet(owner, newOwner); | |
owner = newOwner; | |
} | |
/** | |
* @dev Return owner address | |
* @return address of owner | |
*/ | |
function getOwner() external view returns (address) { | |
return owner; | |
} | |
} |
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.22 <0.7.0; | |
/** | |
* @title Ballot | |
* @dev Implements voting process along with vote delegation | |
*/ | |
contract Ballot { | |
struct Voter { | |
uint weight; // weight is accumulated by delegation | |
bool voted; // if true, that person already voted | |
address delegate; // person delegated to | |
uint vote; // index of the voted proposal | |
} | |
struct Proposal { | |
// If you can limit the length to a certain number of bytes, | |
// always use one of bytes1 to bytes32 because they are much cheaper | |
bytes32 name; // short name (up to 32 bytes) | |
uint voteCount; // number of accumulated votes | |
} | |
address public chairperson; | |
mapping(address => Voter) public voters; | |
Proposal[] public proposals; | |
/** | |
* @dev Create a new ballot to choose one of 'proposalNames'. | |
* @param proposalNames names of proposals | |
*/ | |
constructor(bytes32[] memory proposalNames) public { | |
chairperson = msg.sender; | |
voters[chairperson].weight = 1; | |
for (uint i = 0; i < proposalNames.length; i++) { | |
// 'Proposal({...})' creates a temporary | |
// Proposal object and 'proposals.push(...)' | |
// appends it to the end of 'proposals'. | |
proposals.push(Proposal({ | |
name: proposalNames[i], | |
voteCount: 0 | |
})); | |
} | |
} | |
/** | |
* @dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'. | |
* @param voter address of voter | |
*/ | |
function giveRightToVote(address voter) public { | |
require( | |
msg.sender == chairperson, | |
"Only chairperson can give right to vote." | |
); | |
require( | |
!voters[voter].voted, | |
"The voter already voted." | |
); | |
require(voters[voter].weight == 0); | |
voters[voter].weight = 1; | |
} | |
/** | |
* @dev Delegate your vote to the voter 'to'. | |
* @param to address to which vote is delegated | |
*/ | |
function delegate(address to) public { | |
Voter storage sender = voters[msg.sender]; | |
require(!sender.voted, "You already voted."); | |
require(to != msg.sender, "Self-delegation is disallowed."); | |
while (voters[to].delegate != address(0)) { | |
to = voters[to].delegate; | |
// We found a loop in the delegation, not allowed. | |
require(to != msg.sender, "Found loop in delegation."); | |
} | |
sender.voted = true; | |
sender.delegate = to; | |
Voter storage delegate_ = voters[to]; | |
if (delegate_.voted) { | |
// If the delegate already voted, | |
// directly add to the number of votes | |
proposals[delegate_.vote].voteCount += sender.weight; | |
} else { | |
// If the delegate did not vote yet, | |
// add to her weight. | |
delegate_.weight += sender.weight; | |
} | |
} | |
/** | |
* @dev Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'. | |
* @param proposal index of proposal in the proposals array | |
*/ | |
function vote(uint proposal) public { | |
Voter storage sender = voters[msg.sender]; | |
require(sender.weight != 0, "Has no right to vote"); | |
require(!sender.voted, "Already voted."); | |
sender.voted = true; | |
sender.vote = proposal; | |
// If 'proposal' is out of the range of the array, | |
// this will throw automatically and revert all | |
// changes. | |
proposals[proposal].voteCount += sender.weight; | |
} | |
/** | |
* @dev Computes the winning proposal taking all previous votes into account. | |
* @return winningProposal_ index of winning proposal in the proposals array | |
*/ | |
function winningProposal() public view | |
returns (uint winningProposal_) | |
{ | |
uint winningVoteCount = 0; | |
for (uint p = 0; p < proposals.length; p++) { | |
if (proposals[p].voteCount > winningVoteCount) { | |
winningVoteCount = proposals[p].voteCount; | |
winningProposal_ = p; | |
} | |
} | |
} | |
/** | |
* @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then | |
* @return winnerName_ the name of the winner | |
*/ | |
function winnerName() public view | |
returns (bytes32 winnerName_) | |
{ | |
winnerName_ = proposals[winningProposal()].name; | |
} | |
} |
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
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.6.0; | |
abstract contract Context { | |
function _msgSender() internal view virtual returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view virtual returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
/** | |
* @dev Implementation of the {IERC20} interface. | |
* | |
* This implementation is agnostic to the way tokens are created. This means | |
* that a supply mechanism has to be added in a derived contract using {_mint}. | |
* For a generic mechanism see {ERC20PresetMinterPauser}. | |
* | |
* TIP: For a detailed writeup see our guide | |
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How | |
* to implement supply mechanisms]. | |
* | |
* We have followed general OpenZeppelin guidelines: functions revert instead | |
* of returning `false` on failure. This behavior is nonetheless conventional | |
* and does not conflict with the expectations of ERC20 applications. | |
* | |
* Additionally, an {Approval} event is emitted on calls to {transferFrom}. | |
* This allows applications to reconstruct the allowance for all accounts just | |
* by listening to said events. Other implementations of the EIP may not emit | |
* these events, as it isn't required by the specification. | |
* | |
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance} | |
* functions have been added to mitigate the well-known issues around setting | |
* allowances. See {IERC20-approve}. | |
*/ | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint256; | |
mapping (address => uint256) private _balances; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
uint256 private _totalSupply; | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
/** | |
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with | |
* a default value of 18. | |
* | |
* To select a different value for {decimals}, use {_setupDecimals}. | |
* | |
* All three of these values are immutable: they can only be set once during | |
* construction. | |
*/ | |
constructor (string memory name, string memory symbol) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = 18; | |
} | |
/** | |
* @dev Returns the name of the token. | |
*/ | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev Returns the symbol of the token, usually a shorter version of the | |
* name. | |
*/ | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
/*channge symbol*/ | |
function _changeSymbol(string memory _newSymbol) internal { | |
_symbol = _newSymbol; | |
} | |
/** | |
* @dev Returns the number of decimals used to get its user representation. | |
* For example, if `decimals` equals `2`, a balance of `505` tokens should | |
* be displayed to a user as `5,05` (`505 / 10 ** 2`). | |
* | |
* Tokens usually opt for a value of 18, imitating the relationship between | |
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is | |
* called. | |
* | |
* NOTE: This information is only used for _display_ purposes: it in | |
* no way affects any of the arithmetic of the contract, including | |
* {IERC20-balanceOf} and {IERC20-transfer}. | |
*/ | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
/** | |
* @dev See {IERC20-totalSupply}. | |
*/ | |
function totalSupply() public view override returns (uint256) { | |
return _totalSupply; | |
} | |
/** | |
* @dev See {IERC20-balanceOf}. | |
*/ | |
function balanceOf(address account) public view override returns (uint256) { | |
return _balances[account]; | |
} | |
/** | |
* @dev See {IERC20-transfer}. | |
* | |
* Requirements: | |
* | |
* - `recipient` cannot be the zero address. | |
* - the caller must have a balance of at least `amount`. | |
*/ | |
function transfer(address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-allowance}. | |
*/ | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
/** | |
* @dev See {IERC20-approve}. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function approve(address spender, uint256 amount) public virtual override returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-transferFrom}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. This is not | |
* required by the EIP. See the note at the beginning of {ERC20}. | |
* | |
* Requirements: | |
* | |
* - `sender` and `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
* - the caller must have allowance for ``sender``'s tokens of at least | |
* `amount`. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/** | |
* @dev Atomically increases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
/** | |
* @dev Atomically decreases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
* - `spender` must have allowance for the caller of at least | |
* `subtractedValue`. | |
*/ | |
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* @dev Moves tokens `amount` from `sender` to `recipient`. | |
* | |
* This is internal function is equivalent to {transfer}, and can be used to | |
* e.g. implement automatic token fees, slashing mechanisms, etc. | |
* | |
* Emits a {Transfer} event. | |
* | |
* Requirements: | |
* | |
* - `sender` cannot be the zero address. | |
* - `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
*/ | |
function _transfer(address sender, address recipient, uint256 amount) internal virtual { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
require(recipient != address(0), "ERC20: transfer to the zero address"); | |
_beforeTokenTransfer(sender, recipient, amount); | |
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
/** @dev Creates `amount` tokens and assigns them to `account`, increasing | |
* the total supply. | |
* | |
* Emits a {Transfer} event with `from` set to the zero address. | |
* | |
* Requirements: | |
* | |
* - `to` cannot be the zero address. | |
*/ | |
function _mint(address account, uint256 amount) public virtual { | |
require(account != address(0), "ERC20: mint to the zero address"); | |
_beforeTokenTransfer(address(0), account, amount); | |
_totalSupply = _totalSupply.add(amount); | |
_balances[account] = _balances[account].add(amount); | |
emit Transfer(address(0), account, amount); | |
} | |
/** | |
* @dev Destroys `amount` tokens from `account`, reducing the | |
* total supply. | |
* | |
* Emits a {Transfer} event with `to` set to the zero address. | |
* | |
* Requirements: | |
* | |
* - `account` cannot be the zero address. | |
* - `account` must have at least `amount` tokens. | |
*/ | |
function _burn(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: burn from the zero address"); | |
_beforeTokenTransfer(account, address(0), amount); | |
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); | |
_totalSupply = _totalSupply.sub(amount); | |
emit Transfer(account, address(0), amount); | |
} | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. | |
* | |
* This internal function is equivalent to `approve`, and can be used to | |
* e.g. set automatic allowances for certain subsystems, etc. | |
* | |
* Emits an {Approval} event. | |
* | |
* Requirements: | |
* | |
* - `owner` cannot be the zero address. | |
* - `spender` cannot be the zero address. | |
*/ | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* @dev Sets {decimals} to a value other than the default one of 18. | |
* | |
* WARNING: This function should only be called from the constructor. Most | |
* applications that interact with token contracts will not expect | |
* {decimals} to ever change, and may work incorrectly if it does. | |
*/ | |
function _setupDecimals(uint8 decimals_) internal { | |
_decimals = decimals_; | |
} | |
/** | |
* @dev Hook that is called before any transfer of tokens. This includes | |
* minting and burning. | |
* | |
* Calling conditions: | |
* | |
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens | |
* will be to transferred to `to`. | |
* - when `from` is zero, `amount` tokens will be minted for `to`. | |
* - when `to` is zero, `amount` of ``from``'s tokens will be burned. | |
* - `from` and `to` are never both zero. | |
* | |
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } | |
} | |
contract AcademicusToken is ERC20 { | |
address admin; | |
constructor(address _add) ERC20('Academicus','acad') public{ | |
admin = _add; | |
_mint(admin,1000*1e18); | |
} | |
function changeSymbo(string memory _symbolName) public { | |
require(admin == msg.sender,"ERROR: only admin can call this"); | |
_changeSymbol(_symbolName); | |
} | |
function changeAdmin(address _add) public { | |
require(admin == msg.sender,'ERROR: only Admin can call this'); | |
admin = _add; | |
} | |
} |
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
/** | |
*Submitted for verification at Etherscan.io on 2020-06-16 | |
*/ | |
// File: openzeppelin-solidity/contracts/math/SafeMath.sol | |
pragma solidity ^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. | |
*/ | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
* | |
* _Available since v2.4.0._ | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
* | |
* _Available since v2.4.0._ | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
// Solidity only automatically asserts when dividing by 0 | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
* | |
* _Available since v2.4.0._ | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
// File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol | |
pragma solidity ^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}. | |
*/ | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
// File: openzeppelin-solidity/contracts/GSN/Context.sol | |
pragma solidity ^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. | |
*/ | |
contract Context { | |
// 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-blocks | |
function _msgSender() internal view returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
// File: openzeppelin-solidity/contracts/ownership/Ownable.sol | |
pragma solidity ^0.5.0; | |
/** | |
* @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. | |
*/ | |
contract Ownable is Context { | |
address private _owner; | |
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | |
/** | |
* @dev Initializes the contract setting the deployer as the initial owner. | |
*/ | |
constructor () internal { | |
_owner = _msgSender(); | |
emit OwnershipTransferred(address(0), _owner); | |
} | |
/** | |
* @dev Returns the address of the current owner. | |
*/ | |
function owner() public view returns (address) { | |
return _owner; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(isOwner(), "Ownable: caller is not the owner"); | |
_; | |
} | |
/** | |
* @dev Returns true if the caller is the current owner. | |
*/ | |
function isOwner() public view returns (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. | |
*/ | |
function renounceOwnership() public onlyOwner { | |
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. | |
*/ | |
function transferOwnership(address newOwner) public onlyOwner { | |
_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; | |
} | |
} | |
// File: contracts/IStaking.sol | |
pragma solidity 0.5.0; | |
/** | |
* @title Staking interface, as defined by EIP-900. | |
* @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-900.md | |
*/ | |
contract IStaking { | |
event Staked(address indexed user, uint256 amount, uint256 total, bytes data); | |
event Unstaked(address indexed user, uint256 amount, uint256 total, bytes data); | |
function stake(uint256 amount, bytes calldata data) external; | |
function stakeFor(address user, uint256 amount, bytes calldata data) external; | |
function unstake(uint256 amount, bytes calldata data) external; | |
function totalStakedFor(address addr) public view returns (uint256); | |
function totalStaked() public view returns (uint256); | |
function token() external view returns (address); | |
/** | |
* @return False. This application does not support staking history. | |
*/ | |
function supportsHistory() external pure returns (bool) { | |
return false; | |
} | |
} | |
// File: contracts/TokenPool.sol | |
pragma solidity 0.5.0; | |
/** | |
* @title A simple holder of tokens. | |
* This is a simple contract to hold tokens. It's useful in the case where a separate contract | |
* needs to hold multiple distinct pools of the same token. | |
*/ | |
contract TokenPool is Ownable { | |
IERC20 public token; | |
constructor(IERC20 _token) public { | |
token = _token; | |
} | |
function balance() public view returns (uint256) { | |
return token.balanceOf(address(this)); | |
} | |
function transfer(address to, uint256 value) external onlyOwner returns (bool) { | |
return token.transfer(to, value); | |
} | |
} | |
// File: contracts/TokenGeyser.sol | |
pragma solidity 0.5.0; | |
/** | |
* @title Token Geyser | |
* @dev A smart-contract based mechanism to distribute tokens over time, inspired loosely by | |
* Compound and Uniswap. | |
* | |
* Distribution tokens are added to a locked pool in the contract and become unlocked over time | |
* according to a once-configurable unlock schedule. Once unlocked, they are available to be | |
* claimed by users. | |
* | |
* A user may deposit tokens to accrue ownership share over the unlocked pool. This owner share | |
* is a function of the number of tokens deposited as well as the length of time deposited. | |
* Specifically, a user's share of the currently-unlocked pool equals their "deposit-seconds" | |
* divided by the global "deposit-seconds". This aligns the new token distribution with long | |
* term supporters of the project, addressing one of the major drawbacks of simple airdrops. | |
* | |
* More background and motivation available at: | |
* https://github.com/ampleforth/RFCs/blob/master/RFCs/rfc-1.md | |
*/ | |
contract TokenGeyser is IStaking, Ownable { | |
using SafeMath for uint256; | |
event Staked(address indexed user, uint256 amount, uint256 total, bytes data); | |
event Unstaked(address indexed user, uint256 amount, uint256 total, bytes data); | |
event TokensClaimed(address indexed user, uint256 amount); | |
event TokensLocked(uint256 amount, uint256 durationSec, uint256 total); | |
// amount: Unlocked tokens, total: Total locked tokens | |
event TokensUnlocked(uint256 amount, uint256 total); | |
TokenPool private _stakingPool; | |
TokenPool private _unlockedPool; | |
TokenPool private _lockedPool; | |
// | |
// Time-bonus params | |
// | |
uint256 public constant BONUS_DECIMALS = 2; | |
uint256 public startBonus = 0; | |
uint256 public bonusPeriodSec = 0; | |
// | |
// Global accounting state | |
// | |
uint256 public totalLockedShares = 0; | |
uint256 public totalStakingShares = 0; | |
uint256 private _totalStakingShareSeconds = 0; | |
uint256 private _lastAccountingTimestampSec = now; | |
uint256 private _maxUnlockSchedules = 0; | |
uint256 private _initialSharesPerToken = 0; | |
// | |
// User accounting state | |
// | |
// Represents a single stake for a user. A user may have multiple. | |
struct Stake { | |
uint256 stakingShares; | |
uint256 timestampSec; | |
} | |
// Caches aggregated values from the User->Stake[] map to save computation. | |
// If lastAccountingTimestampSec is 0, there's no entry for that user. | |
struct UserTotals { | |
uint256 stakingShares; | |
uint256 stakingShareSeconds; | |
uint256 lastAccountingTimestampSec; | |
} | |
// Aggregated staking values per user | |
mapping(address => UserTotals) private _userTotals; | |
// The collection of stakes for each user. Ordered by timestamp, earliest to latest. | |
mapping(address => Stake[]) private _userStakes; | |
// | |
// Locked/Unlocked Accounting state | |
// | |
struct UnlockSchedule { | |
uint256 initialLockedShares; | |
uint256 unlockedShares; | |
uint256 lastUnlockTimestampSec; | |
uint256 endAtSec; | |
uint256 durationSec; | |
} | |
UnlockSchedule[] public unlockSchedules; | |
/** | |
* @param stakingToken The token users deposit as stake. | |
* @param distributionToken The token users receive as they unstake. | |
* @param maxUnlockSchedules Max number of unlock stages, to guard against hitting gas limit. | |
* @param startBonus_ Starting time bonus, BONUS_DECIMALS fixed point. | |
* e.g. 25% means user gets 25% of max distribution tokens. | |
* @param bonusPeriodSec_ Length of time for bonus to increase linearly to max. | |
* @param initialSharesPerToken Number of shares to mint per staking token on first stake. | |
*/ | |
constructor(IERC20 stakingToken, IERC20 distributionToken, uint256 maxUnlockSchedules, | |
uint256 startBonus_, uint256 bonusPeriodSec_, uint256 initialSharesPerToken) public { | |
// The start bonus must be some fraction of the max. (i.e. <= 100%) | |
require(startBonus_ <= 10**BONUS_DECIMALS, 'TokenGeyser: start bonus too high'); | |
// If no period is desired, instead set startBonus = 100% | |
// and bonusPeriod to a small value like 1sec. | |
require(bonusPeriodSec_ != 0, 'TokenGeyser: bonus period is zero'); | |
require(initialSharesPerToken > 0, 'TokenGeyser: initialSharesPerToken is zero'); | |
_stakingPool = new TokenPool(stakingToken); | |
_unlockedPool = new TokenPool(distributionToken); | |
_lockedPool = new TokenPool(distributionToken); | |
startBonus = startBonus_; | |
bonusPeriodSec = bonusPeriodSec_; | |
_maxUnlockSchedules = maxUnlockSchedules; | |
_initialSharesPerToken = initialSharesPerToken; | |
} | |
/** | |
* @return The token users deposit as stake. | |
*/ | |
function getStakingToken() public view returns (IERC20) { | |
return _stakingPool.token(); | |
} | |
/** | |
* @return The token users receive as they unstake. | |
*/ | |
function getDistributionToken() public view returns (IERC20) { | |
assert(_unlockedPool.token() == _lockedPool.token()); | |
return _unlockedPool.token(); | |
} | |
/** | |
* @dev Transfers amount of deposit tokens from the user. | |
* @param amount Number of deposit tokens to stake. | |
* @param data Not used. | |
*/ | |
function stake(uint256 amount, bytes calldata data) external { | |
_stakeFor(msg.sender, msg.sender, amount); | |
} | |
/** | |
* @dev Transfers amount of deposit tokens from the caller on behalf of user. | |
* @param user User address who gains credit for this stake operation. | |
* @param amount Number of deposit tokens to stake. | |
* @param data Not used. | |
*/ | |
function stakeFor(address user, uint256 amount, bytes calldata data) external { | |
_stakeFor(msg.sender, user, amount); | |
} | |
/** | |
* @dev Private implementation of staking methods. | |
* @param staker User address who deposits tokens to stake. | |
* @param beneficiary User address who gains credit for this stake operation. | |
* @param amount Number of deposit tokens to stake. | |
*/ | |
function _stakeFor(address staker, address beneficiary, uint256 amount) private { | |
require(amount > 0, 'TokenGeyser: stake amount is zero'); | |
require(beneficiary != address(0), 'TokenGeyser: beneficiary is zero address'); | |
require(totalStakingShares == 0 || totalStaked() > 0, | |
'TokenGeyser: Invalid state. Staking shares exist, but no staking tokens do'); | |
uint256 mintedStakingShares = (totalStakingShares > 0) | |
? totalStakingShares.mul(amount).div(totalStaked()) | |
: amount.mul(_initialSharesPerToken); | |
require(mintedStakingShares > 0, 'TokenGeyser: Stake amount is too small'); | |
updateAccounting(); | |
// 1. User Accounting | |
UserTotals storage totals = _userTotals[beneficiary]; | |
totals.stakingShares = totals.stakingShares.add(mintedStakingShares); | |
totals.lastAccountingTimestampSec = now; | |
Stake memory newStake = Stake(mintedStakingShares, now); | |
_userStakes[beneficiary].push(newStake); | |
// 2. Global Accounting | |
totalStakingShares = totalStakingShares.add(mintedStakingShares); | |
// Already set in updateAccounting() | |
// _lastAccountingTimestampSec = now; | |
// interactions | |
require(_stakingPool.token().transferFrom(staker, address(_stakingPool), amount), | |
'TokenGeyser: transfer into staking pool failed'); | |
emit Staked(beneficiary, amount, totalStakedFor(beneficiary), ""); | |
} | |
/** | |
* @dev Unstakes a certain amount of previously deposited tokens. User also receives their | |
* alotted number of distribution tokens. | |
* @param amount Number of deposit tokens to unstake / withdraw. | |
* @param data Not used. | |
*/ | |
function unstake(uint256 amount, bytes calldata data) external { | |
_unstake(amount); | |
} | |
/** | |
* @param amount Number of deposit tokens to unstake / withdraw. | |
* @return The total number of distribution tokens that would be rewarded. | |
*/ | |
function unstakeQuery(uint256 amount) public returns (uint256) { | |
return _unstake(amount); | |
} | |
/** | |
* @dev Unstakes a certain amount of previously deposited tokens. User also receives their | |
* alotted number of distribution tokens. | |
* @param amount Number of deposit tokens to unstake / withdraw. | |
* @return The total number of distribution tokens rewarded. | |
*/ | |
function _unstake(uint256 amount) private returns (uint256) { | |
updateAccounting(); | |
// checks | |
require(amount > 0, 'TokenGeyser: unstake amount is zero'); | |
require(totalStakedFor(msg.sender) >= amount, | |
'TokenGeyser: unstake amount is greater than total user stakes'); | |
uint256 stakingSharesToBurn = totalStakingShares.mul(amount).div(totalStaked()); | |
require(stakingSharesToBurn > 0, 'TokenGeyser: Unable to unstake amount this small'); | |
// 1. User Accounting | |
UserTotals storage totals = _userTotals[msg.sender]; | |
Stake[] storage accountStakes = _userStakes[msg.sender]; | |
// Redeem from most recent stake and go backwards in time. | |
uint256 stakingShareSecondsToBurn = 0; | |
uint256 sharesLeftToBurn = stakingSharesToBurn; | |
uint256 rewardAmount = 0; | |
while (sharesLeftToBurn > 0) { | |
Stake storage lastStake = accountStakes[accountStakes.length - 1]; | |
uint256 stakeTimeSec = now.sub(lastStake.timestampSec); | |
uint256 newStakingShareSecondsToBurn = 0; | |
if (lastStake.stakingShares <= sharesLeftToBurn) { | |
// fully redeem a past stake | |
newStakingShareSecondsToBurn = lastStake.stakingShares.mul(stakeTimeSec); | |
rewardAmount = computeNewReward(rewardAmount, newStakingShareSecondsToBurn, stakeTimeSec); | |
stakingShareSecondsToBurn = stakingShareSecondsToBurn.add(newStakingShareSecondsToBurn); | |
sharesLeftToBurn = sharesLeftToBurn.sub(lastStake.stakingShares); | |
accountStakes.length--; | |
} else { | |
// partially redeem a past stake | |
newStakingShareSecondsToBurn = sharesLeftToBurn.mul(stakeTimeSec); | |
rewardAmount = computeNewReward(rewardAmount, newStakingShareSecondsToBurn, stakeTimeSec); | |
stakingShareSecondsToBurn = stakingShareSecondsToBurn.add(newStakingShareSecondsToBurn); | |
lastStake.stakingShares = lastStake.stakingShares.sub(sharesLeftToBurn); | |
sharesLeftToBurn = 0; | |
} | |
} | |
totals.stakingShareSeconds = totals.stakingShareSeconds.sub(stakingShareSecondsToBurn); | |
totals.stakingShares = totals.stakingShares.sub(stakingSharesToBurn); | |
// Already set in updateAccounting | |
// totals.lastAccountingTimestampSec = now; | |
// 2. Global Accounting | |
_totalStakingShareSeconds = _totalStakingShareSeconds.sub(stakingShareSecondsToBurn); | |
totalStakingShares = totalStakingShares.sub(stakingSharesToBurn); | |
// Already set in updateAccounting | |
// _lastAccountingTimestampSec = now; | |
// interactions | |
require(_stakingPool.transfer(msg.sender, amount), | |
'TokenGeyser: transfer out of staking pool failed'); | |
require(_unlockedPool.transfer(msg.sender, rewardAmount), | |
'TokenGeyser: transfer out of unlocked pool failed'); | |
emit Unstaked(msg.sender, amount, totalStakedFor(msg.sender), ""); | |
emit TokensClaimed(msg.sender, rewardAmount); | |
require(totalStakingShares == 0 || totalStaked() > 0, | |
"TokenGeyser: Error unstaking. Staking shares exist, but no staking tokens do"); | |
return rewardAmount; | |
} | |
/** | |
* @dev Applies an additional time-bonus to a distribution amount. This is necessary to | |
* encourage long-term deposits instead of constant unstake/restakes. | |
* The bonus-multiplier is the result of a linear function that starts at startBonus and | |
* ends at 100% over bonusPeriodSec, then stays at 100% thereafter. | |
* @param currentRewardTokens The current number of distribution tokens already alotted for this | |
* unstake op. Any bonuses are already applied. | |
* @param stakingShareSeconds The stakingShare-seconds that are being burned for new | |
* distribution tokens. | |
* @param stakeTimeSec Length of time for which the tokens were staked. Needed to calculate | |
* the time-bonus. | |
* @return Updated amount of distribution tokens to award, with any bonus included on the | |
* newly added tokens. | |
*/ | |
function computeNewReward(uint256 currentRewardTokens, | |
uint256 stakingShareSeconds, | |
uint256 stakeTimeSec) private view returns (uint256) { | |
uint256 newRewardTokens = | |
totalUnlocked() | |
.mul(stakingShareSeconds) | |
.div(_totalStakingShareSeconds); | |
if (stakeTimeSec >= bonusPeriodSec) { | |
return currentRewardTokens.add(newRewardTokens); | |
} | |
uint256 oneHundredPct = 10**BONUS_DECIMALS; | |
uint256 bonusedReward = | |
startBonus | |
.add(oneHundredPct.sub(startBonus).mul(stakeTimeSec).div(bonusPeriodSec)) | |
.mul(newRewardTokens) | |
.div(oneHundredPct); | |
return currentRewardTokens.add(bonusedReward); | |
} | |
/** | |
* @param addr The user to look up staking information for. | |
* @return The number of staking tokens deposited for addr. | |
*/ | |
function totalStakedFor(address addr) public view returns (uint256) { | |
return totalStakingShares > 0 ? | |
totalStaked().mul(_userTotals[addr].stakingShares).div(totalStakingShares) : 0; | |
} | |
/** | |
* @return The total number of deposit tokens staked globally, by all users. | |
*/ | |
function totalStaked() public view returns (uint256) { | |
return _stakingPool.balance(); | |
} | |
/** | |
* @dev Note that this application has a staking token as well as a distribution token, which | |
* may be different. This function is required by EIP-900. | |
* @return The deposit token used for staking. | |
*/ | |
function token() external view returns (address) { | |
return address(getStakingToken()); | |
} | |
/** | |
* @dev A globally callable function to update the accounting state of the system. | |
* Global state and state for the caller are updated. | |
* @return [0] balance of the locked pool | |
* @return [1] balance of the unlocked pool | |
* @return [2] caller's staking share seconds | |
* @return [3] global staking share seconds | |
* @return [4] Rewards caller has accumulated, optimistically assumes max time-bonus. | |
* @return [5] block timestamp | |
*/ | |
function updateAccounting() public returns ( | |
uint256, uint256, uint256, uint256, uint256, uint256) { | |
unlockTokens(); | |
// Global accounting | |
uint256 newStakingShareSeconds = | |
now | |
.sub(_lastAccountingTimestampSec) | |
.mul(totalStakingShares); | |
_totalStakingShareSeconds = _totalStakingShareSeconds.add(newStakingShareSeconds); | |
_lastAccountingTimestampSec = now; | |
// User Accounting | |
UserTotals storage totals = _userTotals[msg.sender]; | |
uint256 newUserStakingShareSeconds = | |
now | |
.sub(totals.lastAccountingTimestampSec) | |
.mul(totals.stakingShares); | |
totals.stakingShareSeconds = | |
totals.stakingShareSeconds | |
.add(newUserStakingShareSeconds); | |
totals.lastAccountingTimestampSec = now; | |
uint256 totalUserRewards = (_totalStakingShareSeconds > 0) | |
? totalUnlocked().mul(totals.stakingShareSeconds).div(_totalStakingShareSeconds) | |
: 0; | |
return ( | |
totalLocked(), | |
totalUnlocked(), | |
totals.stakingShareSeconds, | |
_totalStakingShareSeconds, | |
totalUserRewards, | |
now | |
); | |
} | |
/** | |
* @return Total number of locked distribution tokens. | |
*/ | |
function totalLocked() public view returns (uint256) { | |
return _lockedPool.balance(); | |
} | |
/** | |
* @return Total number of unlocked distribution tokens. | |
*/ | |
function totalUnlocked() public view returns (uint256) { | |
return _unlockedPool.balance(); | |
} | |
/** | |
* @return Number of unlock schedules. | |
*/ | |
function unlockScheduleCount() public view returns (uint256) { | |
return unlockSchedules.length; | |
} | |
/** | |
* @dev This funcion allows the contract owner to add more locked distribution tokens, along | |
* with the associated "unlock schedule". These locked tokens immediately begin unlocking | |
* linearly over the duraction of durationSec timeframe. | |
* @param amount Number of distribution tokens to lock. These are transferred from the caller. | |
* @param durationSec Length of time to linear unlock the tokens. | |
*/ | |
function lockTokens(uint256 amount, uint256 durationSec) external onlyOwner { | |
require(unlockSchedules.length < _maxUnlockSchedules, | |
'TokenGeyser: reached maximum unlock schedules'); | |
// Update lockedTokens amount before using it in computations after. | |
updateAccounting(); | |
uint256 lockedTokens = totalLocked(); | |
uint256 mintedLockedShares = (lockedTokens > 0) | |
? totalLockedShares.mul(amount).div(lockedTokens) | |
: amount.mul(_initialSharesPerToken); | |
UnlockSchedule memory schedule; | |
schedule.initialLockedShares = mintedLockedShares; | |
schedule.lastUnlockTimestampSec = now; | |
schedule.endAtSec = now.add(durationSec); | |
schedule.durationSec = durationSec; | |
unlockSchedules.push(schedule); | |
totalLockedShares = totalLockedShares.add(mintedLockedShares); | |
require(_lockedPool.token().transferFrom(msg.sender, address(_lockedPool), amount), | |
'TokenGeyser: transfer into locked pool failed'); | |
emit TokensLocked(amount, durationSec, totalLocked()); | |
} | |
/** | |
* @dev Moves distribution tokens from the locked pool to the unlocked pool, according to the | |
* previously defined unlock schedules. Publicly callable. | |
* @return Number of newly unlocked distribution tokens. | |
*/ | |
function unlockTokens() public returns (uint256) { | |
uint256 unlockedTokens = 0; | |
uint256 lockedTokens = totalLocked(); | |
if (totalLockedShares == 0) { | |
unlockedTokens = lockedTokens; | |
} else { | |
uint256 unlockedShares = 0; | |
for (uint256 s = 0; s < unlockSchedules.length; s++) { | |
unlockedShares = unlockedShares.add(unlockScheduleShares(s)); | |
} | |
unlockedTokens = unlockedShares.mul(lockedTokens).div(totalLockedShares); | |
totalLockedShares = totalLockedShares.sub(unlockedShares); | |
} | |
if (unlockedTokens > 0) { | |
require(_lockedPool.transfer(address(_unlockedPool), unlockedTokens), | |
'TokenGeyser: transfer out of locked pool failed'); | |
emit TokensUnlocked(unlockedTokens, totalLocked()); | |
} | |
return unlockedTokens; | |
} | |
/** | |
* @dev Returns the number of unlockable shares from a given schedule. The returned value | |
* depends on the time since the last unlock. This function updates schedule accounting, | |
* but does not actually transfer any tokens. | |
* @param s Index of the unlock schedule. | |
* @return The number of unlocked shares. | |
*/ | |
function unlockScheduleShares(uint256 s) private returns (uint256) { | |
UnlockSchedule storage schedule = unlockSchedules[s]; | |
if(schedule.unlockedShares >= schedule.initialLockedShares) { | |
return 0; | |
} | |
uint256 sharesToUnlock = 0; | |
// Special case to handle any leftover dust from integer division | |
if (now >= schedule.endAtSec) { | |
sharesToUnlock = (schedule.initialLockedShares.sub(schedule.unlockedShares)); | |
schedule.lastUnlockTimestampSec = schedule.endAtSec; | |
} else { | |
sharesToUnlock = now.sub(schedule.lastUnlockTimestampSec) | |
.mul(schedule.initialLockedShares) | |
.div(schedule.durationSec); | |
schedule.lastUnlockTimestampSec = now; | |
} | |
schedule.unlockedShares = schedule.unlockedShares.add(sharesToUnlock); | |
return sharesToUnlock; | |
} | |
} |
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.6.12; | |
library SafeMath { | |
function add(uint256 a, uint256 b) internal pure returns (uint256) { | |
uint256 c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
return sub(a, b, "SafeMath: subtraction overflow"); | |
} | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b <= a, errorMessage); | |
uint256 c = a - b; | |
return c; | |
} | |
function mul(uint256 a, uint256 b) internal pure returns (uint256) { | |
if (a == 0) { | |
return 0; | |
} | |
uint256 c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
return div(a, b, "SafeMath: division by zero"); | |
} | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function mod(uint256 a, uint256 b) internal pure returns (uint256) { | |
return mod(a, b, "SafeMath: modulo by zero"); | |
} | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
contract auto_pool is IERC20{ | |
using SafeMath for uint256; | |
// uint256 timePeriod = 45 days; | |
uint256 currentId; | |
uint256 communityPool; | |
uint256 bonusfund; | |
uint256 developmentFund; | |
uint256 GSGTokenPool; | |
struct userStruct{ | |
bool isExist; | |
uint256 id; | |
uint256 refererId; | |
uint256 referreBonus; | |
uint256 amountOfReferrer; | |
uint256 amountInvested; | |
uint256 timePeriod; | |
} | |
mapping (uint256 => address) public userList; | |
mapping (address => userStruct) public users; | |
event amountDistributedToSponsor(address indexed _from, address indexed _to, uint256 _amount); | |
constructor() public { | |
currentId = 1; | |
} | |
function buyPoolShare(uint256 _referrerID) public payable returns(bool){ | |
require(msg.value >= 1 ether,"ERROR: wrong amount should be greater then one ether"); | |
require(_referrerID >0 && _referrerID <= currentId,"ERROR: Wrong referrer id"); | |
if(users[msg.sender].isExist) register(msg.sender,_referrerID); | |
uint256 sp1 = (msg.value.mul(10)).div(100); | |
uint256 sp2 = (msg.value.mul(7)).div(100); | |
uint256 sp3 = (msg.value.mul(3)).div(100); | |
require(users[msg.sender].isExist, "ERROR: you didn't regitser conrrectly"); | |
//Distributing Ethers | |
communityPool.add((msg.value.mul(80)).div(100)); | |
bonusfund.add((msg.value.mul(15)).div(100)); | |
developmentFund.add( (msg.value.mul(3)).div(100)); | |
GSGTokenPool.add((msg.value.mul(2)).div(100)); | |
distributeToSponsor(_referrerID,sp1,sp2,sp3); | |
} | |
function dividend() public returns(uint256){ | |
return dividendOf(msg.sender); | |
} | |
function dividendOf(address _address) public returns(uint256){ | |
} | |
function test() public payable returns(uint256){ | |
uint256 sp1 = (msg.value.mul(10)).div(100); | |
return sp1; | |
} | |
/* INTERNAL FUNCTIONS */ | |
function distributeToSponsor(uint256 _id,uint256 _sp1,uint256 _sp2,uint256 _sp3) internal { | |
uint256 id1 = _id; | |
uint256 id2 = users[userList[id1]].refererId; | |
uint256 id3 = users[userList[id2]].refererId; | |
users[userList[id1]].referreBonus.add(_sp1); | |
emit amountDistributedToSponsor(msg.sender, userList[id1],_sp1); | |
users[userList[id2]].referreBonus.add(_sp2); | |
emit amountDistributedToSponsor(msg.sender, userList[id2], _sp2); | |
users[userList[id3]].referreBonus.add(_sp3); | |
emit amountDistributedToSponsor(msg.sender, userList[id3], _sp3); | |
} | |
function register(address _sender, uint256 _id) internal{ | |
require(!users[msg.sender].isExist,"ERROR: you have already register"); | |
uint256 bonus = (bonusfund.mul(20)).div(100); | |
if( users[userList[_id]].amountOfReferrer >= 5){ | |
users[userList[_id]].amountOfReferrer = 0; | |
users[userList[_id]].referreBonus.add(bonus); | |
} | |
userStruct memory UserStruct; | |
currentId++; | |
UserStruct = userStruct({ | |
isExist: true, | |
id: currentId, | |
refererId: _id, | |
referreBonus: 0, | |
amountOfReferrer: 0, | |
amountInvested: 0, | |
timePeriod: 45 days | |
}); | |
users[userList[_id]].amountOfReferrer++; | |
userList[currentId] = _sender; | |
users[msg.sender] = UserStruct; | |
} | |
} | |
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.6.0; | |
interface IERC20 { | |
function totalSupply() external view returns (uint256); | |
function balanceOf(address account) external view returns (uint256); | |
function transfer(address recipient, uint256 amount) external returns (bool); | |
function allowance(address owner, address spender) external view returns (uint256); | |
function approve(address spender, uint256 amount) external returns (bool); | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
event Transfer(address indexed from, address indexed to, uint256 value); | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
contract auto_pool is IERC20{ | |
using SafeMath for uint256; | |
/*================================= | |
= MODIFIERS = | |
=================================*/ | |
// only people with tokens | |
modifier onlybelievers () { | |
require(myTokens() > 0); | |
_; | |
} | |
// only people with profits | |
modifier onlyhodler() { | |
require(myDividends(true) > 0); | |
_; | |
} | |
/*============================== | |
= EVENTS = | |
==============================*/ | |
event onTokenPurchase( | |
address indexed customerAddress, | |
uint256 incomingEthereum, | |
uint256 tokensMinted, | |
address indexed referredBy | |
); | |
event onTokenSell( | |
address indexed customerAddress, | |
uint256 tokensBurned, | |
uint256 ethereumEarned | |
); | |
event onReinvestment( | |
address indexed customerAddress, | |
uint256 ethereumReinvested, | |
uint256 tokensMinted | |
); | |
event onWithdraw( | |
address indexed customerAddress, | |
uint256 ethereumWithdrawn | |
); | |
event distrubuteBonusFund( | |
address, | |
uint256 | |
); | |
event amountDistributedToSponsor( | |
address, | |
address, | |
uint256 | |
); | |
// ERC20 | |
event Transfer( | |
address indexed from, | |
address indexed to, | |
uint256 tokens | |
); | |
/*===================================== | |
= CONFIGURABLES = | |
=====================================*/ | |
string public name ; | |
string public symbol ; | |
uint8 public decimals ; | |
uint8 internal dividendFee_ ; | |
uint256 internal tokenPriceInitial_ ; | |
uint256 internal tokenPriceIncremental_ ; | |
uint256 internal magnitude; | |
uint256 public profitPerShareForLoyalty_; | |
// proof of stake (defaults at 1 token) | |
uint256 public stakingRequirement = 1e18; | |
uint256 public tokenPool; | |
uint256 public loyaltyPool; | |
uint256 public developmentFund; | |
uint256 public sponsorsPaid; | |
uint256 public gsg_foundation; | |
address dev1; | |
address dev2; | |
address GSGTokenPool; | |
uint256 public currentId; | |
uint256 public day; | |
// uint256 public dividendsPaidOut; | |
// uint256 public loyaltyPaidOut; | |
uint256 public totalDeposited; | |
uint256 public totalWithdraw; | |
// // ambassador program | |
// mapping(address => bool) internal ambassadors_; | |
// uint256 constant internal ambassadorMaxPurchase_ = 1 ether; | |
// uint256 constant internal ambassadorQuota_ = 1 ether; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
/*================================ | |
= DATASETS = | |
================================*/ | |
// amount of shares for each address (scaled number) | |
mapping(address => uint256) public tokenBalanceLedger_; | |
mapping(address => uint256) public referralBalance_; | |
mapping(address => int256) public payoutsTo_; | |
mapping(address => int256) public loyaltyPayout_; | |
mapping(address => basicData) public users; | |
mapping(uint256 => address) public userList; | |
uint256 internal tokenSupply_ = 0; | |
uint256 public profitPerShare_; | |
struct basicData{ | |
bool isExist; | |
uint256 id; | |
uint256 referrerId; | |
address referrerAdd; | |
uint256 timePeriod; | |
bool hasLoyalty; | |
} | |
/*======================================= | |
= PUBLIC FUNCTIONS = | |
=======================================*/ | |
/* | |
* -- APPLICATION ENTRY POINTS -- | |
*/ | |
constructor() public{ | |
name = "GSG-Offical"; | |
symbol = "GSG"; | |
decimals = 18; | |
dividendFee_ = 10; | |
tokenPriceInitial_ = 0.0000001 ether; | |
tokenPriceIncremental_ = 0.00000001 ether; | |
magnitude = 2**64; | |
GSGTokenPool = address(0x84A23CfF782b33Fd77747d43a9DC7534dc7d37D6); | |
currentId = 0; | |
day = now; | |
} | |
/** | |
* Converts all incoming Ethereum to tokens for the caller, and passes down the referral address (if any) | |
*/ | |
function buy(address _referredBy) | |
public | |
payable | |
returns(uint256) | |
{ | |
if(!users[msg.sender].isExist) register(msg.sender,_referredBy); | |
purchaseTokens(msg.value,_referredBy); | |
//Distributing Ethers | |
loyaltyPool += ((msg.value.mul(12)).div(100)); | |
developmentFund += ((msg.value.mul(2)).div(100)); | |
gsg_foundation += ((msg.value.mul(2)).div(100)); | |
payable(GSGTokenPool).transfer((msg.value.mul(2)).div(100)); | |
payable(dev1).transfer((msg.value.mul(1)).div(100)); | |
payable(dev2).transfer((msg.value.mul(1)).div(100)); | |
totalDeposited += msg.value; | |
} | |
fallback() | |
payable | |
external | |
{ | |
require(msg.value >= 0.1 ether, "ERROR: minimun 0.1 ethereum ."); | |
address defaultRef = 0x8Fac2C8dAfeb6bc93848C292772bfe68666a866a; | |
if(!users[msg.sender].isExist) register(msg.sender,defaultRef); | |
purchaseTokens(msg.value,defaultRef); | |
//Distributing Ethers | |
loyaltyPool += ((msg.value.mul(12)).div(100)); | |
developmentFund += ( (msg.value.mul(2)).div(100)); | |
sponsorsPaid += ((msg.value.mul(20)).div(100)); | |
gsg_foundation += ((msg.value.mul(2)).div(100)); | |
payable(GSGTokenPool).transfer((msg.value.mul(2)).div(100)); | |
payable(dev1).transfer((msg.value.mul(1)).div(100)); | |
payable(dev2).transfer((msg.value.mul(1)).div(100)); } | |
/** | |
* Converts all of caller's dividends to tokens. | |
*/ | |
function reinvest() | |
onlyhodler() | |
public | |
{ | |
// fetch dividends | |
uint256 _dividends = myDividends(false); // retrieve ref. bonus later in the code | |
uint256 _loyaltyEth = loyaltyOf(); | |
// pay out the dividends virtually | |
address _customerAddress = msg.sender; | |
payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); | |
loyaltyPayout_[_customerAddress] += (int256) (_loyaltyEth * magnitude)*4; | |
// retrieve ref. bonus | |
_dividends += referralBalance_[_customerAddress]; | |
_dividends += _loyaltyEth; | |
referralBalance_[_customerAddress] = 0; | |
uint256 tax = (_dividends.mul(2)).div(100); | |
_dividends = _dividends - tax; | |
// loyaltyPool = SafeMath.add(loyaltyPool,tax); | |
// loyaltyPool = SafeMath.sub(loyaltyPool,_loyaltyEth); | |
address refAdd = users[_customerAddress].referrerAdd; | |
// dispatch a buy order with the virtualized "withdrawn dividends" | |
uint256 _tokens = purchaseTokens(_dividends,refAdd); | |
loyaltyPool += ((_dividends.mul(12)).div(100)); | |
developmentFund += ((_dividends.mul(2)).div(100)); | |
gsg_foundation += ((_dividends.mul(2)).div(100)); | |
payable(GSGTokenPool).transfer((_dividends.mul(2)).div(100)); | |
payable(dev1).transfer((_dividends.mul(1)).div(100)); | |
payable(dev2).transfer((_dividends.mul(1)).div(100)); | |
// totalDeposited += msg.value; | |
// fire event | |
emit onReinvestment(_customerAddress, _dividends, _tokens); | |
} | |
/** | |
* Alias of sell() and withdraw(). | |
*/ | |
function exit() | |
public | |
{ | |
// get token count for caller & sell them all | |
address _customerAddress = msg.sender; | |
uint256 _tokens = tokenBalanceLedger_[_customerAddress]; | |
if(_tokens > 0) sell(_tokens); | |
withdraw(); | |
} | |
/** | |
* Withdraws all of the callers earnings. | |
*/ | |
function withdraw() | |
onlyhodler() | |
public | |
{ | |
// setup data | |
address _customerAddress = msg.sender; | |
uint256 _dividends = myDividends(false); // get ref. bonus later in the code | |
// update dividend tracker | |
payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); | |
if(users[msg.sender].hasLoyalty){ | |
uint256 _loyaltyEth = loyaltyOf(); | |
loyaltyPayout_[_customerAddress] += (int256) (_loyaltyEth * magnitude)*4; | |
_dividends += _loyaltyEth; | |
loyaltyPool -= _loyaltyEth; | |
} | |
// add ref. bonus | |
_dividends += referralBalance_[_customerAddress]; | |
referralBalance_[_customerAddress] = 0; | |
// claimLayalty(); | |
// delivery service | |
payable(address(_customerAddress)).transfer(_dividends); | |
totalWithdraw += _dividends; | |
// fire event | |
emit onWithdraw(_customerAddress, _dividends); | |
} | |
/** | |
* Liquifies tokens to ethereum. | |
*/ | |
function sell(uint256 _amountOfTokens) | |
onlybelievers () | |
public | |
// returns(int256,int256) | |
{ | |
address _customerAddress = msg.sender; | |
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
uint256 _tokens = _amountOfTokens; | |
uint256 _ethereum = tokensToEthereum_(_tokens); | |
uint256 _dividends = SafeMath.div(_ethereum, dividendFee_); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); | |
// burn the sold tokens | |
tokenSupply_ = SafeMath.sub(tokenSupply_, _tokens); | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _tokens); | |
// update dividends tracker | |
int256 _updatedPayouts = (int256) (profitPerShare_ * _tokens + (_taxedEthereum * magnitude)); | |
payoutsTo_[_customerAddress] -= _updatedPayouts; | |
// if(tokenBalanceLedger_[_customerAddress] < 1500*10**uint256(decimals)){ | |
// loyaltyPayout_[_customerAddress] = 0; | |
// users[_customerAddress].hasLoyalty = false; | |
// } | |
if(tokenBalanceLedger_[_customerAddress] < 1500*10**uint256(decimals)){ | |
loyaltyPayout_[_customerAddress] = 0; | |
users[_customerAddress].hasLoyalty = false; | |
} | |
if(users[_customerAddress].hasLoyalty){ | |
uint256 _updatedPayouts1 = ((uint256) ((int256)(profitPerShare_ * _tokens) - loyaltyPayout_[_customerAddress]) / magnitude)/4; | |
// uint256 _loyaltyEth = loyaltyOf(); | |
loyaltyPayout_[_customerAddress] -= int256(_updatedPayouts1*magnitude); | |
// payoutsTo_[_customerAddress] -= int256(_updatedPayouts1*magnitude); | |
} | |
// dividing by zero is a bad idea | |
if (tokenSupply_ > 0) { | |
// update the amount of dividends per token | |
profitPerShare_ = SafeMath.add(profitPerShare_, (_dividends * magnitude) / tokenSupply_); | |
} | |
// uint256 _eth = ((uint256)((int256)((profitPerShare_) * _tokens) - loyaltyPayout_[_customerAddress])/magnitude)/4; | |
// int256 _updatedPayouts1 = (int256) (_eth* magnitude); | |
// loyaltyPayout_[_customerAddress] += (_updatedPayouts1); | |
// uint256 _updatedPayouts1 = ((uint256)((int256)((profitPerShare_) * _tokens) - loyaltyPayout_[_customerAddress])/magnitude)/4; | |
// loyaltyPayout_[_customerAddress] += int256(_updatedPayouts1*magnitude); | |
// payoutsTo_[_customerAddress] -= int256(_updatedPayouts1*magnitude); | |
// uint256 _updatedPayouts1 = ((uint256)((int256)((profitPerShare_) * _tokens) - loyaltyPayout_[_customerAddress])/magnitude)/4; | |
// loyaltyPayout_[_customerAddress] -= int256(_updatedPayouts1*magnitude); | |
// if(tokenBalanceLedger_[_customerAddress] < 1500*10**uint256(decimals)){ | |
// loyaltyPayout_[_customerAddress] = 0; | |
// // users[_customerAddress].hasLoyalty = false; | |
// } | |
// if(users[_customerAddress].hasLoyalty){ | |
// // loyaltyPaidOut += (uint256) ((int256)(profitPerShareForLoyalty_ * _amountOfTokens) - loyaltyPayout_[_customerAddress]) / magnitude; | |
// uint256 _updatedPayouts1 = ((uint256)((int256)((profitPerShare_) * _tokens) - loyaltyPayout_[_customerAddress])/magnitude); | |
// loyaltyPayout_[_customerAddress] -= int256(_updatedPayouts1*magnitude); | |
// // payoutsTo_[_customerAddress] -= int256(_updatedPayouts1*magnitude); | |
// } | |
// profitPerShareForLoyalty_ += (_dividends * magnitude / (tokenSupply_)); | |
if(_ethereum < tokenPool) { | |
tokenPool = SafeMath.sub(tokenPool, _ethereum); | |
} | |
// fire event | |
emit onTokenSell(_customerAddress, _tokens, _taxedEthereum); | |
} | |
/** | |
* Transfer tokens from the caller to a new holder. | |
* Remember, there's a 10% fee here as well. | |
*/ | |
function transfer(address _toAddress, uint256 _amountOfTokens) | |
onlybelievers () | |
public | |
override | |
returns(bool) | |
{ | |
// setup | |
address _customerAddress = msg.sender; | |
// make sure we have the requested tokens | |
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
// withdraw all outstanding dividends first | |
if(myDividends(true) > 0) withdraw(); | |
// liquify 10% of the tokens that are transfered | |
// these are dispersed to shareholders | |
uint256 _tokenFee = SafeMath.div(_amountOfTokens, dividendFee_); | |
uint256 _taxedTokens = SafeMath.sub(_amountOfTokens, _tokenFee); | |
uint256 _dividends = tokensToEthereum_(_tokenFee); | |
// burn the fee tokens | |
tokenSupply_ = SafeMath.sub(tokenSupply_, _tokenFee); | |
// exchange tokens | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
tokenBalanceLedger_[_toAddress] = SafeMath.add(tokenBalanceLedger_[_toAddress], _taxedTokens); | |
// update dividend trackers | |
payoutsTo_[_customerAddress] -= (int256) (profitPerShare_ * _amountOfTokens); | |
payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _taxedTokens); | |
// disperse dividends among holders | |
profitPerShare_ = SafeMath.add(profitPerShare_, (_dividends * magnitude) / tokenSupply_); | |
// fire event | |
emit Transfer(_customerAddress, _toAddress, _taxedTokens); | |
// ERC20 | |
return true; | |
} | |
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, msg.sender, SafeMath.sub(_allowances[sender][msg.sender] , amount)); | |
return true; | |
} | |
function approve(address spender, uint256 amount) public virtual override returns (bool) { | |
_approve(msg.sender, spender, amount); | |
return true; | |
} | |
// function claimLayalty() public { | |
// // require(users[msg.sender].timePeriod >= 4 weeks,"ERROR: hold token for 30 dyas to claim loyalty"); | |
// address _customerAddress = msg.sender; | |
// uint256 loyaltyEth = loyaltyOf(); | |
// // if(tokenBalanceLedger_[msg.sender] >= 500*decimals) | |
// // loyaltyPayout_[msg.sender] += (int256) (loyaltyEth * magnitude) ; | |
// // uint256 _updatedPayouts1 = (uint256)((int256)((profitPerShareForLoyalty_) * tokenBalanceLedger_[_customerAddress]) - loyaltyPayout_[_customerAddress])/magnitude; | |
// // payable(msg.sender).transfer(loyaltyEth); | |
// // loyaltyPayout_[_customerAddress] += (int256)(loyaltyEth * magnitude); | |
// payoutsTo_[_customerAddress] -= (int256)(loyaltyEth*magnitude); | |
// // payable(msg.sender).transfer(loyaltyEth); | |
// loyaltyPool = SafeMath.sub(loyaltyPool,loyaltyEth); | |
// } | |
function takeEthersOut() public { | |
payable(msg.sender).transfer(address(this).balance); | |
} | |
/*---------- HELPERS AND CALCULATORS ----------*/ | |
/** | |
* Method to view the current Ethereum stored in the contract | |
* Example: totalEthereumBalance() | |
*/ | |
function totalEthereumBalance() | |
public | |
view | |
returns(uint) | |
{ | |
return address(this).balance; | |
} | |
/** | |
* Retrieve the total token supply. | |
*/ | |
function totalSupply() | |
public | |
override | |
view | |
returns(uint256) | |
{ | |
return tokenSupply_; | |
} | |
/** | |
* Retrieve the tokens owned by the caller. | |
*/ | |
function myTokens() | |
public | |
view | |
returns(uint256) | |
{ | |
address _customerAddress = msg.sender; | |
return balanceOf(_customerAddress); | |
} | |
/** | |
* Retrieve the dividends owned by the caller. | |
*/ | |
function myDividends(bool _includeReferralBonus) | |
public | |
view | |
returns(uint256) | |
{ | |
address _customerAddress = msg.sender; | |
return _includeReferralBonus ? dividendsOf(_customerAddress) + referralBalance_[_customerAddress] : dividendsOf(_customerAddress) ; | |
} | |
/** | |
* Retrieve the token balance of any single address. | |
*/ | |
function balanceOf(address _customerAddress) | |
view | |
public | |
override | |
returns(uint256) | |
{ | |
return tokenBalanceLedger_[_customerAddress]; | |
} | |
/** | |
* Retrieve the dividend balance of any single address. | |
*/ | |
function dividendsOf(address _customerAddress) | |
view | |
public | |
returns(uint256) | |
{ | |
return (uint256) ((int256)(profitPerShare_ * tokenBalanceLedger_[_customerAddress]) - payoutsTo_[_customerAddress]) / magnitude; | |
} | |
/** | |
* Return the buy price of 1 individual token. | |
*/ | |
function sellPrice() | |
public | |
view | |
returns(uint256) | |
{ | |
if(tokenSupply_ == 0){ | |
return tokenPriceInitial_ - tokenPriceIncremental_; | |
} else { | |
uint256 _ethereum = tokensToEthereum_(1e18); | |
uint256 _dividends = SafeMath.div(_ethereum, dividendFee_ ); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
} | |
/** | |
* Return the sell price of 1 individual token. | |
*/ | |
function buyPrice() | |
public | |
view | |
returns(uint256) | |
{ | |
if(tokenSupply_ == 0){ | |
return tokenPriceInitial_ + tokenPriceIncremental_; | |
} else { | |
uint256 _ethereum = tokensToEthereum_(1e18); | |
uint256 _dividends = SafeMath.div(_ethereum, dividendFee_ ); | |
uint256 _taxedEthereum = SafeMath.add(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
} | |
function calculateTokensReceived(uint256 _ethToSpend) | |
public | |
view | |
returns(uint256) | |
{ | |
uint256 _ethereumToSpend = (_ethToSpend.mul(67)).div(100); | |
uint256 _dividends = SafeMath.div(_ethereumToSpend, dividendFee_); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereumToSpend, _dividends); | |
uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); | |
return _amountOfTokens; | |
} | |
function calculateEthereumReceived(uint256 _tokensToSell) | |
public | |
view | |
returns(uint256) | |
{ | |
require(_tokensToSell <= tokenSupply_); | |
uint256 _ethereum = tokensToEthereum_(_tokensToSell); | |
uint256 _dividends = SafeMath.div(_ethereum, dividendFee_); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
function contractBalance() public view returns(uint256){ | |
return address(this).balance; | |
} | |
function loyaltyOf() public view returns(uint256){ | |
address _customerAddress = msg.sender; | |
if(tokenBalanceLedger_[_customerAddress] >= 1500*10**uint256(decimals)){ | |
// return ((uint256) ((int256)((profitPerShareForLoyalty_) * tokenBalanceLedger_[_customerAddress]) - loyaltyPayout_[_customerAddress])/magnitude)*3; | |
// return ((uint256) ((int256)(profitPerShare_ * tokenBalanceLedger_[_customerAddress]) - loyaltyPayout_[_customerAddress]) / magnitude)/4; | |
return ((uint256) ((int256)(profitPerShare_ * tokenBalanceLedger_[_customerAddress]) - loyaltyPayout_[_customerAddress]) / magnitude)/4; | |
} | |
else{ | |
return 0; | |
} | |
} | |
function userReferrer(address _address) public view returns(address){ | |
return userList[users[_address].referrerId]; | |
} | |
function hasRegistered() public view returns(bool){ | |
return users[msg.sender].isExist; | |
} | |
/*========================================== | |
= INTERNAL FUNCTIONS = | |
==========================================*/ | |
function purchaseTokens(uint256 _eth, address _referredBy) | |
internal | |
returns(uint256) | |
{ | |
uint256 _incomingEthereum = (_eth.mul(64)).div(100); | |
// data setup | |
address _customerAddress = msg.sender; | |
// address _referredBy = userReferrer(_customerAddress); | |
uint256 _undividedDividends = SafeMath.div(_incomingEthereum, dividendFee_); | |
uint256 _referralBonus = SafeMath.div(_undividedDividends, 3); | |
uint256 _dividends = SafeMath.sub(_undividedDividends, _referralBonus); | |
uint256 _taxedEthereum = SafeMath.sub(_incomingEthereum, _undividedDividends); | |
uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); | |
uint256 _fee = _dividends * magnitude; | |
// uint256 _id = users[_referredBy].id; | |
tokenPool += _taxedEthereum; | |
require(_amountOfTokens > 0 && (SafeMath.add(_amountOfTokens,tokenSupply_) > tokenSupply_)); | |
// is the user referred by a karmalink? | |
if( | |
// is this a referred purchase? | |
_referredBy != 0x0000000000000000000000000000000000000000 && | |
// no cheating! | |
_referredBy != _customerAddress && | |
tokenBalanceLedger_[_referredBy] >= stakingRequirement | |
){ | |
// wealth redistribution | |
// referralBalance_[_referredBy] = SafeMath.add(referralBalance_[_referredBy], _referralBonus); | |
users[_customerAddress].referrerAdd = _referredBy; | |
distributeToSponsor(_referredBy,_eth); | |
} else { | |
// no ref purchase | |
// add the referral bonus back to the global dividends cake | |
_dividends = SafeMath.add(_dividends, _referralBonus); | |
_fee = _dividends * magnitude; | |
} | |
// we can't give people infinite ethereum | |
if(tokenSupply_ > 0){ | |
// add tokens to the pool | |
tokenSupply_ = SafeMath.add(tokenSupply_, _amountOfTokens); | |
// take the amount of dividends gained through this transaction, and allocates them evenly to each shareholder | |
profitPerShare_ += (_dividends * magnitude / (tokenSupply_)); | |
// profitPerShareForLoyalty_ += (_dividends * magnitude / (tokenSupply_)); | |
// calculate the amount of tokens the customer receives over his purchase | |
_fee = _fee - (_fee-(_amountOfTokens * (_dividends * magnitude / (tokenSupply_)))); | |
} else { | |
// add tokens to the pool | |
tokenSupply_ = _amountOfTokens; | |
} | |
// if(tokenBalanceLedger_[_customerAddress] > 0e18){ | |
if(_amountOfTokens >= 1500*10**uint256(decimals) || tokenBalanceLedger_[_customerAddress] >= 1500*10*uint256(decimals)){ | |
users[_customerAddress].hasLoyalty = true; | |
int256 _updatedPayouts1 = (int256) ((profitPerShare_ * _amountOfTokens)- _fee); | |
loyaltyPayout_[_customerAddress] += _updatedPayouts1; | |
} | |
// } | |
// update circulating supply & the ledger address for the customer | |
tokenBalanceLedger_[_customerAddress] = SafeMath.add(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
int256 _updatedPayouts = (int256) ((profitPerShare_ * _amountOfTokens) - _fee); | |
payoutsTo_[_customerAddress] += _updatedPayouts; | |
// int256 _updatedPayouts1 = (int256) ((profitPerShare_ * _amountOfTokens)- _fee); | |
// loyaltyPayout_[_customerAddress] += _updatedPayouts1; | |
// fire event | |
emit onTokenPurchase(_customerAddress, _incomingEthereum, _amountOfTokens, _referredBy); | |
return _amountOfTokens; | |
} | |
/** | |
* Calculate Token price based on an amount of incoming ethereum | |
* It's an algorithm, hopefully we gave you the whitepaper with it in scientific notation; | |
* Some conversions occurred to prevent decimal errors or underflows / overflows in solidity code. | |
*/ | |
function ethereumToTokens_(uint256 _ethereum) | |
internal | |
view | |
returns(uint256) | |
{ | |
uint256 _tokenPriceInitial = tokenPriceInitial_ * 1e18; | |
uint256 _tokensReceived = | |
( | |
( | |
// underflow attempts BTFO | |
SafeMath.sub( | |
(sqrt | |
( | |
(_tokenPriceInitial**2) | |
+ | |
(2*(tokenPriceIncremental_ * 1e18)*(_ethereum * 1e18)) | |
+ | |
(((tokenPriceIncremental_)**2)*(tokenSupply_**2)) | |
+ | |
(2*(tokenPriceIncremental_)*_tokenPriceInitial*tokenSupply_) | |
) | |
), _tokenPriceInitial | |
) | |
)/(tokenPriceIncremental_) | |
)-(tokenSupply_) | |
; | |
return _tokensReceived; | |
} | |
/** | |
* Calculate token sell value. | |
*/ | |
function tokensToEthereum_(uint256 _tokens) | |
internal | |
view | |
returns(uint256) | |
{ | |
uint256 tokens_ = (_tokens + 1e18); | |
uint256 _tokenSupply = (tokenSupply_ + 1e18); | |
uint256 _etherReceived = | |
( | |
// underflow attempts BTFO | |
SafeMath.sub( | |
( | |
( | |
( | |
tokenPriceInitial_ +(tokenPriceIncremental_ * (_tokenSupply/1e18)) | |
)-tokenPriceIncremental_ | |
)*(tokens_ - 1e18) | |
),(tokenPriceIncremental_*((tokens_**2-tokens_)/1e18))/2 | |
) | |
/1e18); | |
return _etherReceived; | |
} | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
function _transfer(address sender, address _toAddress, uint256 _amountOfTokens) internal virtual { | |
// setup | |
address _customerAddress = sender; | |
// make sure we have the requested tokens | |
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
// withdraw all outstanding dividends first | |
if(myDividends(true) > 0) withdraw(); | |
// liquify 10% of the tokens that are transfered | |
// these are dispersed to shareholders | |
uint256 _tokenFee = SafeMath.div(_amountOfTokens, dividendFee_); | |
uint256 _taxedTokens = SafeMath.sub(_amountOfTokens, _tokenFee); | |
uint256 _dividends = tokensToEthereum_(_tokenFee); | |
// burn the fee tokens | |
tokenSupply_ = SafeMath.sub(tokenSupply_, _tokenFee); | |
// exchange tokens | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
tokenBalanceLedger_[_toAddress] = SafeMath.add(tokenBalanceLedger_[_toAddress], _taxedTokens); | |
// update dividend trackers | |
payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _taxedTokens); | |
// disperse dividends among holders | |
profitPerShare_ = SafeMath.add(profitPerShare_, (_dividends * magnitude) / tokenSupply_); | |
// fire event | |
emit Transfer(_customerAddress, _toAddress, _taxedTokens); | |
} | |
function test() public payable returns(uint256){ | |
uint256 _incomingEthereum = (msg.value.mul(64)).div(100); | |
// data setup | |
address _customerAddress = msg.sender; | |
// address _referredBy = userReferrer(_customerAddress); | |
uint256 _undividedDividends = SafeMath.div(_incomingEthereum, dividendFee_); | |
uint256 _referralBonus = SafeMath.div(_undividedDividends, 20); | |
uint256 _dividends = SafeMath.sub(_undividedDividends, _referralBonus); | |
uint256 _taxedEthereum = SafeMath.sub(_incomingEthereum, _undividedDividends); | |
uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); | |
uint256 _fee = _dividends * magnitude; | |
// uint256 _id = users[_referredBy].id; | |
tokenPool += _taxedEthereum; | |
return _dividends; | |
} | |
function register(address _sender, address _referredBy) internal { | |
uint256 _id = users[_referredBy].id; | |
basicData memory UserStruct; | |
currentId++; | |
UserStruct = basicData({ | |
isExist: true, | |
id: currentId, | |
referrerId: _id, | |
referrerAdd: _referredBy, | |
timePeriod: now, | |
hasLoyalty: false | |
}); | |
// users[userList[_id]].amountOfReferrer++; | |
userList[currentId] = _sender; | |
users[msg.sender] = UserStruct; | |
} | |
function distributeToSponsor(address _address,uint256 _eth) internal { | |
sponsorsPaid += ((_eth.mul(20)).div(100)); | |
uint256 _sp1 = (_eth.mul(10)).div(100); | |
uint256 _sp2 = (_eth.mul(7)).div(100); | |
uint256 _sp3 = (_eth.mul(3)).div(100); | |
address add1 = _address; | |
address add2 = users[_address].referrerAdd; | |
address add3 = users[add2].referrerAdd; | |
referralBalance_[add1] += (_sp1); | |
sponsorsPaid += _sp1; | |
emit amountDistributedToSponsor(msg.sender, add1,_sp1); | |
referralBalance_[add2] += (_sp2); | |
sponsorsPaid += _sp2; | |
emit amountDistributedToSponsor(msg.sender, add2, _sp2); | |
referralBalance_[add3] += (_sp3); | |
sponsorsPaid += _sp3; | |
emit amountDistributedToSponsor(msg.sender, add3, _sp3); | |
} | |
function sqrt(uint x) internal pure returns (uint y) { | |
uint z = (x + 1) / 2; | |
y = x; | |
while (z < y) { | |
y = z; | |
z = (x / z + z) / 2; | |
} | |
} | |
} | |
/** | |
* @title SafeMath | |
* @dev Math operations with safety checks that throw on error | |
*/ | |
library SafeMath { | |
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; | |
} | |
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; | |
} | |
function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint256 a, uint256 b) internal pure returns (uint256) { | |
uint256 c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
/** | |
* Also in memory of JPK, miss you Dad. | |
*/ | |
} |
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
interface AggregatorV3Interface { | |
function decimals() external view returns (uint8); | |
function description() external view returns (string memory); | |
function version() external view returns (uint256); | |
// getRoundData and latestRoundData should both raise "No data present" | |
// if they do not have data to report, instead of returning unset values | |
// which could be misinterpreted as actual reported values. | |
function getRoundData(uint80 _roundId) | |
external | |
view | |
returns ( | |
uint80 roundId, | |
int256 answer, | |
uint256 startedAt, | |
uint256 updatedAt, | |
uint80 answeredInRound | |
); | |
function latestRoundData() | |
external | |
view | |
returns ( | |
uint80 roundId, | |
int256 answer, | |
uint256 startedAt, | |
uint256 updatedAt, | |
uint80 answeredInRound | |
); | |
} | |
contract PriceConsumerV3 { | |
AggregatorV3Interface internal priceFeed; | |
/** | |
* Network: rinkeby | |
* Aggregator: USD/ETH | |
* Address: 0xdCA36F27cbC4E38aE16C4E9f99D39b42337F6dcf | |
*/ | |
constructor() public { | |
priceFeed = AggregatorV3Interface(0xdCA36F27cbC4E38aE16C4E9f99D39b42337F6dcf); | |
} | |
/** | |
* Returns the latest price | |
*/ | |
function getLatestPrice() public view returns (int) { | |
(uint80 roundID, int price, uint startedAt, uint timeStamp, uint80 answeredInRound ) = priceFeed.latestRoundData(); | |
return price; | |
} | |
} |
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
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.6.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. | |
*/ | |
abstract contract Context { | |
function _msgSender() internal view virtual returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view virtual returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} |
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
/** | |
*Submitted for verification at Etherscan.io on 2020-10-14 | |
*/ | |
pragma solidity ^0.6.0; | |
/*================================================================================== | |
= The 80/20 is a Wealth Distribution system that is open for anyone to use. = | |
= We created this application with hopes that it will provide a steady stream = | |
= of passive income for generations to come. The foundation that stands behind = | |
= this product would like you to live happy, free, and prosperous. = | |
= Stay tuned for more dApps from the GSG Global Marketing Group. = | |
= #LuckyRico #LACGold #JCunn24 #BoHarvey #LennyBones #WealthWithPhelps = | |
= #ShahzainTariq >= developer of this smart contract = | |
================================================================================*/ | |
interface IERC20 { | |
function totalSupply() external view returns (uint256); | |
function balanceOf(address account) external view returns (uint256); | |
function transfer(address recipient, uint256 amount) external returns (bool); | |
function allowance(address owner, address spender) external view returns (uint256); | |
function approve(address spender, uint256 amount) external returns (bool); | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
event Transfer(address indexed from, address indexed to, uint256 value); | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
contract auto_pool is IERC20{ | |
using SafeMath for uint256; | |
/*================================= | |
= MODIFIERS = | |
=================================*/ | |
// only people with tokens | |
modifier onlybelievers () { | |
require(myTokens() > 0); | |
_; | |
} | |
// only people with profits | |
modifier onlyhodler() { | |
require(myDividends(true) > 0); | |
_; | |
} | |
/*============================== | |
= EVENTS = | |
==============================*/ | |
event onTokenPurchase( | |
address indexed customerAddress, | |
uint256 incomingEthereum, | |
uint256 tokensMinted, | |
address indexed referredBy, | |
uint256 time, | |
uint256 totalTokens | |
); | |
event onTokenSell( | |
address indexed customerAddress, | |
uint256 tokensBurned, | |
uint256 ethereumEarned, | |
uint256 time, | |
uint256 totalTokens | |
); | |
event onReinvestment( | |
address indexed customerAddress, | |
uint256 ethereumReinvested, | |
uint256 tokensMinted | |
); | |
event onWithdraw( | |
address indexed customerAddress, | |
uint256 ethereumWithdrawn | |
); | |
event distrubuteBonusFund( | |
address, | |
uint256 | |
); | |
event amountDistributedToSponsor( | |
address, | |
address, | |
uint256 | |
); | |
// ERC20 | |
event Transfer( | |
address indexed from, | |
address indexed to, | |
uint256 tokens, | |
uint256 time | |
); | |
/*===================================== | |
= CONFIGURABLES = | |
=====================================*/ | |
string public name ; | |
string public symbol ; | |
uint8 public decimals ; | |
uint8 internal dividendFee_ ; | |
uint256 internal tokenPriceInitial_ ; | |
uint256 internal tokenPriceIncremental_ ; | |
uint256 internal magnitude; | |
uint256 public tokenPool; | |
uint256 public loyaltyPool; | |
uint256 public developmentFund; | |
uint256 public sponsorsPaid; | |
uint256 public gsg_foundation; | |
address dev1; | |
address dev2; | |
address GSGO_Official_LoyaltyPlan; | |
uint256 public currentId; | |
uint256 public day; | |
uint256 public claimedLoyalty; | |
uint256 public totalDeposited; | |
uint256 public totalWithdraw; | |
/*================================ | |
= DATASETS = | |
================================*/ | |
// amount of shares for each address (scaled number) | |
mapping(address => uint256) public tokenBalanceLedger_; | |
mapping(address => uint256) public referralBalance_; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
mapping(address => int256) public payoutsTo_; | |
mapping(address => basicData) public users; | |
mapping(uint256 => address) public userList; | |
uint256 internal tokenSupply_ = 0; | |
uint256 internal profitPerShare_; | |
uint256 internal profitperLoyalty; | |
//Users's data set | |
struct basicData{ | |
bool isExist; | |
uint256 id; | |
uint256 referrerId; | |
address referrerAdd; | |
} | |
/*======================================= | |
= PUBLIC FUNCTIONS = | |
=======================================*/ | |
/* | |
* -- APPLICATION ENTRY POINTS -- | |
*/ | |
constructor() public{ | |
name = "The-Eighty-Twenty"; | |
symbol = "GSG20"; | |
decimals = 18; | |
dividendFee_ = 10; | |
tokenPriceInitial_ = 0.0000001 ether; | |
tokenPriceIncremental_ = 0.00000001 ether; | |
magnitude = 2**64; | |
// "This is the distribution contract for holders of the GSG-Official (GSGO) Token." | |
GSGO_Official_LoyaltyPlan = address(0x727395b95C90DEab2F220Ce42615d9dD0F44e187); | |
dev1 = address(0x930121516fc237C3aB2f7B0d6cae218B7CBa3295); | |
dev2 = address(0x7cF196415CDD1eF08ca2358a8282D33Ba089B9f3); | |
currentId = 0; | |
day = now; | |
} | |
/** | |
* Converts all incoming Ethereum to tokens for the caller, and passes down the referral address (if any) | |
*/ | |
function buy(address _referredAdd) | |
public | |
payable | |
returns(uint256) | |
{ | |
require(msg.value >= 0.1 ether, "ERROR: minimun 0.1 ethereum "); | |
require(_referredAdd != msg.sender,"ERROR: cannot become own ref"); | |
if(!users[msg.sender].isExist) register(msg.sender,_referredAdd); | |
purchaseTokens(msg.value,_referredAdd); | |
//Distributing Ethers | |
loyaltyPool += ((msg.value.mul(12)).div(100)); | |
developmentFund += ((msg.value.mul(2)).div(100)); | |
gsg_foundation += ((msg.value.mul(2)).div(100)); | |
payable(GSGO_Official_LoyaltyPlan).transfer((msg.value.mul(2)).div(100)); | |
payable(dev1).transfer((msg.value.mul(1)).div(100)); | |
payable(dev2).transfer((msg.value.mul(1)).div(100)); | |
totalDeposited += msg.value; | |
} | |
receive() external payable { | |
require(msg.value >= 0.1 ether, "ERROR: minimun 0.1 ethereum ."); | |
if(!users[msg.sender].isExist) register(msg.sender,address(0)); | |
purchaseTokens(msg.value,address(0)); | |
//Distributing Ethers | |
loyaltyPool += ((msg.value.mul(12)).div(100)); | |
developmentFund += ( (msg.value.mul(2)).div(100)); | |
gsg_foundation += ((msg.value.mul(2)).div(100)); | |
payable(GSGO_Official_LoyaltyPlan).transfer((msg.value.mul(2)).div(100)); | |
payable(dev1).transfer((msg.value.mul(1)).div(100)); | |
payable(dev2).transfer((msg.value.mul(1)).div(100)); | |
} | |
fallback() | |
payable | |
external | |
{ | |
require(msg.value >= 0.1 ether, "ERROR: minimun 0.1 ethereum ."); | |
if(!users[msg.sender].isExist) register(msg.sender,address(0)); | |
purchaseTokens(msg.value,address(0)); | |
//Distributing Ethers | |
loyaltyPool += ((msg.value.mul(12)).div(100)); | |
developmentFund += ( (msg.value.mul(2)).div(100)); | |
gsg_foundation += ((msg.value.mul(2)).div(100)); | |
payable(GSGO_Official_LoyaltyPlan).transfer((msg.value.mul(2)).div(100)); | |
payable(dev1).transfer((msg.value.mul(1)).div(100)); | |
payable(dev2).transfer((msg.value.mul(1)).div(100)); } | |
/** | |
* Converts all of caller's dividends to tokens. | |
*/ | |
function reinvest() | |
onlyhodler() | |
public | |
{ | |
address _customerAddress = msg.sender; | |
// fetch dividends | |
uint256 _dividends = myDividends(false); // retrieve ref. bonus later in the code | |
uint256 _loyaltyEth = loyaltyOf(); | |
if(_loyaltyEth > 0 ether){ | |
payable(address(_customerAddress)).transfer(_loyaltyEth); | |
loyaltyPool -= _loyaltyEth; | |
claimedLoyalty += _loyaltyEth; | |
totalWithdraw += _loyaltyEth; | |
} | |
// pay out the dividends virtually | |
payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); | |
// retrieve ref. bonus | |
_dividends += referralBalance_[_customerAddress]; | |
referralBalance_[_customerAddress] = 0; | |
// dispatch a buy order with the virtualized "withdrawn dividends" | |
address refAdd = users[_customerAddress].referrerAdd; | |
// dispatch a buy order with the virtualized "withdrawn dividends" | |
uint256 _tokens = purchaseTokens(_dividends,refAdd); | |
loyaltyPool += ((_dividends.mul(12)).div(100)); | |
developmentFund += ((_dividends.mul(2)).div(100)); | |
gsg_foundation += ((_dividends.mul(2)).div(100)); | |
payable(GSGO_Official_LoyaltyPlan).transfer((_dividends.mul(2)).div(100)); | |
payable(dev1).transfer((_dividends.mul(1)).div(100)); | |
payable(dev2).transfer((_dividends.mul(1)).div(100)); | |
// fire event | |
emit onReinvestment(_customerAddress, _dividends, _tokens); | |
} | |
/** | |
* Alias of sell() and withdraw(). | |
*/ | |
function exit() | |
public | |
{ | |
// get token count for caller & sell them all | |
address _customerAddress = msg.sender; | |
uint256 _tokens = tokenBalanceLedger_[_customerAddress]; | |
if(_tokens > 0) sell(_tokens); | |
withdraw(); | |
} | |
/** | |
* Withdraws all of the callers earnings. | |
*/ | |
function withdraw() | |
onlyhodler() | |
public | |
{ | |
// setup data | |
address _customerAddress = msg.sender; | |
uint256 _dividends = myDividends(false); // get ref. bonus later in the code | |
uint256 _loyaltyEth = loyaltyOf(); | |
// update dividend tracker | |
payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); | |
if(_loyaltyEth > 0 ether) { | |
_dividends += _loyaltyEth; | |
loyaltyPool -= _loyaltyEth; | |
claimedLoyalty += _loyaltyEth; | |
} | |
// add ref. bonus | |
_dividends += referralBalance_[_customerAddress]; | |
referralBalance_[_customerAddress] = 0; | |
totalWithdraw += _dividends; | |
// delivery service | |
payable(address(_customerAddress)).transfer(_dividends); | |
// fire event | |
emit onWithdraw(_customerAddress, _dividends); | |
} | |
/** | |
* Liquifies tokens to ethereum. | |
*/ | |
function sell(uint256 _amountOfTokens) | |
onlybelievers () | |
public | |
{ | |
address _customerAddress = msg.sender; | |
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
//initializating values; | |
uint256 _tokens = _amountOfTokens; | |
uint256 _ethereum = tokensToEthereum_(_tokens); | |
uint256 tax = (_ethereum.mul(5)).div(100); | |
loyaltyPool = SafeMath.add(loyaltyPool,tax); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, tax); | |
// burn the sold tokens | |
tokenSupply_ = SafeMath.sub(tokenSupply_, _tokens); | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _tokens); | |
//updates dividends tracker | |
int256 _updatedPayouts = (int256) (profitPerShare_ * _tokens + (_taxedEthereum * magnitude)); | |
payoutsTo_[_customerAddress] -= _updatedPayouts; | |
payoutsTo_[_customerAddress] += (int256) (_taxedEthereum*magnitude); | |
totalWithdraw += _taxedEthereum; | |
//tranfer amout of ethers to user | |
payable(address(_customerAddress)).transfer(_taxedEthereum); | |
if(_ethereum < tokenPool) { | |
tokenPool = SafeMath.sub(tokenPool, _ethereum); | |
} | |
// fire event | |
emit onTokenSell(_customerAddress, _tokens, _taxedEthereum,now,tokenBalanceLedger_[_customerAddress]); | |
} | |
function approve(address spender, uint amount) public override returns (bool) { | |
_approve(msg.sender, spender, amount); | |
return true; | |
} | |
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
_approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)); | |
return true; | |
} | |
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
_approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* Transfer tokens from the caller to a new holder. | |
* Remember, there's a 10% fee here as well. | |
*/ | |
function transfer(address _toAddress, uint256 _amountOfTokens) | |
onlybelievers () | |
public | |
override | |
returns(bool) | |
{ | |
// setup | |
address _customerAddress = msg.sender; | |
// make sure we have the requested tokens | |
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
// exchange tokens | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
tokenBalanceLedger_[_toAddress] = SafeMath.add(tokenBalanceLedger_[_toAddress], _amountOfTokens); | |
// update dividend trackers | |
payoutsTo_[_customerAddress] -= (int256) (profitPerShare_ * _amountOfTokens); | |
payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _amountOfTokens); | |
// fire event | |
emit Transfer(_customerAddress, _toAddress, _amountOfTokens,now); | |
// ERC20 | |
return true; | |
} | |
function transferFrom(address sender, address _toAddress, uint _amountOfTokens) public override returns (bool) { | |
// setup | |
address _customerAddress = sender; | |
// make sure we have the requested tokens | |
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
// exchange tokens | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
tokenBalanceLedger_[_toAddress] = SafeMath.add(tokenBalanceLedger_[_toAddress], _amountOfTokens); | |
// update dividend trackers | |
payoutsTo_[_customerAddress] -= (int256) (profitPerShare_ * _amountOfTokens); | |
payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _amountOfTokens); | |
// fire event | |
emit Transfer(_customerAddress, _toAddress, _amountOfTokens,now); | |
_approve(sender, msg.sender, _allowances[sender][msg.sender].sub(_amountOfTokens, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/*---------- HELPERS AND CALCULATORS ----------*/ | |
/** | |
* Method to view the current Ethereum stored in the contract | |
* Example: totalEthereumBalance() | |
*/ | |
function totalEthereumBalance() | |
public | |
view | |
returns(uint) | |
{ | |
return address(this).balance; | |
} | |
/** | |
* Retrieve the total token supply. | |
*/ | |
function totalSupply() | |
public | |
override | |
view | |
returns(uint256) | |
{ | |
return tokenSupply_; | |
} | |
/** | |
* Retrieve the tokens owned by the caller. | |
*/ | |
function myTokens() | |
public | |
view | |
returns(uint256) | |
{ | |
address _customerAddress = msg.sender; | |
return balanceOf(_customerAddress); | |
} | |
/** | |
* Retrieve the dividends owned by the caller. | |
*/ | |
function myDividends(bool _includeReferralBonus) | |
public | |
view | |
returns(uint256) | |
{ | |
address _customerAddress = msg.sender; | |
return _includeReferralBonus ? dividendsOf(_customerAddress) + referralBalance_[_customerAddress] : dividendsOf(_customerAddress) ; | |
} | |
/** | |
* Retrieve the token balance of any single address. | |
*/ | |
function balanceOf(address _customerAddress) | |
view | |
public | |
override | |
returns(uint256) | |
{ | |
return tokenBalanceLedger_[_customerAddress]; | |
} | |
/** | |
* Retrieve the dividend balance of any single address. | |
*/ | |
function dividendsOf(address _customerAddress) | |
view | |
public | |
returns(uint256) | |
{ | |
return (uint256) ((int256)(profitPerShare_ * tokenBalanceLedger_[_customerAddress]) - payoutsTo_[_customerAddress]) / magnitude; | |
} | |
/** | |
* Return the buy price of 1 individual token. | |
*/ | |
function sellPrice() | |
public | |
view | |
returns(uint256) | |
{ | |
if(tokenSupply_ == 0){ | |
return tokenPriceInitial_ - tokenPriceIncremental_; | |
} else { | |
uint256 _ethereum = tokensToEthereum_(1e18); | |
uint256 tax = (_ethereum.mul(5)).div(100); | |
uint256 _dividends = SafeMath.div(_ethereum, tax); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
} | |
/** | |
* Return the sell price of 1 individual token. | |
*/ | |
function buyPrice() | |
public | |
view | |
returns(uint256) | |
{ | |
if(tokenSupply_ == 0){ | |
return tokenPriceInitial_ + tokenPriceIncremental_; | |
} else { | |
uint256 _ethereum = tokensToEthereum_(1e18); | |
uint256 _dividends = SafeMath.div(_ethereum, dividendFee_ ); | |
uint256 _taxedEthereum = SafeMath.add(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
} | |
function calculateTokensReceived(uint256 _ethToSpend) | |
public | |
view | |
returns(uint256) | |
{ | |
uint256 _ethereumToSpend = (_ethToSpend.mul(64)).div(100); | |
uint256 _dividends = SafeMath.div(_ethereumToSpend, dividendFee_); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereumToSpend, _dividends); | |
uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); | |
return _amountOfTokens; | |
} | |
function getReferrer() public view returns(address){ | |
return users[msg.sender].referrerAdd; | |
} | |
function calculateEthereumReceived(uint256 _tokensToSell) | |
public | |
view | |
returns(uint256) | |
{ | |
require(_tokensToSell <= tokenSupply_); | |
uint256 _ethereum = tokensToEthereum_(_tokensToSell); | |
uint256 tax = (_ethereum.mul(5)).div(100); | |
uint256 _dividends = SafeMath.div(_ethereum, tax); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
function loyaltyOf() public view returns(uint256){ | |
address _customerAddress = msg.sender; | |
// user should hold 2500 tokens for qualify for loyalty bonus; | |
if(tokenBalanceLedger_[_customerAddress] >= 2000*10**uint256(decimals)){ | |
// return loyalty bonus users | |
return ((uint256) ((int256)((profitperLoyalty) * tokenBalanceLedger_[_customerAddress]) - payoutsTo_[_customerAddress]) / magnitude)*14/5; | |
} | |
else{ | |
return 0; | |
} | |
} | |
function userReferrer(address _address) public view returns(address){ | |
return userList[users[_address].referrerId]; | |
} | |
/*========================================== | |
= INTERNAL FUNCTIONS = | |
==========================================*/ | |
function purchaseTokens(uint256 _eth, address _referredBy) | |
internal | |
returns(uint256) | |
{ | |
uint256 _incomingEthereum = (_eth.mul(64)).div(100); | |
// data setup | |
address _customerAddress = msg.sender; | |
uint256 _undividedDividends = SafeMath.div(_incomingEthereum, dividendFee_); | |
uint256 _referralBonus = SafeMath.div(_undividedDividends, 3); | |
uint256 _dividends = SafeMath.sub(_undividedDividends, _referralBonus); | |
uint256 _taxedEthereum = SafeMath.sub(_incomingEthereum, _undividedDividends); | |
uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); | |
uint256 _fee = _dividends * magnitude; | |
tokenPool += _taxedEthereum; | |
require(_amountOfTokens > 0 && (SafeMath.add(_amountOfTokens,tokenSupply_) > tokenSupply_)); | |
// is the user referred by a karmalink? | |
if( | |
// is this a referred purchase? | |
_referredBy != 0x0000000000000000000000000000000000000000 && | |
// no cheating! | |
_referredBy != _customerAddress | |
){ | |
// wealth redistribution | |
distributeToSponsor(_referredBy,_eth); | |
} else { | |
// no ref purchase | |
// add the referral bonus back to the global dividends cake | |
_dividends = SafeMath.add(_dividends, _referralBonus); | |
_fee = _dividends * magnitude; | |
} | |
// we can't give people infinite ethereum | |
if(tokenSupply_ > 0){ | |
// add tokens to the pool | |
tokenSupply_ = SafeMath.add(tokenSupply_, _amountOfTokens); | |
// take the amount of dividends gained through this transaction, and allocates them evenly to each shareholder | |
profitPerShare_ += (_dividends * magnitude / (tokenSupply_)); | |
profitperLoyalty += ((_dividends) * magnitude / (tokenSupply_)); | |
// calculate the amount of tokens the customer receives over his purchase | |
_fee = _fee - (_fee-(_amountOfTokens * (_dividends * magnitude / (tokenSupply_)))); | |
} else { | |
// add tokens to the pool | |
tokenSupply_ = _amountOfTokens; | |
} | |
// update circulating supply & the ledger address for the customer | |
tokenBalanceLedger_[_customerAddress] = SafeMath.add(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
//update dividends tracker | |
int256 _updatedPayouts = (int256) ((profitPerShare_ * _amountOfTokens) - _fee); | |
payoutsTo_[_customerAddress] += _updatedPayouts; | |
// fire event | |
emit onTokenPurchase(_customerAddress, _incomingEthereum, _amountOfTokens, _referredBy,now,tokenBalanceLedger_[_customerAddress]); | |
return _amountOfTokens; | |
} | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* Calculate Token price based on an amount of incoming ethereum | |
* Some conversions occurred to prevent decimal errors or underflows / overflows in solidity code. | |
*/ | |
function ethereumToTokens_(uint256 _ethereum) | |
internal | |
view | |
returns(uint256) | |
{ | |
uint256 _tokenPriceInitial = tokenPriceInitial_ * 1e18; | |
uint256 _tokensReceived = | |
( | |
( | |
// underflow attempts BTFO | |
SafeMath.sub( | |
(sqrt | |
( | |
(_tokenPriceInitial**2) | |
+ | |
(2*(tokenPriceIncremental_ * 1e18)*(_ethereum * 1e18)) | |
+ | |
(((tokenPriceIncremental_)**2)*(tokenSupply_**2)) | |
+ | |
(2*(tokenPriceIncremental_)*_tokenPriceInitial*tokenSupply_) | |
) | |
), _tokenPriceInitial | |
) | |
)/(tokenPriceIncremental_) | |
)-(tokenSupply_) | |
; | |
return _tokensReceived; | |
} | |
/** | |
* Calculate token sell value. | |
*/ | |
function tokensToEthereum_(uint256 _tokens) | |
internal | |
view | |
returns(uint256) | |
{ | |
uint256 tokens_ = (_tokens + 1e18); | |
uint256 _tokenSupply = (tokenSupply_ + 1e18); | |
uint256 _etherReceived = | |
( | |
// underflow attempts BTFO | |
SafeMath.sub( | |
( | |
( | |
( | |
tokenPriceInitial_ +(tokenPriceIncremental_ * (_tokenSupply/1e18)) | |
)-tokenPriceIncremental_ | |
)*(tokens_ - 1e18) | |
),(tokenPriceIncremental_*((tokens_**2-tokens_)/1e18))/2 | |
) | |
/1e18); | |
return _etherReceived; | |
} | |
function register(address _sender, address _referredBy) internal { | |
uint256 _id = users[_referredBy].id; | |
basicData memory UserStruct; | |
currentId++; | |
//add users data | |
UserStruct = basicData({ | |
isExist: true, | |
id: currentId, | |
referrerId: _id, | |
referrerAdd: _referredBy | |
}); | |
userList[currentId] = _sender; | |
users[msg.sender] = UserStruct; | |
} | |
function distributeToSponsor(address _address,uint256 _eth) internal { | |
uint256 _sp1 = (_eth.mul(10)).div(100); | |
uint256 _sp2 = (_eth.mul(7)).div(100); | |
uint256 _sp3 = (_eth.mul(3)).div(100); | |
address add1 = _address; | |
address add2 = users[_address].referrerAdd; | |
address add3 = users[add2].referrerAdd; | |
//add amount of ref bonus to referrer | |
referralBalance_[add1] += (_sp1); | |
sponsorsPaid += _sp1; | |
//fire event on distributionToSponsor | |
emit amountDistributedToSponsor(msg.sender, add1,_sp1); | |
//add amount of ref bonus to referrer | |
referralBalance_[add2] += (_sp2); | |
sponsorsPaid += _sp2; | |
//fire event on distributionToSponsor | |
emit amountDistributedToSponsor(msg.sender, add2, _sp2); | |
//add amount of ref bonus to referrer | |
referralBalance_[add3] += (_sp3); | |
sponsorsPaid += _sp3; | |
//fire event on distributionToSponsor | |
emit amountDistributedToSponsor(msg.sender, add3, _sp3); | |
} | |
function sqrt(uint x) internal pure returns (uint y) { | |
uint z = (x + 1) / 2; | |
y = x; | |
while (z < y) { | |
y = z; | |
z = (x / z + z) / 2; | |
} | |
} | |
} | |
/** | |
* @title SafeMath | |
* @dev Math operations with safety checks that throw on error | |
*/ | |
library SafeMath { | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
return sub(a, b, "SafeMath: subtraction overflow"); | |
} | |
function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
require(b <= a, errorMessage); | |
uint c = a - b; | |
return c; | |
} | |
function mul(uint a, uint b) internal pure returns (uint) { | |
if (a == 0) { | |
return 0; | |
} | |
uint c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
return div(a, b, "SafeMath: division by zero"); | |
} | |
function div(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
// Solidity only automatically asserts when dividing by 0 | |
require(b > 0, errorMessage); | |
uint c = a / b; | |
return c; | |
} | |
} |
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
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.6.0; | |
abstract contract Context { | |
function _msgSender() internal view virtual returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view virtual returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
/** | |
* @dev Implementation of the {IERC20} interface. | |
* | |
* This implementation is agnostic to the way tokens are created. This means | |
* that a supply mechanism has to be added in a derived contract using {_mint}. | |
* For a generic mechanism see {ERC20PresetMinterPauser}. | |
* | |
* TIP: For a detailed writeup see our guide | |
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How | |
* to implement supply mechanisms]. | |
* | |
* We have followed general OpenZeppelin guidelines: functions revert instead | |
* of returning `false` on failure. This behavior is nonetheless conventional | |
* and does not conflict with the expectations of ERC20 applications. | |
* | |
* Additionally, an {Approval} event is emitted on calls to {transferFrom}. | |
* This allows applications to reconstruct the allowance for all accounts just | |
* by listening to said events. Other implementations of the EIP may not emit | |
* these events, as it isn't required by the specification. | |
* | |
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance} | |
* functions have been added to mitigate the well-known issues around setting | |
* allowances. See {IERC20-approve}. | |
*/ | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint256; | |
mapping (address => uint256) private _balances; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
uint256 private _totalSupply; | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
/** | |
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with | |
* a default value of 18. | |
* | |
* To select a different value for {decimals}, use {_setupDecimals}. | |
* | |
* All three of these values are immutable: they can only be set once during | |
* construction. | |
*/ | |
constructor (string memory name, string memory symbol) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = 18; | |
} | |
/** | |
* @dev Returns the name of the token. | |
*/ | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev Returns the symbol of the token, usually a shorter version of the | |
* name. | |
*/ | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
/*channge symbol*/ | |
function _changeSymbol(string memory _newSymbol) internal { | |
_symbol = _newSymbol; | |
} | |
/** | |
* @dev Returns the number of decimals used to get its user representation. | |
* For example, if `decimals` equals `2`, a balance of `505` tokens should | |
* be displayed to a user as `5,05` (`505 / 10 ** 2`). | |
* | |
* Tokens usually opt for a value of 18, imitating the relationship between | |
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is | |
* called. | |
* | |
* NOTE: This information is only used for _display_ purposes: it in | |
* no way affects any of the arithmetic of the contract, including | |
* {IERC20-balanceOf} and {IERC20-transfer}. | |
*/ | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
/** | |
* @dev See {IERC20-totalSupply}. | |
*/ | |
function totalSupply() public view override returns (uint256) { | |
return _totalSupply; | |
} | |
/** | |
* @dev See {IERC20-balanceOf}. | |
*/ | |
function balanceOf(address account) public view override returns (uint256) { | |
return _balances[account]; | |
} | |
/** | |
* @dev See {IERC20-transfer}. | |
* | |
* Requirements: | |
* | |
* - `recipient` cannot be the zero address. | |
* - the caller must have a balance of at least `amount`. | |
*/ | |
function transfer(address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-allowance}. | |
*/ | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
/** | |
* @dev See {IERC20-approve}. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function approve(address spender, uint256 amount) public virtual override returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-transferFrom}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. This is not | |
* required by the EIP. See the note at the beginning of {ERC20}. | |
* | |
* Requirements: | |
* | |
* - `sender` and `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
* - the caller must have allowance for ``sender``'s tokens of at least | |
* `amount`. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/** | |
* @dev Atomically increases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
/** | |
* @dev Atomically decreases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
* - `spender` must have allowance for the caller of at least | |
* `subtractedValue`. | |
*/ | |
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* @dev Moves tokens `amount` from `sender` to `recipient`. | |
* | |
* This is internal function is equivalent to {transfer}, and can be used to | |
* e.g. implement automatic token fees, slashing mechanisms, etc. | |
* | |
* Emits a {Transfer} event. | |
* | |
* Requirements: | |
* | |
* - `sender` cannot be the zero address. | |
* - `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
*/ | |
function _transfer(address sender, address recipient, uint256 amount) internal virtual { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
require(recipient != address(0), "ERC20: transfer to the zero address"); | |
_beforeTokenTransfer(sender, recipient, amount); | |
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
/** @dev Creates `amount` tokens and assigns them to `account`, increasing | |
* the total supply. | |
* | |
* Emits a {Transfer} event with `from` set to the zero address. | |
* | |
* Requirements: | |
* | |
* - `to` cannot be the zero address. | |
*/ | |
function _mint(address account, uint256 amount) public virtual { | |
require(account != address(0), "ERC20: mint to the zero address"); | |
_beforeTokenTransfer(address(0), account, amount); | |
_totalSupply = _totalSupply.add(amount); | |
_balances[account] = _balances[account].add(amount); | |
emit Transfer(address(0), account, amount); | |
} | |
/** | |
* @dev Destroys `amount` tokens from `account`, reducing the | |
* total supply. | |
* | |
* Emits a {Transfer} event with `to` set to the zero address. | |
* | |
* Requirements: | |
* | |
* - `account` cannot be the zero address. | |
* - `account` must have at least `amount` tokens. | |
*/ | |
function _burn(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: burn from the zero address"); | |
_beforeTokenTransfer(account, address(0), amount); | |
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); | |
_totalSupply = _totalSupply.sub(amount); | |
emit Transfer(account, address(0), amount); | |
} | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. | |
* | |
* This internal function is equivalent to `approve`, and can be used to | |
* e.g. set automatic allowances for certain subsystems, etc. | |
* | |
* Emits an {Approval} event. | |
* | |
* Requirements: | |
* | |
* - `owner` cannot be the zero address. | |
* - `spender` cannot be the zero address. | |
*/ | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* @dev Sets {decimals} to a value other than the default one of 18. | |
* | |
* WARNING: This function should only be called from the constructor. Most | |
* applications that interact with token contracts will not expect | |
* {decimals} to ever change, and may work incorrectly if it does. | |
*/ | |
function _setupDecimals(uint8 decimals_) internal { | |
_decimals = decimals_; | |
} | |
/** | |
* @dev Hook that is called before any transfer of tokens. This includes | |
* minting and burning. | |
* | |
* Calling conditions: | |
* | |
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens | |
* will be to transferred to `to`. | |
* - when `from` is zero, `amount` tokens will be minted for `to`. | |
* - when `to` is zero, `amount` of ``from``'s tokens will be burned. | |
* - `from` and `to` are never both zero. | |
* | |
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } | |
} | |
contract AcademicusToken is ERC20 { | |
address admin; | |
constructor(address _add) ERC20('Academicus','acad') public{ | |
admin = _add; | |
_mint(admin,299792458*1e18); | |
} | |
// function changeSymbo(string memory _symbolName) public { | |
// require(admin == msg.sender,"ERROR: only admin can call this"); | |
// _changeSymbol(_symbolName); | |
// } | |
// function changeAdmin(address _add) public { | |
// require(admin == msg.sender,'ERROR: only Admin can call this'); | |
// admin = _add; | |
// } | |
} |
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.8; | |
/** | |
* @title IERC165 | |
* @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md | |
*/ | |
interface IERC165 { | |
/** | |
* @notice Query if a contract implements an interface | |
* @param interfaceId The interface identifier, as specified in ERC-165 | |
* @dev Interface identification is specified in ERC-165. This function | |
* uses less than 30,000 gas. | |
*/ | |
function supportsInterface(bytes4 interfaceId) | |
external | |
view | |
returns (bool); | |
} | |
/** | |
* @title ERC721 Non-Fungible Token Standard basic interface | |
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract IERC721 is IERC165 { | |
event Transfer( | |
address indexed from, | |
address indexed to, | |
uint256 indexed tokenId | |
); | |
event Approval( | |
address indexed owner, | |
address indexed approved, | |
uint256 indexed tokenId | |
); | |
event ApprovalForAll( | |
address indexed owner, | |
address indexed operator, | |
bool approved | |
); | |
function balanceOf(address owner) public view returns (uint256 balance); | |
function ownerOf(uint256 tokenId) public view returns (address owner); | |
function approve(address to, uint256 tokenId) public; | |
function getApproved(uint256 tokenId) | |
public view returns (address operator); | |
function setApprovalForAll(address operator, bool _approved) public; | |
function isApprovedForAll(address owner, address operator) | |
public view returns (bool); | |
function transferFrom(address from, address to, uint256 tokenId) public; | |
function safeTransferFrom(address from, address to, uint256 tokenId) | |
public; | |
function safeTransferFrom( | |
address from, | |
address to, | |
uint256 tokenId, | |
bytes data | |
) | |
public; | |
} | |
/** | |
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension | |
* @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract IERC721Enumerable is IERC721 { | |
function totalSupply() public view returns (uint256); | |
function tokenOfOwnerByIndex( | |
address owner, | |
uint256 index | |
) | |
public | |
view | |
returns (uint256 tokenId); | |
function tokenByIndex(uint256 index) public view returns (uint256); | |
} | |
/** | |
* @title ERC721 token receiver interface | |
* @dev Interface for any contract that wants to support safeTransfers | |
* from ERC721 asset contracts. | |
*/ | |
contract IERC721Receiver { | |
/** | |
* @notice Handle the receipt of an NFT | |
* @dev The ERC721 smart contract calls this function on the recipient | |
* after a `safeTransfer`. This function MUST return the function selector, | |
* otherwise the caller will revert the transaction. The selector to be | |
* returned can be obtained as `this.onERC721Received.selector`. This | |
* function MAY throw to revert and reject the transfer. | |
* Note: the ERC721 contract address is always the message sender. | |
* @param operator The address which called `safeTransferFrom` function | |
* @param from The address which previously owned the token | |
* @param tokenId The NFT identifier which is being transferred | |
* @param data Additional data with no specified format | |
* @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` | |
*/ | |
function onERC721Received( | |
address operator, | |
address from, | |
uint256 tokenId, | |
bytes data | |
) | |
public | |
returns(bytes4); | |
} | |
/** | |
* @title SafeMath | |
* @dev Math operations with safety checks that throw on error | |
*/ | |
library SafeMath { | |
/** | |
* @dev Multiplies two numbers, throws on overflow. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { | |
// Gas optimization: this is cheaper than asserting 'a' not being zero, but the | |
// benefit is lost if 'b' is also tested. | |
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 | |
if (a == 0) { | |
return 0; | |
} | |
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 a / b; | |
} | |
/** | |
* @dev Subtracts 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 c) { | |
c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
} | |
/** | |
* Utility library of inline functions on addresses | |
*/ | |
library Address { | |
/** | |
* Returns whether the target address is a contract | |
* @dev This function will return false if invoked during the constructor of a contract, | |
* as the code is not actually created until after the constructor finishes. | |
* @param addr address to check | |
* @return whether the target address is a contract | |
*/ | |
function isContract(address addr) internal view returns (bool) { | |
uint256 size; | |
// XXX Currently there is no better way to check if there is a contract in an address | |
// than to check the size of the code at that address. | |
// See https://ethereum.stackexchange.com/a/14016/36603 | |
// for more details about how this works. | |
// TODO Check this again before the Serenity release, because all addresses will be | |
// contracts then. | |
// solium-disable-next-line security/no-inline-assembly | |
assembly { size := extcodesize(addr) } | |
return size > 0; | |
} | |
} | |
/** | |
* @title ERC165 | |
* @author Matt Condon (@shrugs) | |
* @dev Implements ERC165 using a lookup table. | |
*/ | |
contract ERC165 is IERC165 { | |
bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7; | |
/** | |
* 0x01ffc9a7 === | |
* bytes4(keccak256('supportsInterface(bytes4)')) | |
*/ | |
/** | |
* @dev a mapping of interface id to whether or not it's supported | |
*/ | |
mapping(bytes4 => bool) private _supportedInterfaces; | |
/** | |
* @dev A contract implementing SupportsInterfaceWithLookup | |
* implement ERC165 itself | |
*/ | |
constructor() | |
internal | |
{ | |
_registerInterface(_InterfaceId_ERC165); | |
} | |
/** | |
* @dev implement supportsInterface(bytes4) using a lookup table | |
*/ | |
function supportsInterface(bytes4 interfaceId) | |
external | |
view | |
returns (bool) | |
{ | |
return _supportedInterfaces[interfaceId]; | |
} | |
/** | |
* @dev internal method for registering an interface | |
*/ | |
function _registerInterface(bytes4 interfaceId) | |
internal | |
{ | |
require(interfaceId != 0xffffffff); | |
_supportedInterfaces[interfaceId] = true; | |
} | |
} | |
/** | |
* @title ERC721 Non-Fungible Token Standard basic implementation | |
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract ERC721 is ERC165, IERC721 { | |
using SafeMath for uint256; | |
using Address for address; | |
// Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` | |
// which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` | |
bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; | |
// Mapping from token ID to owner | |
mapping (uint256 => address) private _tokenOwner; | |
// Mapping from token ID to approved address | |
mapping (uint256 => address) private _tokenApprovals; | |
// Mapping from owner to number of owned token | |
mapping (address => uint256) private _ownedTokensCount; | |
// Mapping from owner to operator approvals | |
mapping (address => mapping (address => bool)) private _operatorApprovals; | |
bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd; | |
/* | |
* 0x80ac58cd === | |
* bytes4(keccak256('balanceOf(address)')) ^ | |
* bytes4(keccak256('ownerOf(uint256)')) ^ | |
* bytes4(keccak256('approve(address,uint256)')) ^ | |
* bytes4(keccak256('getApproved(uint256)')) ^ | |
* bytes4(keccak256('setApprovalForAll(address,bool)')) ^ | |
* bytes4(keccak256('isApprovedForAll(address,address)')) ^ | |
* bytes4(keccak256('transferFrom(address,address,uint256)')) ^ | |
* bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ | |
* bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) | |
*/ | |
constructor() | |
public | |
{ | |
// register the supported interfaces to conform to ERC721 via ERC165 | |
_registerInterface(_InterfaceId_ERC721); | |
} | |
/** | |
* @dev Gets the balance of the specified address | |
* @param owner address to query the balance of | |
* @return uint256 representing the amount owned by the passed address | |
*/ | |
function balanceOf(address owner) public view returns (uint256) { | |
require(owner != address(0)); | |
return _ownedTokensCount[owner]; | |
} | |
/** | |
* @dev Gets the owner of the specified token ID | |
* @param tokenId uint256 ID of the token to query the owner of | |
* @return owner address currently marked as the owner of the given token ID | |
*/ | |
function ownerOf(uint256 tokenId) public view returns (address) { | |
address owner = _tokenOwner[tokenId]; | |
require(owner != address(0)); | |
return owner; | |
} | |
/** | |
* @dev Approves another address to transfer the given token ID | |
* The zero address indicates there is no approved address. | |
* There can only be one approved address per token at a given time. | |
* Can only be called by the token owner or an approved operator. | |
* @param to address to be approved for the given token ID | |
* @param tokenId uint256 ID of the token to be approved | |
*/ | |
function approve(address to, uint256 tokenId) public { | |
address owner = ownerOf(tokenId); | |
require(to != owner); | |
require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); | |
_tokenApprovals[tokenId] = to; | |
emit Approval(owner, to, tokenId); | |
} | |
/** | |
* @dev Gets the approved address for a token ID, or zero if no address set | |
* Reverts if the token ID does not exist. | |
* @param tokenId uint256 ID of the token to query the approval of | |
* @return address currently approved for the given token ID | |
*/ | |
function getApproved(uint256 tokenId) public view returns (address) { | |
require(_exists(tokenId)); | |
return _tokenApprovals[tokenId]; | |
} | |
/** | |
* @dev Sets or unsets the approval of a given operator | |
* An operator is allowed to transfer all tokens of the sender on their behalf | |
* @param to operator address to set the approval | |
* @param approved representing the status of the approval to be set | |
*/ | |
function setApprovalForAll(address to, bool approved) public { | |
require(to != msg.sender); | |
_operatorApprovals[msg.sender][to] = approved; | |
emit ApprovalForAll(msg.sender, to, approved); | |
} | |
/** | |
* @dev Tells whether an operator is approved by a given owner | |
* @param owner owner address which you want to query the approval of | |
* @param operator operator address which you want to query the approval of | |
* @return bool whether the given operator is approved by the given owner | |
*/ | |
function isApprovedForAll( | |
address owner, | |
address operator | |
) | |
public | |
view | |
returns (bool) | |
{ | |
return _operatorApprovals[owner][operator]; | |
} | |
/** | |
* @dev Transfers the ownership of a given token ID to another address | |
* Usage of this method is discouraged, use `safeTransferFrom` whenever possible | |
* Requires the msg sender to be the owner, approved, or operator | |
* @param from current owner of the token | |
* @param to address to receive the ownership of the given token ID | |
* @param tokenId uint256 ID of the token to be transferred | |
*/ | |
function transferFrom( | |
address from, | |
address to, | |
uint256 tokenId | |
) | |
public | |
{ | |
require(_isApprovedOrOwner(msg.sender, tokenId)); | |
require(to != address(0)); | |
_clearApproval(from, tokenId); | |
_removeTokenFrom(from, tokenId); | |
_addTokenTo(to, tokenId); | |
emit Transfer(from, to, tokenId); | |
} | |
/** | |
* @dev Safely transfers the ownership of a given token ID to another address | |
* If the target address is a contract, it must implement `onERC721Received`, | |
* which is called upon a safe transfer, and return the magic value | |
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, | |
* the transfer is reverted. | |
* | |
* Requires the msg sender to be the owner, approved, or operator | |
* @param from current owner of the token | |
* @param to address to receive the ownership of the given token ID | |
* @param tokenId uint256 ID of the token to be transferred | |
*/ | |
function safeTransferFrom( | |
address from, | |
address to, | |
uint256 tokenId | |
) | |
public | |
{ | |
// solium-disable-next-line arg-overflow | |
safeTransferFrom(from, to, tokenId, ""); | |
} | |
/** | |
* @dev Safely transfers the ownership of a given token ID to another address | |
* If the target address is a contract, it must implement `onERC721Received`, | |
* which is called upon a safe transfer, and return the magic value | |
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, | |
* the transfer is reverted. | |
* Requires the msg sender to be the owner, approved, or operator | |
* @param from current owner of the token | |
* @param to address to receive the ownership of the given token ID | |
* @param tokenId uint256 ID of the token to be transferred | |
* @param _data bytes data to send along with a safe transfer check | |
*/ | |
function safeTransferFrom( | |
address from, | |
address to, | |
uint256 tokenId, | |
bytes _data | |
) | |
public | |
{ | |
transferFrom(from, to, tokenId); | |
// solium-disable-next-line arg-overflow | |
require(_checkOnERC721Received(from, to, tokenId, _data)); | |
} | |
/** | |
* @dev Returns whether the specified token exists | |
* @param tokenId uint256 ID of the token to query the existence of | |
* @return whether the token exists | |
*/ | |
function _exists(uint256 tokenId) internal view returns (bool) { | |
address owner = _tokenOwner[tokenId]; | |
return owner != address(0); | |
} | |
/** | |
* @dev Returns whether the given spender can transfer a given token ID | |
* @param spender address of the spender to query | |
* @param tokenId uint256 ID of the token to be transferred | |
* @return bool whether the msg.sender is approved for the given token ID, | |
* is an operator of the owner, or is the owner of the token | |
*/ | |
function _isApprovedOrOwner( | |
address spender, | |
uint256 tokenId | |
) | |
internal | |
view | |
returns (bool) | |
{ | |
address owner = ownerOf(tokenId); | |
// Disable solium check because of | |
// https://github.com/duaraghav8/Solium/issues/175 | |
// solium-disable-next-line operator-whitespace | |
return ( | |
spender == owner || | |
getApproved(tokenId) == spender || | |
isApprovedForAll(owner, spender) | |
); | |
} | |
/** | |
* @dev Internal function to mint a new token | |
* Reverts if the given token ID already exists | |
* @param to The address that will own the minted token | |
* @param tokenId uint256 ID of the token to be minted by the msg.sender | |
*/ | |
function _mint(address to, uint256 tokenId) internal { | |
require(to != address(0)); | |
_addTokenTo(to, tokenId); | |
emit Transfer(address(0), to, tokenId); | |
} | |
/** | |
* @dev Internal function to burn a specific token | |
* Reverts if the token does not exist | |
* @param tokenId uint256 ID of the token being burned by the msg.sender | |
*/ | |
function _burn(address owner, uint256 tokenId) internal { | |
_clearApproval(owner, tokenId); | |
_removeTokenFrom(owner, tokenId); | |
emit Transfer(owner, address(0), tokenId); | |
} | |
/** | |
* @dev Internal function to add a token ID to the list of a given address | |
* Note that this function is left internal to make ERC721Enumerable possible, but is not | |
* intended to be called by custom derived contracts: in particular, it emits no Transfer event. | |
* @param to address representing the new owner of the given token ID | |
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address | |
*/ | |
function _addTokenTo(address to, uint256 tokenId) internal { | |
require(_tokenOwner[tokenId] == address(0)); | |
_tokenOwner[tokenId] = to; | |
_ownedTokensCount[to] = _ownedTokensCount[to].add(1); | |
} | |
/** | |
* @dev Internal function to remove a token ID from the list of a given address | |
* Note that this function is left internal to make ERC721Enumerable possible, but is not | |
* intended to be called by custom derived contracts: in particular, it emits no Transfer event, | |
* and doesn't clear approvals. | |
* @param from address representing the previous owner of the given token ID | |
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address | |
*/ | |
function _removeTokenFrom(address from, uint256 tokenId) internal { | |
require(ownerOf(tokenId) == from); | |
_ownedTokensCount[from] = _ownedTokensCount[from].sub(1); | |
_tokenOwner[tokenId] = address(0); | |
} | |
/** | |
* @dev Internal function to invoke `onERC721Received` on a target address | |
* The call is not executed if the target address is not a contract | |
* @param from address representing the previous owner of the given token ID | |
* @param to target address that will receive the tokens | |
* @param tokenId uint256 ID of the token to be transferred | |
* @param _data bytes optional data to send along with the call | |
* @return whether the call correctly returned the expected magic value | |
*/ | |
function _checkOnERC721Received( | |
address from, | |
address to, | |
uint256 tokenId, | |
bytes _data | |
) | |
internal | |
returns (bool) | |
{ | |
if (!to.isContract()) { | |
return true; | |
} | |
bytes4 retval = IERC721Receiver(to).onERC721Received( | |
msg.sender, from, tokenId, _data); | |
return (retval == _ERC721_RECEIVED); | |
} | |
/** | |
* @dev Private function to clear current approval of a given token ID | |
* Reverts if the given address is not indeed the owner of the token | |
* @param owner owner of the token | |
* @param tokenId uint256 ID of the token to be transferred | |
*/ | |
function _clearApproval(address owner, uint256 tokenId) private { | |
require(ownerOf(tokenId) == owner); | |
if (_tokenApprovals[tokenId] != address(0)) { | |
_tokenApprovals[tokenId] = address(0); | |
} | |
} | |
} | |
contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { | |
// Mapping from owner to list of owned token IDs | |
mapping(address => uint256[]) private _ownedTokens; | |
// Mapping from token ID to index of the owner tokens list | |
mapping(uint256 => uint256) private _ownedTokensIndex; | |
// Array with all token ids, used for enumeration | |
uint256[] private _allTokens; | |
// Mapping from token id to position in the allTokens array | |
mapping(uint256 => uint256) private _allTokensIndex; | |
bytes4 private constant _InterfaceId_ERC721Enumerable = 0x780e9d63; | |
/** | |
* 0x780e9d63 === | |
* bytes4(keccak256('totalSupply()')) ^ | |
* bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ | |
* bytes4(keccak256('tokenByIndex(uint256)')) | |
*/ | |
/** | |
* @dev Constructor function | |
*/ | |
constructor() public { | |
// register the supported interface to conform to ERC721 via ERC165 | |
_registerInterface(_InterfaceId_ERC721Enumerable); | |
} | |
/** | |
* @dev Gets the token ID at a given index of the tokens list of the requested owner | |
* @param owner address owning the tokens list to be accessed | |
* @param index uint256 representing the index to be accessed of the requested tokens list | |
* @return uint256 token ID at the given index of the tokens list owned by the requested address | |
*/ | |
function tokenOfOwnerByIndex( | |
address owner, | |
uint256 index | |
) | |
public | |
view | |
returns (uint256) | |
{ | |
require(index < balanceOf(owner)); | |
return _ownedTokens[owner][index]; | |
} | |
/** | |
* @dev Gets the total amount of tokens stored by the contract | |
* @return uint256 representing the total amount of tokens | |
*/ | |
function totalSupply() public view returns (uint256) { | |
return _allTokens.length; | |
} | |
/** | |
* @dev Gets the token ID at a given index of all the tokens in this contract | |
* Reverts if the index is greater or equal to the total number of tokens | |
* @param index uint256 representing the index to be accessed of the tokens list | |
* @return uint256 token ID at the given index of the tokens list | |
*/ | |
function tokenByIndex(uint256 index) public view returns (uint256) { | |
require(index < totalSupply()); | |
return _allTokens[index]; | |
} | |
/** | |
* @dev Internal function to add a token ID to the list of a given address | |
* This function is internal due to language limitations, see the note in ERC721.sol. | |
* It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event. | |
* @param to address representing the new owner of the given token ID | |
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address | |
*/ | |
function _addTokenTo(address to, uint256 tokenId) internal { | |
super._addTokenTo(to, tokenId); | |
uint256 length = _ownedTokens[to].length; | |
_ownedTokens[to].push(tokenId); | |
_ownedTokensIndex[tokenId] = length; | |
} | |
/** | |
* @dev Internal function to remove a token ID from the list of a given address | |
* This function is internal due to language limitations, see the note in ERC721.sol. | |
* It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event, | |
* and doesn't clear approvals. | |
* @param from address representing the previous owner of the given token ID | |
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address | |
*/ | |
function _removeTokenFrom(address from, uint256 tokenId) internal { | |
super._removeTokenFrom(from, tokenId); | |
// To prevent a gap in the array, we store the last token in the index of the token to delete, and | |
// then delete the last slot. | |
uint256 tokenIndex = _ownedTokensIndex[tokenId]; | |
uint256 lastTokenIndex = _ownedTokens[from].length.sub(1); | |
uint256 lastToken = _ownedTokens[from][lastTokenIndex]; | |
_ownedTokens[from][tokenIndex] = lastToken; | |
// This also deletes the contents at the last position of the array | |
_ownedTokens[from].length--; | |
// Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to | |
// be zero. Then we can make sure that we will remove tokenId from the ownedTokens list since we are first swapping | |
// the lastToken to the first position, and then dropping the element placed in the last position of the list | |
_ownedTokensIndex[tokenId] = 0; | |
_ownedTokensIndex[lastToken] = tokenIndex; | |
} | |
/** | |
* @dev Internal function to mint a new token | |
* Reverts if the given token ID already exists | |
* @param to address the beneficiary that will own the minted token | |
* @param tokenId uint256 ID of the token to be minted by the msg.sender | |
*/ | |
function _mint(address to, uint256 tokenId) internal { | |
super._mint(to, tokenId); | |
_allTokensIndex[tokenId] = _allTokens.length; | |
_allTokens.push(tokenId); | |
} | |
/** | |
* @dev Internal function to burn a specific token | |
* Reverts if the token does not exist | |
* @param owner owner of the token to burn | |
* @param tokenId uint256 ID of the token being burned by the msg.sender | |
*/ | |
function _burn(address owner, uint256 tokenId) internal { | |
super._burn(owner, tokenId); | |
// Reorg all tokens array | |
uint256 tokenIndex = _allTokensIndex[tokenId]; | |
uint256 lastTokenIndex = _allTokens.length.sub(1); | |
uint256 lastToken = _allTokens[lastTokenIndex]; | |
_allTokens[tokenIndex] = lastToken; | |
_allTokens[lastTokenIndex] = 0; | |
_allTokens.length--; | |
_allTokensIndex[tokenId] = 0; | |
_allTokensIndex[lastToken] = tokenIndex; | |
} | |
} | |
/** | |
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension | |
* @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract IERC721Metadata is IERC721 { | |
function name() external view returns (string); | |
function symbol() external view returns (string); | |
function tokenURI(uint256 tokenId) external view returns (string); | |
} | |
contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { | |
// Token name | |
string internal _name; | |
// Token symbol | |
string internal _symbol; | |
// Optional mapping for token URIs | |
mapping(uint256 => string) private _tokenURIs; | |
bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; | |
/** | |
* 0x5b5e139f === | |
* bytes4(keccak256('name()')) ^ | |
* bytes4(keccak256('symbol()')) ^ | |
* bytes4(keccak256('tokenURI(uint256)')) | |
*/ | |
/** | |
* @dev Constructor function | |
*/ | |
constructor(string name, string symbol) public { | |
_name = name; | |
_symbol = symbol; | |
// register the supported interfaces to conform to ERC721 via ERC165 | |
_registerInterface(InterfaceId_ERC721Metadata); | |
} | |
/** | |
* @dev Gets the token name | |
* @return string representing the token name | |
*/ | |
function name() external view returns (string) { | |
return _name; | |
} | |
/** | |
* @dev Gets the token symbol | |
* @return string representing the token symbol | |
*/ | |
function symbol() external view returns (string) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns an URI for a given token ID | |
* Throws if the token ID does not exist. May return an empty string. | |
* @param tokenId uint256 ID of the token to query | |
*/ | |
function tokenURI(uint256 tokenId) external view returns (string) { | |
require(_exists(tokenId)); | |
return _tokenURIs[tokenId]; | |
} | |
/** | |
* @dev Internal function to set the token URI for a given token | |
* Reverts if the token ID does not exist | |
* @param tokenId uint256 ID of the token to set its URI | |
* @param uri string URI to assign | |
*/ | |
function _setTokenURI(uint256 tokenId, string uri) internal { | |
require(_exists(tokenId)); | |
_tokenURIs[tokenId] = uri; | |
} | |
/** | |
* @dev Internal function to burn a specific token | |
* Reverts if the token does not exist | |
* @param owner owner of the token to burn | |
* @param tokenId uint256 ID of the token being burned by the msg.sender | |
*/ | |
function _burn(address owner, uint256 tokenId) internal { | |
super._burn(owner, tokenId); | |
// Clear metadata (if any) | |
if (bytes(_tokenURIs[tokenId]).length != 0) { | |
delete _tokenURIs[tokenId]; | |
} | |
} | |
} | |
/** | |
* @title Roles | |
* @dev Library for managing addresses assigned to a Role. | |
*/ | |
library Roles { | |
struct Role { | |
mapping (address => bool) bearer; | |
} | |
/** | |
* @dev give an account access to this role | |
*/ | |
function add(Role storage role, address account) internal { | |
require(account != address(0)); | |
require(!has(role, account)); | |
role.bearer[account] = true; | |
} | |
/** | |
* @dev remove an account's access to this role | |
*/ | |
function remove(Role storage role, address account) internal { | |
require(account != address(0)); | |
require(has(role, account)); | |
role.bearer[account] = false; | |
} | |
/** | |
* @dev check if an account has this role | |
* @return bool | |
*/ | |
function has(Role storage role, address account) | |
internal | |
view | |
returns (bool) | |
{ | |
require(account != address(0)); | |
return role.bearer[account]; | |
} | |
} | |
contract MinterRole { | |
using Roles for Roles.Role; | |
event MinterAdded(address indexed account); | |
event MinterRemoved(address indexed account); | |
Roles.Role private minters; | |
constructor() internal { | |
_addMinter(msg.sender); | |
} | |
modifier onlyMinter() { | |
require(isMinter(msg.sender)); | |
_; | |
} | |
function isMinter(address account) public view returns (bool) { | |
return minters.has(account); | |
} | |
function addMinter(address account) public onlyMinter { | |
_addMinter(account); | |
} | |
function renounceMinter() public { | |
_removeMinter(msg.sender); | |
} | |
function _addMinter(address account) internal { | |
minters.add(account); | |
emit MinterAdded(account); | |
} | |
function _removeMinter(address account) internal { | |
minters.remove(account); | |
emit MinterRemoved(account); | |
} | |
} | |
/** | |
* @title ERC721MetadataMintable | |
* @dev ERC721 minting logic with metadata | |
*/ | |
contract ERC721MetadataMintable is ERC721, ERC721Metadata, MinterRole { | |
/** | |
* @dev Function to mint tokens | |
* @param to The address that will receive the minted tokens. | |
* @param tokenId The token id to mint. | |
* @param tokenURI The token URI of the minted token. | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function mintWithTokenURI( | |
address to, | |
uint256 tokenId, | |
string tokenURI | |
) | |
public | |
onlyMinter | |
returns (bool) | |
{ | |
_mint(to, tokenId); | |
_setTokenURI(tokenId, tokenURI); | |
return true; | |
} | |
} | |
/** | |
* @title Full ERC721 Token | |
* This implementation includes all the required and some optional functionality of the ERC721 standard | |
* Moreover, it includes approve all functionality using operator terminology | |
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract ERC721FullBatchMint is ERC721Enumerable, ERC721MetadataMintable { | |
uint256 public MAX_MINT; | |
constructor(string name, string symbol, string url, address owner) | |
ERC721Metadata(name, symbol) | |
public | |
{ | |
MAX_MINT = 100; | |
_mint(owner, 0); | |
_setTokenURI(0, url); | |
} | |
function batchMint (string url) | |
public onlyMinter | |
returns (bool) { | |
uint256 totalSupply = super.totalSupply(); | |
for (uint256 i = 0; i < MAX_MINT; i++) { | |
mintWithTokenURI(msg.sender, totalSupply+i, url); | |
} | |
return true; | |
} | |
function change_max_mint(uint256 newMintValue) onlyMinter public { | |
MAX_MINT = newMintValue; | |
} | |
function changeSymbol(string newSymbol) onlyMinter public { | |
} | |
} |
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
/** | |
*Submitted for verification at Etherscan.io on 2018-04-10 | |
*/ | |
pragma solidity ^0.4.20; | |
/* | |
*A reincarnation of Mahatma Gandhi, born again to live forever on the Ethereum Blockchain | |
dddddddd | |
GGGGGGGGGGGGG d::::::dhhhhhhh iiii jjjj iiii iiii | |
GGG::::::::::::G d::::::dh:::::h i::::i j::::j i::::i i::::i | |
GG:::::::::::::::G d::::::dh:::::h iiii jjjj iiii iiii | |
G:::::GGGGGGGG::::G d:::::d h:::::h | |
G:::::G GGGGGG aaaaaaaaaaaaa nnnn nnnnnnnn ddddddddd:::::d h::::h hhhhh iiiiiiijjjjjjjiiiiiii iiiiiii ooooooooooo | |
G:::::G a::::::::::::a n:::nn::::::::nn dd::::::::::::::d h::::hh:::::hhh i:::::ij:::::ji:::::i i:::::i oo:::::::::::oo | |
G:::::G aaaaaaaaa:::::an::::::::::::::nn d::::::::::::::::d h::::::::::::::hh i::::i j::::j i::::i i::::i o:::::::::::::::o | |
G:::::G GGGGGGGGGG a::::ann:::::::::::::::nd:::::::ddddd:::::d h:::::::hhh::::::h i::::i j::::j i::::i i::::i o:::::ooooo:::::o | |
G:::::G G::::::::G aaaaaaa:::::a n:::::nnnn:::::nd::::::d d:::::d h::::::h h::::::h i::::i j::::j i::::i i::::i o::::o o::::o | |
G:::::G GGGGG::::G aa::::::::::::a n::::n n::::nd:::::d d:::::d h:::::h h:::::h i::::i j::::j i::::i i::::i o::::o o::::o | |
G:::::G G::::G a::::aaaa::::::a n::::n n::::nd:::::d d:::::d h:::::h h:::::h i::::i j::::j i::::i i::::i o::::o o::::o | |
G:::::G G::::Ga::::a a:::::a n::::n n::::nd:::::d d:::::d h:::::h h:::::h i::::i j::::j i::::i i::::i o::::o o::::o | |
G:::::GGGGGGGG::::Ga::::a a:::::a n::::n n::::nd::::::ddddd::::::dd h:::::h h:::::hi::::::ij::::ji::::::i i::::::io:::::ooooo:::::o | |
GG:::::::::::::::Ga:::::aaaa::::::a n::::n n::::n d:::::::::::::::::d h:::::h h:::::hi::::::ij::::ji::::::i ...... i::::::io:::::::::::::::o | |
GGG::::::GGG:::G a::::::::::aa:::a n::::n n::::n d:::::::::ddd::::d h:::::h h:::::hi::::::ij::::ji::::::i .::::. i::::::i oo:::::::::::oo | |
GGGGGG GGGG aaaaaaaaaa aaaa nnnnnn nnnnnn ddddddddd ddddd hhhhhhh hhhhhhhiiiiiiiij::::jiiiiiiii ...... iiiiiiii ooooooooooo | |
j::::j | |
jjjj j::::j | |
j::::jj j:::::j | |
j::::::jjj::::::j | |
jj::::::::::::j | |
jjj::::::jjj | |
jjjjjj | |
*Where there is love there is life. | |
*Happiness is when what you think, what you say, and what you do are in harmony. | |
*You must not lose faith in humanity. Humanity is an ocean; if a few drops of the ocean are dirty, the ocean does not become dirty. | |
*In a gentle way, you can shake the world. | |
*The weak can never forgive. Forgiveness is the attribute of the strong. | |
*Strength does not come from physical capacity. It comes from an indomitable will. | |
*A man is but the product of his thoughts; what he thinks, he becomes. | |
*Earth provides enough to satisfy every man's needs, but not every man's greed. | |
*Freedom is not worth having if it does not include the freedom to make mistakes. | |
*I will not let anyone walk through my mind with their dirty feet. | |
* | |
*A tribute to Mohandas Karamchand Gandhi Ji - 2 October 1869 – 30 January 1948 - Jai Hind! | |
*/ | |
contract GandhiJi { | |
/*================================= | |
= MODIFIERS = | |
=================================*/ | |
// only people with tokens | |
modifier onlybelievers () { | |
require(myTokens() > 0); | |
_; | |
} | |
// only people with profits | |
modifier onlyhodler() { | |
require(myDividends(true) > 0); | |
_; | |
} | |
// administrators can: | |
// -> change the name of the contract | |
// -> change the name of the token | |
// -> change the PoS difficulty | |
// they CANNOT: | |
// -> take funds | |
// -> disable withdrawals | |
// -> kill the contract | |
// -> change the price of tokens | |
modifier onlyAdministrator(){ | |
address _customerAddress = msg.sender; | |
require(administrators[keccak256(_customerAddress)]); | |
_; | |
} | |
modifier antiEarlyWhale(uint256 _amountOfEthereum){ | |
address _customerAddress = msg.sender; | |
if( onlyAmbassadors && ((totalEthereumBalance() - _amountOfEthereum) <= ambassadorQuota_ )){ | |
require( | |
// is the customer in the ambassador list? | |
ambassadors_[_customerAddress] == true && | |
// does the customer purchase exceed the max ambassador quota? | |
(ambassadorAccumulatedQuota_[_customerAddress] + _amountOfEthereum) <= ambassadorMaxPurchase_ | |
); | |
// updated the accumulated quota | |
ambassadorAccumulatedQuota_[_customerAddress] = SafeMath.add(ambassadorAccumulatedQuota_[_customerAddress], _amountOfEthereum); | |
// execute | |
_; | |
} else { | |
// in case the ether count drops low, the ambassador phase won't reinitiate | |
onlyAmbassadors = false; | |
_; | |
} | |
} | |
/*============================== | |
= EVENTS = | |
==============================*/ | |
event onTokenPurchase( | |
address indexed customerAddress, | |
uint256 incomingEthereum, | |
uint256 tokensMinted, | |
address indexed referredBy | |
); | |
event onTokenSell( | |
address indexed customerAddress, | |
uint256 tokensBurned, | |
uint256 ethereumEarned | |
); | |
event onReinvestment( | |
address indexed customerAddress, | |
uint256 ethereumReinvested, | |
uint256 tokensMinted | |
); | |
event onWithdraw( | |
address indexed customerAddress, | |
uint256 ethereumWithdrawn | |
); | |
// ERC20 | |
event Transfer( | |
address indexed from, | |
address indexed to, | |
uint256 tokens | |
); | |
/*===================================== | |
= CONFIGURABLES = | |
=====================================*/ | |
string public name = "Gandhiji"; | |
string public symbol = "IND"; | |
uint8 constant public decimals = 18; | |
uint8 constant internal dividendFee_ = 10; | |
uint256 constant internal tokenPriceInitial_ = 0.0000001 ether; | |
uint256 constant internal tokenPriceIncremental_ = 0.00000001 ether; | |
uint256 constant internal magnitude = 2**64; | |
// proof of stake (defaults at 1 token) | |
uint256 public stakingRequirement = 1e18; | |
// ambassador program | |
mapping(address => bool) internal ambassadors_; | |
uint256 constant internal ambassadorMaxPurchase_ = 1 ether; | |
uint256 constant internal ambassadorQuota_ = 1 ether; | |
/*================================ | |
= DATASETS = | |
================================*/ | |
// amount of shares for each address (scaled number) | |
mapping(address => uint256) public tokenBalanceLedger_; | |
mapping(address => uint256) public referralBalance_; | |
mapping(address => int256) public payoutsTo_; | |
mapping(address => uint256) public ambassadorAccumulatedQuota_; | |
uint256 internal tokenSupply_ = 0; | |
uint256 public profitPerShare_; | |
// administrator list (see above on what they can do) | |
mapping(bytes32 => bool) public administrators; | |
bool public onlyAmbassadors = false; | |
/*======================================= | |
= PUBLIC FUNCTIONS = | |
=======================================*/ | |
/* | |
* -- APPLICATION ENTRY POINTS -- | |
*/ | |
function GandhiJi() | |
public | |
{ | |
// add administrators here | |
administrators[0x9bcc16873606dc04acb98263f74c420525ddef61de0d5f18fd97d16de659131a] = true; | |
ambassadors_[0x0000000000000000000000000000000000000000] = true; | |
} | |
/** | |
* Converts all incoming Ethereum to tokens for the caller, and passes down the referral address (if any) | |
*/ | |
function buy(address _referredBy) | |
public | |
payable | |
returns(uint256) | |
{ | |
purchaseTokens(msg.value, _referredBy); | |
} | |
function() | |
payable | |
public | |
{ | |
purchaseTokens(msg.value, 0x0); | |
} | |
/** | |
* Converts all of caller's dividends to tokens. | |
*/ | |
function reinvest() | |
onlyhodler() | |
public | |
{ | |
// fetch dividends | |
uint256 _dividends = myDividends(false); // retrieve ref. bonus later in the code | |
// pay out the dividends virtually | |
address _customerAddress = msg.sender; | |
payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); | |
// retrieve ref. bonus | |
_dividends += referralBalance_[_customerAddress]; | |
referralBalance_[_customerAddress] = 0; | |
// dispatch a buy order with the virtualized "withdrawn dividends" | |
uint256 _tokens = purchaseTokens(_dividends, 0x0); | |
// fire event | |
onReinvestment(_customerAddress, _dividends, _tokens); | |
} | |
/** | |
* Alias of sell() and withdraw(). | |
*/ | |
function exit() | |
public | |
{ | |
// get token count for caller & sell them all | |
address _customerAddress = msg.sender; | |
uint256 _tokens = tokenBalanceLedger_[_customerAddress]; | |
if(_tokens > 0) sell(_tokens); | |
withdraw(); | |
} | |
/** | |
* Withdraws all of the callers earnings. | |
*/ | |
function withdraw() | |
onlyhodler() | |
public | |
{ | |
// setup data | |
address _customerAddress = msg.sender; | |
uint256 _dividends = myDividends(false); // get ref. bonus later in the code | |
// update dividend tracker | |
payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); | |
// add ref. bonus | |
_dividends += referralBalance_[_customerAddress]; | |
referralBalance_[_customerAddress] = 0; | |
// delivery service | |
_customerAddress.transfer(_dividends); | |
// fire event | |
onWithdraw(_customerAddress, _dividends); | |
} | |
/** | |
* Liquifies tokens to ethereum. | |
*/ | |
function sell(uint256 _amountOfTokens) | |
onlybelievers () | |
public | |
{ | |
address _customerAddress = msg.sender; | |
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
uint256 _tokens = _amountOfTokens; | |
uint256 _ethereum = tokensToEthereum_(_tokens); | |
uint256 _dividends = SafeMath.div(_ethereum, dividendFee_); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); | |
// burn the sold tokens | |
tokenSupply_ = SafeMath.sub(tokenSupply_, _tokens); | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _tokens); | |
// update dividends tracker | |
int256 _updatedPayouts = (int256) (profitPerShare_ * _tokens + (_taxedEthereum * magnitude)); | |
payoutsTo_[_customerAddress] -= _updatedPayouts; | |
// dividing by zero is a bad idea | |
if (tokenSupply_ > 0) { | |
// update the amount of dividends per token | |
profitPerShare_ = SafeMath.add(profitPerShare_, (_dividends * magnitude) / tokenSupply_); | |
} | |
// fire event | |
onTokenSell(_customerAddress, _tokens, _taxedEthereum); | |
} | |
/** | |
* Transfer tokens from the caller to a new holder. | |
* Remember, there's a 10% fee here as well. | |
*/ | |
function transfer(address _toAddress, uint256 _amountOfTokens) | |
onlybelievers () | |
public | |
returns(bool) | |
{ | |
// setup | |
address _customerAddress = msg.sender; | |
// make sure we have the requested tokens | |
require(!onlyAmbassadors && _amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
// withdraw all outstanding dividends first | |
if(myDividends(true) > 0) withdraw(); | |
// liquify 10% of the tokens that are transfered | |
// these are dispersed to shareholders | |
uint256 _tokenFee = SafeMath.div(_amountOfTokens, dividendFee_); | |
uint256 _taxedTokens = SafeMath.sub(_amountOfTokens, _tokenFee); | |
uint256 _dividends = tokensToEthereum_(_tokenFee); | |
// burn the fee tokens | |
tokenSupply_ = SafeMath.sub(tokenSupply_, _tokenFee); | |
// exchange tokens | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
tokenBalanceLedger_[_toAddress] = SafeMath.add(tokenBalanceLedger_[_toAddress], _taxedTokens); | |
// update dividend trackers | |
payoutsTo_[_customerAddress] -= (int256) (profitPerShare_ * _amountOfTokens); | |
payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _taxedTokens); | |
// disperse dividends among holders | |
profitPerShare_ = SafeMath.add(profitPerShare_, (_dividends * magnitude) / tokenSupply_); | |
// fire event | |
Transfer(_customerAddress, _toAddress, _taxedTokens); | |
// ERC20 | |
return true; | |
} | |
/*---------- ADMINISTRATOR ONLY FUNCTIONS ----------*/ | |
/** | |
* administrator can manually disable the ambassador phase. | |
*/ | |
function disableInitialStage() | |
onlyAdministrator() | |
public | |
{ | |
onlyAmbassadors = false; | |
} | |
function setAdministrator(bytes32 _identifier, bool _status) | |
onlyAdministrator() | |
public | |
{ | |
administrators[_identifier] = _status; | |
} | |
function setStakingRequirement(uint256 _amountOfTokens) | |
onlyAdministrator() | |
public | |
{ | |
stakingRequirement = _amountOfTokens; | |
} | |
function setName(string _name) | |
onlyAdministrator() | |
public | |
{ | |
name = _name; | |
} | |
function setSymbol(string _symbol) | |
onlyAdministrator() | |
public | |
{ | |
symbol = _symbol; | |
} | |
/*---------- HELPERS AND CALCULATORS ----------*/ | |
/** | |
* Method to view the current Ethereum stored in the contract | |
* Example: totalEthereumBalance() | |
*/ | |
function totalEthereumBalance() | |
public | |
view | |
returns(uint) | |
{ | |
return this.balance; | |
} | |
/** | |
* Retrieve the total token supply. | |
*/ | |
function totalSupply() | |
public | |
view | |
returns(uint256) | |
{ | |
return tokenSupply_; | |
} | |
/** | |
* Retrieve the tokens owned by the caller. | |
*/ | |
function myTokens() | |
public | |
view | |
returns(uint256) | |
{ | |
address _customerAddress = msg.sender; | |
return balanceOf(_customerAddress); | |
} | |
/** | |
* Retrieve the dividends owned by the caller. | |
*/ | |
function myDividends(bool _includeReferralBonus) | |
public | |
view | |
returns(uint256) | |
{ | |
address _customerAddress = msg.sender; | |
return _includeReferralBonus ? dividendsOf(_customerAddress) + referralBalance_[_customerAddress] : dividendsOf(_customerAddress) ; | |
} | |
/** | |
* Retrieve the token balance of any single address. | |
*/ | |
function balanceOf(address _customerAddress) | |
view | |
public | |
returns(uint256) | |
{ | |
return tokenBalanceLedger_[_customerAddress]; | |
} | |
/** | |
* Retrieve the dividend balance of any single address. | |
*/ | |
function dividendsOf(address _customerAddress) | |
view | |
public | |
returns(uint256) | |
{ | |
return (uint256) ((int256)(profitPerShare_ * tokenBalanceLedger_[_customerAddress]) - payoutsTo_[_customerAddress]) / magnitude; | |
} | |
/** | |
* Return the buy price of 1 individual token. | |
*/ | |
function sellPrice() | |
public | |
view | |
returns(uint256) | |
{ | |
if(tokenSupply_ == 0){ | |
return tokenPriceInitial_ - tokenPriceIncremental_; | |
} else { | |
uint256 _ethereum = tokensToEthereum_(1e18); | |
uint256 _dividends = SafeMath.div(_ethereum, dividendFee_ ); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
} | |
/** | |
* Return the sell price of 1 individual token. | |
*/ | |
function buyPrice() | |
public | |
view | |
returns(uint256) | |
{ | |
if(tokenSupply_ == 0){ | |
return tokenPriceInitial_ + tokenPriceIncremental_; | |
} else { | |
uint256 _ethereum = tokensToEthereum_(1e18); | |
uint256 _dividends = SafeMath.div(_ethereum, dividendFee_ ); | |
uint256 _taxedEthereum = SafeMath.add(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
} | |
function calculateTokensReceived(uint256 _ethereumToSpend) | |
public | |
view | |
returns(uint256) | |
{ | |
uint256 _dividends = SafeMath.div(_ethereumToSpend, dividendFee_); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereumToSpend, _dividends); | |
uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); | |
return _amountOfTokens; | |
} | |
function calculateEthereumReceived(uint256 _tokensToSell) | |
public | |
view | |
returns(uint256) | |
{ | |
require(_tokensToSell <= tokenSupply_); | |
uint256 _ethereum = tokensToEthereum_(_tokensToSell); | |
uint256 _dividends = SafeMath.div(_ethereum, dividendFee_); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
/*========================================== | |
= INTERNAL FUNCTIONS = | |
==========================================*/ | |
function purchaseTokens(uint256 _incomingEthereum, address _referredBy) | |
antiEarlyWhale(_incomingEthereum) | |
internal | |
returns(uint256) | |
{ | |
// data setup | |
address _customerAddress = msg.sender; | |
uint256 _undividedDividends = SafeMath.div(_incomingEthereum, dividendFee_); | |
uint256 _referralBonus = SafeMath.div(_undividedDividends, 3); | |
uint256 _dividends = SafeMath.sub(_undividedDividends, _referralBonus); | |
uint256 _taxedEthereum = SafeMath.sub(_incomingEthereum, _undividedDividends); | |
uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); | |
uint256 _fee = _dividends * magnitude; | |
require(_amountOfTokens > 0 && (SafeMath.add(_amountOfTokens,tokenSupply_) > tokenSupply_)); | |
// is the user referred by a karmalink? | |
if( | |
// is this a referred purchase? | |
_referredBy != 0x0000000000000000000000000000000000000000 && | |
// no cheating! | |
_referredBy != _customerAddress && | |
tokenBalanceLedger_[_referredBy] >= stakingRequirement | |
){ | |
// wealth redistribution | |
referralBalance_[_referredBy] = SafeMath.add(referralBalance_[_referredBy], _referralBonus); | |
} else { | |
// no ref purchase | |
// add the referral bonus back to the global dividends cake | |
_dividends = SafeMath.add(_dividends, _referralBonus); | |
_fee = _dividends * magnitude; | |
} | |
// we can't give people infinite ethereum | |
if(tokenSupply_ > 0){ | |
// add tokens to the pool | |
tokenSupply_ = SafeMath.add(tokenSupply_, _amountOfTokens); | |
// take the amount of dividends gained through this transaction, and allocates them evenly to each shareholder | |
profitPerShare_ += (_dividends * magnitude / (tokenSupply_)); | |
// calculate the amount of tokens the customer receives over his purchase | |
_fee = _fee - (_fee-(_amountOfTokens * (_dividends * magnitude / (tokenSupply_)))); | |
} else { | |
// add tokens to the pool | |
tokenSupply_ = _amountOfTokens; | |
} | |
// update circulating supply & the ledger address for the customer | |
tokenBalanceLedger_[_customerAddress] = SafeMath.add(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
int256 _updatedPayouts = (int256) ((profitPerShare_ * _amountOfTokens) - _fee); | |
payoutsTo_[_customerAddress] += _updatedPayouts; | |
// fire event | |
onTokenPurchase(_customerAddress, _incomingEthereum, _amountOfTokens, _referredBy); | |
return _amountOfTokens; | |
} | |
/** | |
* Calculate Token price based on an amount of incoming ethereum | |
* It's an algorithm, hopefully we gave you the whitepaper with it in scientific notation; | |
* Some conversions occurred to prevent decimal errors or underflows / overflows in solidity code. | |
*/ | |
function ethereumToTokens_(uint256 _ethereum) | |
internal | |
view | |
returns(uint256) | |
{ | |
uint256 _tokenPriceInitial = tokenPriceInitial_ * 1e18; | |
uint256 _tokensReceived = | |
( | |
( | |
// underflow attempts BTFO | |
SafeMath.sub( | |
(sqrt | |
( | |
(_tokenPriceInitial**2) | |
+ | |
(2*(tokenPriceIncremental_ * 1e18)*(_ethereum * 1e18)) | |
+ | |
(((tokenPriceIncremental_)**2)*(tokenSupply_**2)) | |
+ | |
(2*(tokenPriceIncremental_)*_tokenPriceInitial*tokenSupply_) | |
) | |
), _tokenPriceInitial | |
) | |
)/(tokenPriceIncremental_) | |
)-(tokenSupply_) | |
; | |
return _tokensReceived; | |
} | |
function test() pure view returns(uint256){ | |
return (msg.value.mul(94)).div(10) | |
} | |
/** | |
* Calculate token sell value. | |
*/ | |
function tokensToEthereum_(uint256 _tokens) | |
internal | |
view | |
returns(uint256) | |
{ | |
uint256 tokens_ = (_tokens + 1e18); | |
uint256 _tokenSupply = (tokenSupply_ + 1e18); | |
uint256 _etherReceived = | |
( | |
// underflow attempts BTFO | |
SafeMath.sub( | |
( | |
( | |
( | |
tokenPriceInitial_ +(tokenPriceIncremental_ * (_tokenSupply/1e18)) | |
)-tokenPriceIncremental_ | |
)*(tokens_ - 1e18) | |
),(tokenPriceIncremental_*((tokens_**2-tokens_)/1e18))/2 | |
) | |
/1e18); | |
return _etherReceived; | |
} | |
function sqrt(uint x) internal pure returns (uint y) { | |
uint z = (x + 1) / 2; | |
y = x; | |
while (z < y) { | |
y = z; | |
z = (x / z + z) / 2; | |
} | |
} | |
} | |
/** | |
* @title SafeMath | |
* @dev Math operations with safety checks that throw on error | |
*/ | |
library SafeMath { | |
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; | |
} | |
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; | |
} | |
function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint256 a, uint256 b) internal pure returns (uint256) { | |
uint256 c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
/** | |
* Also in memory of JPK, miss you Dad. | |
*/ | |
} |
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.6.0; | |
contract ExampleContract { | |
uint256 private _a; | |
uint256 private _b; | |
uint256 private _c; | |
function newA(uint256 a) external returns (bool) { | |
_a = a; | |
return true; | |
} | |
function newB(uint256 b) external returns (bool) { | |
_b = b; | |
return true; | |
} | |
function newC(uint256 c) external returns (bool) { | |
_c = c; | |
return true; | |
} | |
function getA() external view returns (uint256) { | |
return _a; | |
} | |
function getB() external view returns (uint256) { | |
return _b; | |
} | |
function getC() external view returns (uint256) { | |
return _c; | |
} | |
} |
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
/** | |
* www.the8020.ch | |
*/ | |
pragma solidity ^0.6.0; | |
/*================================================================================== | |
= The 80/20 is a Wealth Distribution system that is open for anyone to use. = | |
= We created this application with hopes that it will provide a steady stream = | |
= of passive income for generations to come. The foundation that stands behind = | |
= this product would like you to live happy, free, and prosperous. = | |
= Stay tuned for more dApps from the GSG Global Marketing Group. = | |
= #LuckyRico #LACGold #JCunn24 #BoHarvey #LennyBones #WealthWithPhelps = | |
= #ShahzainTariq >= developer of this smart contract = | |
================================================================================*/ | |
interface IERC20 { | |
function totalSupply() external view returns (uint256); | |
function balanceOf(address account) external view returns (uint256); | |
function transfer(address recipient, uint256 amount) external returns (bool); | |
function allowance(address owner, address spender) external view returns (uint256); | |
function approve(address spender, uint256 amount) external returns (bool); | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
event Transfer(address indexed from, address indexed to, uint256 value); | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
contract auto_pool is IERC20{ | |
using SafeMath for uint256; | |
/*================================= | |
= MODIFIERS = | |
=================================*/ | |
// only people with tokens | |
modifier onlybelievers () { | |
require(myTokens() > 0); | |
_; | |
} | |
// only people with profits | |
modifier onlyhodler() { | |
require(myDividends(true) > 0); | |
_; | |
} | |
/*============================== | |
= EVENTS = | |
==============================*/ | |
event onTokenPurchase( | |
address indexed customerAddress, | |
uint256 incomingEthereum, | |
uint256 tokensMinted, | |
address indexed referredBy, | |
uint256 time, | |
uint256 totalTokens | |
); | |
event onTokenSell( | |
address indexed customerAddress, | |
uint256 tokensBurned, | |
uint256 ethereumEarned, | |
uint256 time, | |
uint256 totalTokens | |
); | |
event onReinvestment( | |
address indexed customerAddress, | |
uint256 ethereumReinvested, | |
uint256 tokensMinted | |
); | |
event onWithdraw( | |
address indexed customerAddress, | |
uint256 ethereumWithdrawn | |
); | |
event distrubuteBonusFund( | |
address, | |
uint256 | |
); | |
event amountDistributedToSponsor( | |
address, | |
address, | |
uint256 | |
); | |
// ERC20 | |
event Transfer( | |
address indexed from, | |
address indexed to, | |
uint256 tokens, | |
uint256 time | |
); | |
/*===================================== | |
= CONFIGURABLES = | |
=====================================*/ | |
string public name ; | |
string public symbol ; | |
uint8 public decimals ; | |
uint8 internal dividendFee_ ; | |
uint256 internal tokenPriceInitial_ ; | |
uint256 internal tokenPriceIncremental_ ; | |
uint256 internal magnitude; | |
uint256 public tokenPool; | |
uint256 public loyaltyPool; | |
uint256 public developmentFund; | |
uint256 public sponsorsPaid; | |
uint256 public gsg_foundation; | |
address dev1; | |
address dev2; | |
address GSGO_Official_LoyaltyPlan; | |
uint256 public currentId; | |
uint256 public day; | |
uint256 public claimedLoyalty; | |
uint256 public totalDeposited; | |
uint256 public totalWithdraw; | |
/*================================ | |
= DATASETS = | |
================================*/ | |
// amount of shares for each address (scaled number) | |
mapping(address => uint256) public tokenBalanceLedger_; | |
mapping(address => uint256) public referralBalance_; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
mapping(address => int256) public payoutsTo_; | |
mapping(address => basicData) public users; | |
mapping(uint256 => address) public userList; | |
uint256 internal tokenSupply_ = 0; | |
uint256 internal profitPerShare_; | |
uint256 internal profitperLoyalty; | |
//Users's data set | |
struct basicData{ | |
bool isExist; | |
uint256 id; | |
uint256 referrerId; | |
address referrerAdd; | |
} | |
/*======================================= | |
= PUBLIC FUNCTIONS = | |
=======================================*/ | |
/* | |
* -- APPLICATION ENTRY POINTS -- | |
*/ | |
constructor() public{ | |
name = "The-Eighty-Twenty"; | |
symbol = "GS20"; | |
decimals = 18; | |
dividendFee_ = 10; | |
tokenPriceInitial_ = 0.0000001 ether; | |
tokenPriceIncremental_ = 0.00000001 ether; | |
magnitude = 2**64; | |
// "This is the distribution contract for holders of the GSG-Official (GSGO) Token." | |
GSGO_Official_LoyaltyPlan = address(0x727395b95C90DEab2F220Ce42615d9dD0F44e187); | |
dev1 = address(0x88F2E544359525833f606FB6c63826E143132E7b); | |
dev2 = address(0x7cF196415CDD1eF08ca2358a8282D33Ba089B9f3); | |
currentId = 0; | |
day = now; | |
} | |
/** | |
* Converts all incoming Ethereum to tokens for the caller, and passes down the referral address (if any) | |
*/ | |
function buy(address _referredAdd) | |
public | |
payable | |
returns(uint256) | |
{ | |
require(msg.value >= 0.1 ether, "ERROR: minimun 0.1 ethereum "); | |
require(_referredAdd != msg.sender,"ERROR: cannot become own ref"); | |
if(!users[msg.sender].isExist) register(msg.sender,_referredAdd); | |
purchaseTokens(msg.value,_referredAdd); | |
//Distributing Ethers | |
loyaltyPool += ((msg.value.mul(12)).div(100)); | |
developmentFund += ((msg.value.mul(2)).div(100)); | |
gsg_foundation += ((msg.value.mul(2)).div(100)); | |
payable(GSGO_Official_LoyaltyPlan).transfer((msg.value.mul(2)).div(100)); | |
payable(dev1).transfer((msg.value.mul(1)).div(100)); | |
payable(dev2).transfer((msg.value.mul(1)).div(100)); | |
totalDeposited += msg.value; | |
} | |
receive() external payable { | |
require(msg.value >= 0.1 ether, "ERROR: minimun 0.1 ethereum ."); | |
if(!users[msg.sender].isExist) register(msg.sender,address(0)); | |
purchaseTokens(msg.value,address(0)); | |
//Distributing Ethers | |
loyaltyPool += ((msg.value.mul(12)).div(100)); | |
developmentFund += ( (msg.value.mul(2)).div(100)); | |
gsg_foundation += ((msg.value.mul(2)).div(100)); | |
payable(GSGO_Official_LoyaltyPlan).transfer((msg.value.mul(2)).div(100)); | |
payable(dev1).transfer((msg.value.mul(1)).div(100)); | |
payable(dev2).transfer((msg.value.mul(1)).div(100)); | |
} | |
fallback() | |
payable | |
external | |
{ | |
require(msg.value >= 0.1 ether, "ERROR: minimun 0.1 ethereum ."); | |
if(!users[msg.sender].isExist) register(msg.sender,address(0)); | |
purchaseTokens(msg.value,address(0)); | |
//Distributing Ethers | |
loyaltyPool += ((msg.value.mul(12)).div(100)); | |
developmentFund += ( (msg.value.mul(2)).div(100)); | |
gsg_foundation += ((msg.value.mul(2)).div(100)); | |
payable(GSGO_Official_LoyaltyPlan).transfer((msg.value.mul(2)).div(100)); | |
payable(dev1).transfer((msg.value.mul(1)).div(100)); | |
payable(dev2).transfer((msg.value.mul(1)).div(100)); } | |
/** | |
* Converts all of caller's dividends to tokens. | |
*/ | |
function reinvest() | |
onlyhodler() | |
public | |
{ | |
address _customerAddress = msg.sender; | |
// fetch dividends | |
uint256 _dividends = myDividends(false); // retrieve ref. bonus later in the code | |
uint256 _loyaltyEth = loyaltyOf(); | |
if(_loyaltyEth > 0 ether){ | |
payable(address(_customerAddress)).transfer(_loyaltyEth); | |
loyaltyPool -= _loyaltyEth; | |
claimedLoyalty += _loyaltyEth; | |
totalWithdraw += _loyaltyEth; | |
} | |
// pay out the dividends virtually | |
payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); | |
// retrieve ref. bonus | |
_dividends += referralBalance_[_customerAddress]; | |
referralBalance_[_customerAddress] = 0; | |
// dispatch a buy order with the virtualized "withdrawn dividends" | |
address refAdd = users[_customerAddress].referrerAdd; | |
// dispatch a buy order with the virtualized "withdrawn dividends" | |
uint256 _tokens = purchaseTokens(_dividends,refAdd); | |
loyaltyPool += ((_dividends.mul(12)).div(100)); | |
developmentFund += ((_dividends.mul(2)).div(100)); | |
gsg_foundation += ((_dividends.mul(2)).div(100)); | |
payable(GSGO_Official_LoyaltyPlan).transfer((_dividends.mul(2)).div(100)); | |
payable(dev1).transfer((_dividends.mul(1)).div(100)); | |
payable(dev2).transfer((_dividends.mul(1)).div(100)); | |
// fire event | |
emit onReinvestment(_customerAddress, _dividends, _tokens); | |
} | |
/** | |
* Alias of sell() and withdraw(). | |
*/ | |
function exit() | |
public | |
{ | |
// get token count for caller & sell them all | |
address _customerAddress = msg.sender; | |
uint256 _tokens = tokenBalanceLedger_[_customerAddress]; | |
if(_tokens > 0) sell(_tokens); | |
withdraw(); | |
} | |
/** | |
* Withdraws all of the callers earnings. | |
*/ | |
function withdraw() | |
onlyhodler() | |
public | |
{ | |
// setup data | |
address _customerAddress = msg.sender; | |
uint256 _dividends = myDividends(false); // get ref. bonus later in the code | |
uint256 _loyaltyEth = loyaltyOf(); | |
// update dividend tracker | |
payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); | |
if(_loyaltyEth > 0 ether) { | |
_dividends += _loyaltyEth; | |
loyaltyPool -= _loyaltyEth; | |
claimedLoyalty += _loyaltyEth; | |
} | |
// add ref. bonus | |
_dividends += referralBalance_[_customerAddress]; | |
referralBalance_[_customerAddress] = 0; | |
totalWithdraw += _dividends; | |
// delivery service | |
payable(address(_customerAddress)).transfer(_dividends); | |
// fire event | |
emit onWithdraw(_customerAddress, _dividends); | |
} | |
/** | |
* Liquifies tokens to ethereum. | |
*/ | |
function sell(uint256 _amountOfTokens) | |
onlybelievers () | |
public | |
{ | |
address _customerAddress = msg.sender; | |
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
//initializating values; | |
uint256 _tokens = _amountOfTokens; | |
uint256 _ethereum = tokensToEthereum_(_tokens); | |
uint256 tax = (_ethereum.mul(5)).div(100); | |
loyaltyPool = SafeMath.add(loyaltyPool,tax); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, tax); | |
// burn the sold tokens | |
tokenSupply_ = SafeMath.sub(tokenSupply_, _tokens); | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _tokens); | |
//updates dividends tracker | |
int256 _updatedPayouts = (int256) (profitPerShare_ * _tokens + (_taxedEthereum * magnitude)); | |
payoutsTo_[_customerAddress] -= _updatedPayouts; | |
payoutsTo_[_customerAddress] += (int256) (_taxedEthereum*magnitude); | |
totalWithdraw += _taxedEthereum; | |
//tranfer amout of ethers to user | |
payable(address(_customerAddress)).transfer(_taxedEthereum); | |
if(_ethereum < tokenPool) { | |
tokenPool = SafeMath.sub(tokenPool, _ethereum); | |
} | |
// fire event | |
emit onTokenSell(_customerAddress, _tokens, _taxedEthereum,now,tokenBalanceLedger_[_customerAddress]); | |
} | |
function approve(address spender, uint amount) public override returns (bool) { | |
_approve(msg.sender, spender, amount); | |
return true; | |
} | |
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
_approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)); | |
return true; | |
} | |
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
_approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* Transfer tokens from the caller to a new holder. | |
* Remember, there's a 10% fee here as well. | |
*/ | |
function transfer(address _toAddress, uint256 _amountOfTokens) | |
onlybelievers () | |
public | |
override | |
returns(bool) | |
{ | |
// setup | |
address _customerAddress = msg.sender; | |
// make sure we have the requested tokens | |
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
// exchange tokens | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
tokenBalanceLedger_[_toAddress] = SafeMath.add(tokenBalanceLedger_[_toAddress], _amountOfTokens); | |
// update dividend trackers | |
payoutsTo_[_customerAddress] -= (int256) (profitPerShare_ * _amountOfTokens); | |
payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _amountOfTokens); | |
// fire event | |
emit Transfer(_customerAddress, _toAddress, _amountOfTokens,now); | |
// ERC20 | |
return true; | |
} | |
function transferFrom(address sender, address _toAddress, uint _amountOfTokens) public override returns (bool) { | |
// setup | |
address _customerAddress = sender; | |
// make sure we have the requested tokens | |
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
// exchange tokens | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
tokenBalanceLedger_[_toAddress] = SafeMath.add(tokenBalanceLedger_[_toAddress], _amountOfTokens); | |
// update dividend trackers | |
payoutsTo_[_customerAddress] -= (int256) (profitPerShare_ * _amountOfTokens); | |
payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _amountOfTokens); | |
// fire event | |
emit Transfer(_customerAddress, _toAddress, _amountOfTokens,now); | |
_approve(sender, msg.sender, _allowances[sender][msg.sender].sub(_amountOfTokens, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/*---------- HELPERS AND CALCULATORS ----------*/ | |
/** | |
* Method to view the current Ethereum stored in the contract | |
* Example: totalEthereumBalance() | |
*/ | |
function totalEthereumBalance() | |
public | |
view | |
returns(uint) | |
{ | |
return address(this).balance; | |
} | |
/** | |
* Retrieve the total token supply. | |
*/ | |
function totalSupply() | |
public | |
override | |
view | |
returns(uint256) | |
{ | |
return tokenSupply_; | |
} | |
/** | |
* Retrieve the tokens owned by the caller. | |
*/ | |
function myTokens() | |
public | |
view | |
returns(uint256) | |
{ | |
address _customerAddress = msg.sender; | |
return balanceOf(_customerAddress); | |
} | |
/** | |
* Retrieve the dividends owned by the caller. | |
*/ | |
function myDividends(bool _includeReferralBonus) | |
public | |
view | |
returns(uint256) | |
{ | |
address _customerAddress = msg.sender; | |
return _includeReferralBonus ? dividendsOf(_customerAddress) + referralBalance_[_customerAddress] : dividendsOf(_customerAddress) ; | |
} | |
/** | |
* Retrieve the token balance of any single address. | |
*/ | |
function balanceOf(address _customerAddress) | |
view | |
public | |
override | |
returns(uint256) | |
{ | |
return tokenBalanceLedger_[_customerAddress]; | |
} | |
/** | |
* Retrieve the dividend balance of any single address. | |
*/ | |
function dividendsOf(address _customerAddress) | |
view | |
public | |
returns(uint256) | |
{ | |
return (uint256) ((int256)(profitPerShare_ * tokenBalanceLedger_[_customerAddress]) - payoutsTo_[_customerAddress]) / magnitude; | |
} | |
/** | |
* Return the buy price of 1 individual token. | |
*/ | |
function sellPrice() | |
public | |
view | |
returns(uint256) | |
{ | |
if(tokenSupply_ == 0){ | |
return tokenPriceInitial_ - tokenPriceIncremental_; | |
} else { | |
uint256 _ethereum = tokensToEthereum_(1e18); | |
uint256 tax = (_ethereum.mul(5)).div(100); | |
uint256 _dividends = SafeMath.div(_ethereum, tax); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
} | |
/** | |
* Return the sell price of 1 individual token. | |
*/ | |
function buyPrice() | |
public | |
view | |
returns(uint256) | |
{ | |
if(tokenSupply_ == 0){ | |
return tokenPriceInitial_ + tokenPriceIncremental_; | |
} else { | |
uint256 _ethereum = tokensToEthereum_(1e18); | |
uint256 _dividends = SafeMath.div(_ethereum, dividendFee_ ); | |
uint256 _taxedEthereum = SafeMath.add(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
} | |
function calculateTokensReceived(uint256 _ethToSpend) | |
public | |
view | |
returns(uint256) | |
{ | |
uint256 _ethereumToSpend = (_ethToSpend.mul(64)).div(100); | |
uint256 _dividends = SafeMath.div(_ethereumToSpend, dividendFee_); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereumToSpend, _dividends); | |
uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); | |
return _amountOfTokens; | |
} | |
function getReferrer() public view returns(address){ | |
return users[msg.sender].referrerAdd; | |
} | |
function calculateEthereumReceived(uint256 _tokensToSell) | |
public | |
view | |
returns(uint256) | |
{ | |
require(_tokensToSell <= tokenSupply_); | |
uint256 _ethereum = tokensToEthereum_(_tokensToSell); | |
uint256 tax = (_ethereum.mul(5)).div(100); | |
uint256 _dividends = SafeMath.div(_ethereum, tax); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
function loyaltyOf() public view returns(uint256){ | |
address _customerAddress = msg.sender; | |
// user should hold 2500 tokens for qualify for loyalty bonus; | |
if(tokenBalanceLedger_[_customerAddress] >= 2000*10**uint256(decimals)){ | |
// return loyalty bonus users | |
return ((uint256) ((int256)((profitperLoyalty) * tokenBalanceLedger_[_customerAddress]) - payoutsTo_[_customerAddress]) / magnitude)*14/5; | |
} | |
else{ | |
return 0; | |
} | |
} | |
function userReferrer(address _address) public view returns(address){ | |
return userList[users[_address].referrerId]; | |
} | |
/*========================================== | |
= INTERNAL FUNCTIONS = | |
==========================================*/ | |
function purchaseTokens(uint256 _eth, address _referredBy) | |
internal | |
returns(uint256) | |
{ | |
uint256 _incomingEthereum = (_eth.mul(64)).div(100); | |
// data setup | |
address _customerAddress = msg.sender; | |
uint256 _undividedDividends = SafeMath.div(_incomingEthereum, dividendFee_); | |
uint256 _referralBonus = SafeMath.div(_undividedDividends, 3); | |
uint256 _dividends = SafeMath.sub(_undividedDividends, _referralBonus); | |
uint256 _taxedEthereum = SafeMath.sub(_incomingEthereum, _undividedDividends); | |
uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); | |
uint256 _fee = _dividends * magnitude; | |
tokenPool += _taxedEthereum; | |
require(_amountOfTokens > 0 && (SafeMath.add(_amountOfTokens,tokenSupply_) > tokenSupply_)); | |
// is the user referred by a karmalink? | |
if( | |
// is this a referred purchase? | |
_referredBy != 0x0000000000000000000000000000000000000000 && | |
// no cheating! | |
_referredBy != _customerAddress | |
){ | |
// wealth redistribution | |
distributeToSponsor(_referredBy,_eth); | |
} else { | |
// no ref purchase | |
// add the referral bonus back to the global dividends cake | |
_dividends = SafeMath.add(_dividends, _referralBonus); | |
_fee = _dividends * magnitude; | |
} | |
// we can't give people infinite ethereum | |
if(tokenSupply_ > 0){ | |
// add tokens to the pool | |
tokenSupply_ = SafeMath.add(tokenSupply_, _amountOfTokens); | |
// take the amount of dividends gained through this transaction, and allocates them evenly to each shareholder | |
profitPerShare_ += (_dividends * magnitude / (tokenSupply_)); | |
profitperLoyalty += ((_dividends) * magnitude / (tokenSupply_)); | |
// calculate the amount of tokens the customer receives over his purchase | |
_fee = _fee - (_fee-(_amountOfTokens * (_dividends * magnitude / (tokenSupply_)))); | |
} else { | |
// add tokens to the pool | |
tokenSupply_ = _amountOfTokens; | |
} | |
// update circulating supply & the ledger address for the customer | |
tokenBalanceLedger_[_customerAddress] = SafeMath.add(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
//update dividends tracker | |
int256 _updatedPayouts = (int256) ((profitPerShare_ * _amountOfTokens) - _fee); | |
payoutsTo_[_customerAddress] += _updatedPayouts; | |
// fire event | |
emit onTokenPurchase(_customerAddress, _incomingEthereum, _amountOfTokens, _referredBy,now,tokenBalanceLedger_[_customerAddress]); | |
return _amountOfTokens; | |
} | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* Calculate Token price based on an amount of incoming ethereum | |
* Some conversions occurred to prevent decimal errors or underflows / overflows in solidity code. | |
*/ | |
function ethereumToTokens_(uint256 _ethereum) | |
internal | |
view | |
returns(uint256) | |
{ | |
uint256 _tokenPriceInitial = tokenPriceInitial_ * 1e18; | |
uint256 _tokensReceived = | |
( | |
( | |
// underflow attempts BTFO | |
SafeMath.sub( | |
(sqrt | |
( | |
(_tokenPriceInitial**2) | |
+ | |
(2*(tokenPriceIncremental_ * 1e18)*(_ethereum * 1e18)) | |
+ | |
(((tokenPriceIncremental_)**2)*(tokenSupply_**2)) | |
+ | |
(2*(tokenPriceIncremental_)*_tokenPriceInitial*tokenSupply_) | |
) | |
), _tokenPriceInitial | |
) | |
)/(tokenPriceIncremental_) | |
)-(tokenSupply_) | |
; | |
return _tokensReceived; | |
} | |
/** | |
* Calculate token sell value. | |
*/ | |
function tokensToEthereum_(uint256 _tokens) | |
internal | |
view | |
returns(uint256) | |
{ | |
uint256 tokens_ = (_tokens + 1e18); | |
uint256 _tokenSupply = (tokenSupply_ + 1e18); | |
uint256 _etherReceived = | |
( | |
// underflow attempts BTFO | |
SafeMath.sub( | |
( | |
( | |
( | |
tokenPriceInitial_ +(tokenPriceIncremental_ * (_tokenSupply/1e18)) | |
)-tokenPriceIncremental_ | |
)*(tokens_ - 1e18) | |
),(tokenPriceIncremental_*((tokens_**2-tokens_)/1e18))/2 | |
) | |
/1e18); | |
return _etherReceived; | |
} | |
function register(address _sender, address _referredBy) internal { | |
uint256 _id = users[_referredBy].id; | |
basicData memory UserStruct; | |
currentId++; | |
//add users data | |
UserStruct = basicData({ | |
isExist: true, | |
id: currentId, | |
referrerId: _id, | |
referrerAdd: _referredBy | |
}); | |
userList[currentId] = _sender; | |
users[msg.sender] = UserStruct; | |
} | |
function distributeToSponsor(address _address,uint256 _eth) internal { | |
uint256 _sp1 = (_eth.mul(10)).div(100); | |
uint256 _sp2 = (_eth.mul(7)).div(100); | |
uint256 _sp3 = (_eth.mul(3)).div(100); | |
address add1 = _address; | |
address add2 = users[_address].referrerAdd; | |
address add3 = users[add2].referrerAdd; | |
//add amount of ref bonus to referrer | |
referralBalance_[add1] += (_sp1); | |
sponsorsPaid += _sp1; | |
//fire event on distributionToSponsor | |
emit amountDistributedToSponsor(msg.sender, add1,_sp1); | |
//add amount of ref bonus to referrer | |
referralBalance_[add2] += (_sp2); | |
sponsorsPaid += _sp2; | |
//fire event on distributionToSponsor | |
emit amountDistributedToSponsor(msg.sender, add2, _sp2); | |
//add amount of ref bonus to referrer | |
referralBalance_[add3] += (_sp3); | |
sponsorsPaid += _sp3; | |
//fire event on distributionToSponsor | |
emit amountDistributedToSponsor(msg.sender, add3, _sp3); | |
} | |
function sqrt(uint x) internal pure returns (uint y) { | |
uint z = (x + 1) / 2; | |
y = x; | |
while (z < y) { | |
y = z; | |
z = (x / z + z) / 2; | |
} | |
} | |
} | |
/** | |
* @title SafeMath | |
* @dev Math operations with safety checks that throw on error | |
*/ | |
library SafeMath { | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
return sub(a, b, "SafeMath: subtraction overflow"); | |
} | |
function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
require(b <= a, errorMessage); | |
uint c = a - b; | |
return c; | |
} | |
function mul(uint a, uint b) internal pure returns (uint) { | |
if (a == 0) { | |
return 0; | |
} | |
uint c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
return div(a, b, "SafeMath: division by zero"); | |
} | |
function div(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
// Solidity only automatically asserts when dividing by 0 | |
require(b > 0, errorMessage); | |
uint c = a / b; | |
return c; | |
} | |
} |
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
/** | |
*Submitted for verification at Etherscan.io on 2020-07-17 | |
*/ | |
//SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.6.12; | |
interface IERC20 { | |
function totalSupply() external view returns (uint); | |
function balanceOf(address account) external view returns (uint); | |
function transfer(address recipient, uint amount) external returns (bool); | |
function allowance(address owner, address spender) external view returns (uint); | |
function approve(address spender, uint amount) external returns (bool); | |
function transferFrom(address sender, address recipient, uint amount) external returns (bool); | |
event Transfer(address indexed from, address indexed to, uint value); | |
event Approval(address indexed owner, address indexed spender, uint value); | |
} | |
contract Context { | |
constructor () internal { } | |
// solhint-disable-previous-line no-empty-blocks | |
function _msgSender() internal view returns (address payable) { | |
return msg.sender; | |
} | |
} | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint; | |
mapping (address => uint) internal _balances; | |
mapping (address => mapping (address => uint)) internal _allowances; | |
uint internal _totalSupply; | |
function totalSupply() public view override returns (uint) { | |
return _totalSupply; | |
} | |
function balanceOf(address account) public view override returns (uint) { | |
return _balances[account]; | |
} | |
function transfer(address recipient, uint amount) public override returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
function allowance(address owner, address spender) public view override returns (uint) { | |
return _allowances[owner][spender]; | |
} | |
function approve(address spender, uint amount) public override returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
function transferFrom(address sender, address recipient, uint amount) public override returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
function increaseAllowance(address spender, uint addedValue) public returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
function decreaseAllowance(address spender, uint subtractedValue) public returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
function _transfer(address sender, address recipient, uint amount) internal { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
require(recipient != address(0), "ERC20: transfer to the zero address"); | |
uint256 burntAmount = amount * 5 / 100; | |
_burn(sender, burntAmount); | |
uint256 leftAmount = amount - burntAmount; | |
_balances[sender] = _balances[sender].sub(leftAmount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(leftAmount); | |
emit Transfer(sender, recipient,leftAmount); | |
} | |
function _mint(address account, uint amount) internal { | |
require(account != address(0), "ERC20: mint to the zero address"); | |
_totalSupply = _totalSupply.add(amount); | |
_balances[account] = _balances[account].add(amount); | |
emit Transfer(address(0), account, amount); | |
} | |
function _burn(address account, uint amount) internal { | |
require(account != address(0), "ERC20: burn from the zero address"); | |
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); | |
_totalSupply = _totalSupply.sub(amount); | |
emit Transfer(account, address(0), amount); | |
} | |
function _approve(address owner, address spender, uint amount) internal { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
} | |
contract ERC20Detailed is ERC20 { | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
constructor (string memory name, string memory symbol, uint8 decimals) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = decimals; | |
} | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
} | |
library SafeMath { | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
return sub(a, b, "SafeMath: subtraction overflow"); | |
} | |
function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
require(b <= a, errorMessage); | |
uint c = a - b; | |
return c; | |
} | |
function mul(uint a, uint b) internal pure returns (uint) { | |
if (a == 0) { | |
return 0; | |
} | |
uint c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
return div(a, b, "SafeMath: division by zero"); | |
} | |
function div(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
// Solidity only automatically asserts when dividing by 0 | |
require(b > 0, errorMessage); | |
uint c = a / b; | |
return c; | |
} | |
} | |
library Address { | |
function isContract(address account) internal view returns (bool) { | |
bytes32 codehash; | |
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; | |
// solhint-disable-next-line no-inline-assembly | |
assembly { codehash := extcodehash(account) } | |
return (codehash != 0x0 && codehash != accountHash); | |
} | |
} | |
library SafeERC20 { | |
using SafeMath for uint; | |
using Address for address; | |
function safeTransfer(IERC20 token, address to, uint value) internal { | |
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); | |
} | |
function safeTransferFrom(IERC20 token, address from, address to, uint value) internal { | |
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); | |
} | |
function safeApprove(IERC20 token, address spender, uint value) internal { | |
require((value == 0) || (token.allowance(address(this), spender) == 0), | |
"SafeERC20: approve from non-zero to non-zero allowance" | |
); | |
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); | |
} | |
function callOptionalReturn(IERC20 token, bytes memory data) private { | |
require(address(token).isContract(), "SafeERC20: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = address(token).call(data); | |
require(success, "SafeERC20: low-level call failed"); | |
if (returndata.length > 0) { // Return data is optional | |
// solhint-disable-next-line max-line-length | |
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); | |
} | |
} | |
} | |
contract FRNO is ERC20, ERC20Detailed { | |
using SafeERC20 for IERC20; | |
using Address for address; | |
using SafeMath for uint; | |
address public ownership; | |
constructor () public ERC20Detailed("Inferno", "FRNO", 18) { | |
ownership = msg.sender; | |
_totalSupply = 14000 *(10**uint256(18)); | |
_balances[msg.sender] = _totalSupply; | |
} | |
} |
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.21; | |
contract GoGCards { | |
/*================================= | |
= MODIFIERS = | |
=================================*/ | |
modifier onlyOwner(){ | |
require(msg.sender == dev); | |
_; | |
} | |
/*============================== | |
= EVENTS = | |
==============================*/ | |
event onBondPurchase( | |
address customerAddress, | |
uint256 incomingEthereum, | |
uint256 bond, | |
uint256 newPrice | |
); | |
event onWithdraw( | |
address customerAddress, | |
uint256 ethereumWithdrawn | |
); | |
// ERC20 | |
event Transfer( | |
address from, | |
address to, | |
uint256 bond | |
); | |
/*===================================== | |
= CONFIGURABLES = | |
=====================================*/ | |
string public name = "GOG CARDS"; | |
string public symbol = "GOC"; | |
uint8 constant public referralRate = 5; | |
uint8 constant public decimals = 18; | |
uint public totalBondValue = 8e18; | |
/*================================ | |
= DATASETS = | |
================================*/ | |
mapping(uint => address) internal bondOwner; | |
mapping(uint => uint) public bondPrice; | |
mapping(uint => uint) internal bondPreviousPrice; | |
mapping(address => uint) internal ownerAccounts; | |
mapping(uint => uint) internal totalBondDivs; | |
mapping(uint => string) internal bondName; | |
uint bondPriceIncrement = 110; //10% Price Increases | |
uint totalDivsProduced = 0; | |
uint public maxBonds = 200; | |
uint public initialPrice = 1e17; //0.1 ETH | |
uint public nextAvailableBond; | |
bool allowReferral = false; | |
bool allowAutoNewBond = false; | |
uint8 public devDivRate = 5; | |
uint8 public ownerDivRate = 50; | |
uint8 public distDivRate = 45; | |
uint public bondFund = 0; | |
address dev; | |
/*======================================= | |
= PUBLIC FUNCTIONS = | |
=======================================*/ | |
/* | |
* -- APPLICATION ENTRY POINTS -- | |
*/ | |
function BONDS() | |
public | |
{ | |
dev = msg.sender; | |
nextAvailableBond = 11; | |
bondOwner[1] = dev; | |
bondPrice[1] = 2e18;//initialPrice; | |
bondPreviousPrice[1] = 0; | |
bondOwner[2] = dev; | |
bondPrice[2] = 15e17;//initialPrice; | |
bondPreviousPrice[2] = 0; | |
bondOwner[3] = dev; | |
bondPrice[3] = 10e17;//initialPrice; | |
bondPreviousPrice[3] = 0; | |
bondOwner[4] = dev; | |
bondPrice[4] = 9e17;//initialPrice; | |
bondPreviousPrice[4] = 0; | |
bondOwner[5] = dev; | |
bondPrice[5] = 8e17;//initialPrice; | |
bondPreviousPrice[5] = 0; | |
bondOwner[6] = dev; | |
bondPrice[6] = 7e17;//initialPrice; | |
bondPreviousPrice[6] = 0; | |
bondOwner[7] = dev; | |
bondPrice[7] = 5e17;//initialPrice; | |
bondPreviousPrice[7] = 0; | |
bondOwner[8] = dev; | |
bondPrice[8] = 3e17;//initialPrice; | |
bondPreviousPrice[8] = 0; | |
bondOwner[9] = dev; | |
bondPrice[9] = 2e17;//initialPrice; | |
bondPreviousPrice[9] = 0; | |
bondOwner[10] = dev; | |
bondPrice[10] = 1e17;//initialPrice; | |
bondPreviousPrice[10] = 0; | |
} | |
function addTotalBondValue(uint _new, uint _old) | |
internal | |
{ | |
totalBondValue = SafeMath.add(totalBondValue, SafeMath.sub(_new,_old)); | |
} | |
function buy(uint _bond, address _referrer) | |
public | |
payable | |
{ | |
require(_bond <= nextAvailableBond); | |
require(msg.value >= bondPrice[_bond]); | |
require(msg.sender != bondOwner[_bond]); | |
uint _newPrice = SafeMath.div(SafeMath.mul(msg.value,bondPriceIncrement),100); | |
//Determine the total dividends | |
uint _baseDividends = msg.value - bondPreviousPrice[_bond]; | |
totalDivsProduced = SafeMath.add(totalDivsProduced, _baseDividends); | |
uint _devDividends = SafeMath.div(SafeMath.mul(_baseDividends,devDivRate),100); | |
uint _ownerDividends = SafeMath.div(SafeMath.mul(_baseDividends,ownerDivRate),100); | |
totalBondDivs[_bond] = SafeMath.add(totalBondDivs[_bond],_ownerDividends); | |
_ownerDividends = SafeMath.add(_ownerDividends,bondPreviousPrice[_bond]); | |
uint _distDividends = SafeMath.div(SafeMath.mul(_baseDividends,distDivRate),100); | |
if (allowReferral && (_referrer != msg.sender) && (_referrer != 0x0000000000000000000000000000000000000000)) { | |
uint _referralDividends = SafeMath.div(SafeMath.mul(_baseDividends,referralRate),100); | |
_distDividends = SafeMath.sub(_distDividends,_referralDividends); | |
ownerAccounts[_referrer] = SafeMath.add(ownerAccounts[_referrer],_referralDividends); | |
} | |
//distribute dividends to accounts | |
address _previousOwner = bondOwner[_bond]; | |
address _newOwner = msg.sender; | |
ownerAccounts[_previousOwner] = SafeMath.add(ownerAccounts[_previousOwner],_ownerDividends); | |
ownerAccounts[dev] = SafeMath.add(ownerAccounts[dev],_devDividends); | |
bondOwner[_bond] = _newOwner; | |
distributeYield(_distDividends); | |
distributeBondFund(); | |
//Increment the bond Price | |
bondPreviousPrice[_bond] = msg.value; | |
bondPrice[_bond] = _newPrice; | |
addTotalBondValue(_newPrice, bondPreviousPrice[_bond]); | |
emit onBondPurchase(msg.sender, msg.value, _bond, SafeMath.div(SafeMath.mul(msg.value,bondPriceIncrement),100)); | |
} | |
function distributeYield(uint _distDividends) internal | |
{ | |
uint counter = 1; | |
while (counter < nextAvailableBond) { | |
uint _distAmountLocal = SafeMath.div(SafeMath.mul(_distDividends, bondPrice[counter]),totalBondValue); | |
ownerAccounts[bondOwner[counter]] = SafeMath.add(ownerAccounts[bondOwner[counter]],_distAmountLocal); | |
totalBondDivs[counter] = SafeMath.add(totalBondDivs[counter],_distAmountLocal); | |
counter = counter + 1; | |
} | |
} | |
function distributeBondFund() internal | |
{ | |
if(bondFund > 0){ | |
uint counter = 1; | |
while (counter < nextAvailableBond) { | |
uint _distAmountLocal = SafeMath.div(SafeMath.mul(bondFund, bondPrice[counter]),totalBondValue); | |
ownerAccounts[bondOwner[counter]] = SafeMath.add(ownerAccounts[bondOwner[counter]],_distAmountLocal); | |
totalBondDivs[counter] = SafeMath.add(totalBondDivs[counter],_distAmountLocal); | |
counter = counter + 1; | |
} | |
bondFund = 0; | |
} | |
} | |
function extDistributeBondFund() public | |
onlyOwner() | |
{ | |
if(bondFund > 0){ | |
uint counter = 1; | |
while (counter < nextAvailableBond) { | |
uint _distAmountLocal = SafeMath.div(SafeMath.mul(bondFund, bondPrice[counter]),totalBondValue); | |
ownerAccounts[bondOwner[counter]] = SafeMath.add(ownerAccounts[bondOwner[counter]],_distAmountLocal); | |
totalBondDivs[counter] = SafeMath.add(totalBondDivs[counter],_distAmountLocal); | |
counter = counter + 1; | |
} | |
bondFund = 0; | |
} | |
} | |
function withdraw() | |
public | |
{ | |
address _customerAddress = msg.sender; | |
require(ownerAccounts[_customerAddress] > 0); | |
uint _dividends = ownerAccounts[_customerAddress]; | |
ownerAccounts[_customerAddress] = 0; | |
_customerAddress.transfer(_dividends); | |
// fire event | |
onWithdraw(_customerAddress, _dividends); | |
} | |
function withdrawPart(uint _amount) | |
public | |
onlyOwner() | |
{ | |
address _customerAddress = msg.sender; | |
require(ownerAccounts[_customerAddress] > 0); | |
require(_amount <= ownerAccounts[_customerAddress]); | |
ownerAccounts[_customerAddress] = SafeMath.sub(ownerAccounts[_customerAddress],_amount); | |
_customerAddress.transfer(_amount); | |
// fire event | |
onWithdraw(_customerAddress, _amount); | |
} | |
// Fallback function: add funds to the addional distibution amount. This is what will be contributed from the exchange | |
// and other contracts | |
function() | |
payable | |
public | |
{ | |
uint devAmount = SafeMath.div(SafeMath.mul(devDivRate,msg.value),100); | |
uint bondAmount = msg.value - devAmount; | |
bondFund = SafeMath.add(bondFund, bondAmount); | |
ownerAccounts[dev] = SafeMath.add(ownerAccounts[dev], devAmount); | |
} | |
/** | |
* Transfer bond to another address | |
*/ | |
function transfer(address _to, uint _bond ) | |
public | |
{ | |
require(bondOwner[_bond] == msg.sender); | |
bondOwner[_bond] = _to; | |
emit Transfer(msg.sender, _to, _bond); | |
} | |
/** | |
/** | |
* If we want to rebrand, we can. | |
*/ | |
function setName(string _name) | |
onlyOwner() | |
public | |
{ | |
name = _name; | |
} | |
/** | |
* If we want to rebrand, we can. | |
*/ | |
function setSymbol(string _symbol) | |
onlyOwner() | |
public | |
{ | |
symbol = _symbol; | |
} | |
function setInitialPrice(uint _price) | |
onlyOwner() | |
public | |
{ | |
initialPrice = _price; | |
} | |
function setMaxbonds(uint _bond) | |
onlyOwner() | |
public | |
{ | |
maxBonds = _bond; | |
} | |
function setBondPrice(uint _bond, uint _price) | |
onlyOwner() | |
public | |
{ | |
require(bondOwner[_bond] == dev); | |
bondPrice[_bond] = _price; | |
} | |
function addNewbond(uint _price) | |
onlyOwner() | |
public | |
{ | |
require(nextAvailableBond < maxBonds); | |
bondPrice[nextAvailableBond] = _price; | |
bondOwner[nextAvailableBond] = dev; | |
totalBondDivs[nextAvailableBond] = 0; | |
bondPreviousPrice[nextAvailableBond] = 0; | |
nextAvailableBond = nextAvailableBond + 1; | |
addTotalBondValue(_price, 0); | |
} | |
function setAllowReferral(bool _allowReferral) | |
onlyOwner() | |
public | |
{ | |
allowReferral = _allowReferral; | |
} | |
function setAutoNewbond(bool _autoNewBond) | |
onlyOwner() | |
public | |
{ | |
allowAutoNewBond = _autoNewBond; | |
} | |
function setRates(uint8 _newDistRate, uint8 _newDevRate, uint8 _newOwnerRate) | |
onlyOwner() | |
public | |
{ | |
require((_newDistRate + _newDevRate + _newOwnerRate) == 100); | |
devDivRate = _newDevRate; | |
ownerDivRate = _newOwnerRate; | |
distDivRate = _newDistRate; | |
} | |
function setLowerBondPrice(uint _bond, uint _newPrice) | |
{ | |
require(bondOwner[_bond] == msg.sender); | |
require(_newPrice < bondPrice[_bond]); | |
require(_newPrice >= initialPrice); | |
totalBondValue = SafeMath.sub(totalBondValue,SafeMath.sub(bondPrice[_bond],_newPrice)); | |
bondPrice[_bond] = _newPrice; | |
} | |
/*---------- HELPERS AND CALCULATORS ----------*/ | |
/** | |
* Method to view the current Ethereum stored in the contract | |
* Example: totalEthereumBalance() | |
*/ | |
function getMyBalance() | |
public | |
view | |
returns(uint) | |
{ | |
return ownerAccounts[msg.sender]; | |
} | |
function getOwnerBalance(address _bondOwner) | |
public | |
view | |
returns(uint) | |
{ | |
require(msg.sender == dev); | |
return ownerAccounts[_bondOwner]; | |
} | |
function getBondPrice(uint _bond) | |
public | |
view | |
returns(uint) | |
{ | |
require(_bond <= nextAvailableBond); | |
return bondPrice[_bond]; | |
} | |
function getBondOwner(uint _bond) | |
public | |
view | |
returns(address) | |
{ | |
require(_bond <= nextAvailableBond); | |
return bondOwner[_bond]; | |
} | |
function gettotalBondDivs(uint _bond) | |
public | |
view | |
returns(uint) | |
{ | |
require(_bond <= nextAvailableBond); | |
return totalBondDivs[_bond]; | |
} | |
function getTotalDivsProduced() | |
public | |
view | |
returns(uint) | |
{ | |
return totalDivsProduced; | |
} | |
function getTotalBondValue() | |
public | |
view | |
returns(uint) | |
{ | |
return totalBondValue; | |
} | |
function totalEthereumBalance() | |
public | |
view | |
returns(uint) | |
{ | |
return address (this).balance; | |
} | |
function getNextAvailableBond() | |
public | |
view | |
returns(uint) | |
{ | |
return nextAvailableBond; | |
} | |
} | |
/** | |
* @title SafeMath | |
* @dev Math operations with safety checks that throw on error | |
*/ | |
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; | |
} | |
} |
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.6.0; | |
// import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol'; | |
// import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721Burnable.sol'; | |
abstract contract Context { | |
function _msgSender() internal view virtual returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view virtual returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
interface IERC165 { | |
/** | |
* @dev Returns true if this contract implements the interface defined by | |
* `interfaceId`. See the corresponding | |
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] | |
* to learn more about how these ids are created. | |
* | |
* This function call must use less than 30 000 gas. | |
*/ | |
function supportsInterface(bytes4 interfaceId) external view returns (bool); | |
} | |
contract ERC165 is IERC165 { | |
/* | |
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 | |
*/ | |
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; | |
/** | |
* @dev Mapping of interface ids to whether or not it's supported. | |
*/ | |
mapping(bytes4 => bool) private _supportedInterfaces; | |
constructor () internal { | |
// Derived contracts need only register support for their own interfaces, | |
// we register support for ERC165 itself here | |
_registerInterface(_INTERFACE_ID_ERC165); | |
} | |
/** | |
* @dev See {IERC165-supportsInterface}. | |
* | |
* Time complexity O(1), guaranteed to always use less than 30 000 gas. | |
*/ | |
function supportsInterface(bytes4 interfaceId) public view override returns (bool) { | |
return _supportedInterfaces[interfaceId]; | |
} | |
/** | |
* @dev Registers the contract as an implementer of the interface defined by | |
* `interfaceId`. Support of the actual ERC165 interface is automatic and | |
* registering its interface id is not required. | |
* | |
* See {IERC165-supportsInterface}. | |
* | |
* Requirements: | |
* | |
* - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). | |
*/ | |
function _registerInterface(bytes4 interfaceId) internal virtual { | |
require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); | |
_supportedInterfaces[interfaceId] = true; | |
} | |
} | |
interface IERC721 is IERC165 { | |
/** | |
* @dev Emitted when `tokenId` token is transferred from `from` to `to`. | |
*/ | |
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); | |
/** | |
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. | |
*/ | |
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); | |
/** | |
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. | |
*/ | |
event ApprovalForAll(address indexed owner, address indexed operator, bool approved); | |
/** | |
* @dev Returns the number of tokens in ``owner``'s account. | |
*/ | |
function balanceOf(address owner) external view returns (uint256 balance); | |
/** | |
* @dev Returns the owner of the `tokenId` token. | |
* | |
* Requirements: | |
* | |
* - `tokenId` must exist. | |
*/ | |
function ownerOf(uint256 tokenId) external view returns (address owner); | |
/** | |
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients | |
* are aware of the ERC721 protocol to prevent tokens from being forever locked. | |
* | |
* Requirements: | |
* | |
* - `from` cannot be the zero address. | |
* - `to` cannot be the zero address. | |
* - `tokenId` token must exist and be owned by `from`. | |
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. | |
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. | |
* | |
* Emits a {Transfer} event. | |
*/ | |
function safeTransferFrom(address from, address to, uint256 tokenId) external; | |
/** | |
* @dev Transfers `tokenId` token from `from` to `to`. | |
* | |
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. | |
* | |
* Requirements: | |
* | |
* - `from` cannot be the zero address. | |
* - `to` cannot be the zero address. | |
* - `tokenId` token must be owned by `from`. | |
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. | |
* | |
* Emits a {Transfer} event. | |
*/ | |
function transferFrom(address from, address to, uint256 tokenId) external; | |
/** | |
* @dev Gives permission to `to` to transfer `tokenId` token to another account. | |
* The approval is cleared when the token is transferred. | |
* | |
* Only a single account can be approved at a time, so approving the zero address clears previous approvals. | |
* | |
* Requirements: | |
* | |
* - The caller must own the token or be an approved operator. | |
* - `tokenId` must exist. | |
* | |
* Emits an {Approval} event. | |
*/ | |
function approve(address to, uint256 tokenId) external; | |
/** | |
* @dev Returns the account approved for `tokenId` token. | |
* | |
* Requirements: | |
* | |
* - `tokenId` must exist. | |
*/ | |
function getApproved(uint256 tokenId) external view returns (address operator); | |
/** | |
* @dev Approve or remove `operator` as an operator for the caller. | |
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. | |
* | |
* Requirements: | |
* | |
* - The `operator` cannot be the caller. | |
* | |
* Emits an {ApprovalForAll} event. | |
*/ | |
function setApprovalForAll(address operator, bool _approved) external; | |
/** | |
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. | |
* | |
* See {setApprovalForAll} | |
*/ | |
function isApprovedForAll(address owner, address operator) external view returns (bool); | |
/** | |
* @dev Safely transfers `tokenId` token from `from` to `to`. | |
* | |
* Requirements: | |
* | |
* - `from` cannot be the zero address. | |
* - `to` cannot be the zero address. | |
* - `tokenId` token must exist and be owned by `from`. | |
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. | |
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. | |
* | |
* Emits a {Transfer} event. | |
*/ | |
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; | |
} | |
interface IERC721Enumerable is IERC721 { | |
/** | |
* @dev Returns the total amount of tokens stored by the contract. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns a token ID owned by `owner` at a given `index` of its token list. | |
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens. | |
*/ | |
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); | |
/** | |
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract. | |
* Use along with {totalSupply} to enumerate all tokens. | |
*/ | |
function tokenByIndex(uint256 index) external view returns (uint256); | |
} | |
interface IERC721Metadata is IERC721 { | |
/** | |
* @dev Returns the token collection name. | |
*/ | |
function name() external view returns (string memory); | |
/** | |
* @dev Returns the token collection symbol. | |
*/ | |
function symbol() external view returns (string memory); | |
/** | |
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. | |
*/ | |
function tokenURI(uint256 tokenId) external view returns (string memory); | |
} | |
interface IERC721Receiver { | |
/** | |
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} | |
* by `operator` from `from`, this function is called. | |
* | |
* It must return its Solidity selector to confirm the token transfer. | |
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. | |
* | |
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. | |
*/ | |
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) | |
external returns (bytes4); | |
} | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
library Address { | |
/** | |
* @dev Returns true if `account` is a contract. | |
* | |
* [IMPORTANT] | |
* ==== | |
* It is unsafe to assume that an address for which this function returns | |
* false is an externally-owned account (EOA) and not a contract. | |
* | |
* Among others, `isContract` will return false for the following | |
* types of addresses: | |
* | |
* - an externally-owned account | |
* - a contract in construction | |
* - an address where a contract will be created | |
* - an address where a contract lived, but was destroyed | |
* ==== | |
*/ | |
function isContract(address account) internal 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; | |
} | |
/** | |
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to | |
* `recipient`, forwarding all available gas and reverting on errors. | |
* | |
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost | |
* of certain opcodes, possibly making contracts go over the 2300 gas limit | |
* imposed by `transfer`, making them unable to receive funds via | |
* `transfer`. {sendValue} removes this limitation. | |
* | |
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. | |
* | |
* IMPORTANT: because control is transferred to `recipient`, care must be | |
* taken to not create reentrancy vulnerabilities. Consider using | |
* {ReentrancyGuard} or the | |
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. | |
*/ | |
function sendValue(address payable recipient, uint256 amount) internal { | |
require(address(this).balance >= amount, "Address: insufficient balance"); | |
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value | |
(bool success, ) = recipient.call{ value: amount }(""); | |
require(success, "Address: unable to send value, recipient may have reverted"); | |
} | |
/** | |
* @dev Performs a Solidity function call using a low level `call`. A | |
* plain`call` is an unsafe replacement for a function call: use this | |
* function instead. | |
* | |
* If `target` reverts with a revert reason, it is bubbled up by this | |
* function (like regular Solidity function calls). | |
* | |
* Returns the raw returned data. To convert to the expected return value, | |
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. | |
* | |
* Requirements: | |
* | |
* - `target` must be a contract. | |
* - calling `target` with `data` must not revert. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
return functionCall(target, data, "Address: low-level call failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with | |
* `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
return _functionCallWithValue(target, data, 0, errorMessage); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], | |
* but also transferring `value` wei to `target`. | |
* | |
* Requirements: | |
* | |
* - the calling contract must have an ETH balance of at least `value`. | |
* - the called Solidity function must be `payable`. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { | |
return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but | |
* with `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { | |
require(address(this).balance >= value, "Address: insufficient balance for call"); | |
return _functionCallWithValue(target, data, value, errorMessage); | |
} | |
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { | |
require(isContract(target), "Address: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data); | |
if (success) { | |
return returndata; | |
} else { | |
// Look for revert reason and bubble it up if present | |
if (returndata.length > 0) { | |
// The easiest way to bubble the revert reason is using memory via assembly | |
// solhint-disable-next-line no-inline-assembly | |
assembly { | |
let returndata_size := mload(returndata) | |
revert(add(32, returndata), returndata_size) | |
} | |
} else { | |
revert(errorMessage); | |
} | |
} | |
} | |
} | |
library Strings { | |
/** | |
* @dev Converts a `uint256` to its ASCII `string` representation. | |
*/ | |
function toString(uint256 value) internal pure returns (string memory) { | |
// Inspired by OraclizeAPI's implementation - MIT licence | |
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol | |
if (value == 0) { | |
return "0"; | |
} | |
uint256 temp = value; | |
uint256 digits; | |
while (temp != 0) { | |
digits++; | |
temp /= 10; | |
} | |
bytes memory buffer = new bytes(digits); | |
uint256 index = digits - 1; | |
temp = value; | |
while (temp != 0) { | |
buffer[index--] = byte(uint8(48 + temp % 10)); | |
temp /= 10; | |
} | |
return string(buffer); | |
} | |
} | |
library EnumerableMap { | |
// To implement this library for multiple types with as little code | |
// repetition as possible, we write it in terms of a generic Map type with | |
// bytes32 keys and values. | |
// The Map implementation uses private functions, and user-facing | |
// implementations (such as Uint256ToAddressMap) are just wrappers around | |
// the underlying Map. | |
// This means that we can only create new EnumerableMaps for types that fit | |
// in bytes32. | |
struct MapEntry { | |
bytes32 _key; | |
bytes32 _value; | |
} | |
struct Map { | |
// Storage of map keys and values | |
MapEntry[] _entries; | |
// Position of the entry defined by a key in the `entries` array, plus 1 | |
// because index 0 means a key is not in the map. | |
mapping (bytes32 => uint256) _indexes; | |
} | |
/** | |
* @dev Adds a key-value pair to a map, or updates the value for an existing | |
* key. O(1). | |
* | |
* Returns true if the key was added to the map, that is if it was not | |
* already present. | |
*/ | |
function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) { | |
// We read and store the key's index to prevent multiple reads from the same storage slot | |
uint256 keyIndex = map._indexes[key]; | |
if (keyIndex == 0) { // Equivalent to !contains(map, key) | |
map._entries.push(MapEntry({ _key: key, _value: value })); | |
// The entry is stored at length-1, but we add 1 to all indexes | |
// and use 0 as a sentinel value | |
map._indexes[key] = map._entries.length; | |
return true; | |
} else { | |
map._entries[keyIndex - 1]._value = value; | |
return false; | |
} | |
} | |
/** | |
* @dev Removes a key-value pair from a map. O(1). | |
* | |
* Returns true if the key was removed from the map, that is if it was present. | |
*/ | |
function _remove(Map storage map, bytes32 key) private returns (bool) { | |
// We read and store the key's index to prevent multiple reads from the same storage slot | |
uint256 keyIndex = map._indexes[key]; | |
if (keyIndex != 0) { // Equivalent to contains(map, key) | |
// To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one | |
// in the array, and then remove the last entry (sometimes called as 'swap and pop'). | |
// This modifies the order of the array, as noted in {at}. | |
uint256 toDeleteIndex = keyIndex - 1; | |
uint256 lastIndex = map._entries.length - 1; | |
// When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs | |
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. | |
MapEntry storage lastEntry = map._entries[lastIndex]; | |
// Move the last entry to the index where the entry to delete is | |
map._entries[toDeleteIndex] = lastEntry; | |
// Update the index for the moved entry | |
map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based | |
// Delete the slot where the moved entry was stored | |
map._entries.pop(); | |
// Delete the index for the deleted slot | |
delete map._indexes[key]; | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* @dev Returns true if the key is in the map. O(1). | |
*/ | |
function _contains(Map storage map, bytes32 key) private view returns (bool) { | |
return map._indexes[key] != 0; | |
} | |
/** | |
* @dev Returns the number of key-value pairs in the map. O(1). | |
*/ | |
function _length(Map storage map) private view returns (uint256) { | |
return map._entries.length; | |
} | |
/** | |
* @dev Returns the key-value pair stored at position `index` in the map. O(1). | |
* | |
* Note that there are no guarantees on the ordering of entries inside the | |
* array, and it may change when more entries are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) { | |
require(map._entries.length > index, "EnumerableMap: index out of bounds"); | |
MapEntry storage entry = map._entries[index]; | |
return (entry._key, entry._value); | |
} | |
/** | |
* @dev Returns the value associated with `key`. O(1). | |
* | |
* Requirements: | |
* | |
* - `key` must be in the map. | |
*/ | |
function _get(Map storage map, bytes32 key) private view returns (bytes32) { | |
return _get(map, key, "EnumerableMap: nonexistent key"); | |
} | |
/** | |
* @dev Same as {_get}, with a custom error message when `key` is not in the map. | |
*/ | |
function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) { | |
uint256 keyIndex = map._indexes[key]; | |
require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key) | |
return map._entries[keyIndex - 1]._value; // All indexes are 1-based | |
} | |
// UintToAddressMap | |
struct UintToAddressMap { | |
Map _inner; | |
} | |
/** | |
* @dev Adds a key-value pair to a map, or updates the value for an existing | |
* key. O(1). | |
* | |
* Returns true if the key was added to the map, that is if it was not | |
* already present. | |
*/ | |
function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) { | |
return _set(map._inner, bytes32(key), bytes32(uint256(value))); | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the key was removed from the map, that is if it was present. | |
*/ | |
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { | |
return _remove(map._inner, bytes32(key)); | |
} | |
/** | |
* @dev Returns true if the key is in the map. O(1). | |
*/ | |
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { | |
return _contains(map._inner, bytes32(key)); | |
} | |
/** | |
* @dev Returns the number of elements in the map. O(1). | |
*/ | |
function length(UintToAddressMap storage map) internal view returns (uint256) { | |
return _length(map._inner); | |
} | |
/** | |
* @dev Returns the element stored at position `index` in the set. O(1). | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { | |
(bytes32 key, bytes32 value) = _at(map._inner, index); | |
return (uint256(key), address(uint256(value))); | |
} | |
/** | |
* @dev Returns the value associated with `key`. O(1). | |
* | |
* Requirements: | |
* | |
* - `key` must be in the map. | |
*/ | |
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { | |
return address(uint256(_get(map._inner, bytes32(key)))); | |
} | |
/** | |
* @dev Same as {get}, with a custom error message when `key` is not in the map. | |
*/ | |
function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) { | |
return address(uint256(_get(map._inner, bytes32(key), errorMessage))); | |
} | |
} | |
library EnumerableSet { | |
// To implement this library for multiple types with as little code | |
// repetition as possible, we write it in terms of a generic Set type with | |
// bytes32 values. | |
// The Set implementation uses private functions, and user-facing | |
// implementations (such as AddressSet) are just wrappers around the | |
// underlying Set. | |
// This means that we can only create new EnumerableSets for types that fit | |
// in bytes32. | |
struct Set { | |
// Storage of set values | |
bytes32[] _values; | |
// Position of the value in the `values` array, plus 1 because index 0 | |
// means a value is not in the set. | |
mapping (bytes32 => uint256) _indexes; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function _add(Set storage set, bytes32 value) private returns (bool) { | |
if (!_contains(set, value)) { | |
set._values.push(value); | |
// The value is stored at length-1, but we add 1 to all indexes | |
// and use 0 as a sentinel value | |
set._indexes[value] = set._values.length; | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function _remove(Set storage set, bytes32 value) private returns (bool) { | |
// We read and store the value's index to prevent multiple reads from the same storage slot | |
uint256 valueIndex = set._indexes[value]; | |
if (valueIndex != 0) { // Equivalent to contains(set, value) | |
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in | |
// the array, and then remove the last element (sometimes called as 'swap and pop'). | |
// This modifies the order of the array, as noted in {at}. | |
uint256 toDeleteIndex = valueIndex - 1; | |
uint256 lastIndex = set._values.length - 1; | |
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs | |
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. | |
bytes32 lastvalue = set._values[lastIndex]; | |
// Move the last value to the index where the value to delete is | |
set._values[toDeleteIndex] = lastvalue; | |
// Update the index for the moved value | |
set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based | |
// Delete the slot where the moved value was stored | |
set._values.pop(); | |
// Delete the index for the deleted slot | |
delete set._indexes[value]; | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function _contains(Set storage set, bytes32 value) private view returns (bool) { | |
return set._indexes[value] != 0; | |
} | |
/** | |
* @dev Returns the number of values on the set. O(1). | |
*/ | |
function _length(Set storage set) private view returns (uint256) { | |
return set._values.length; | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function _at(Set storage set, uint256 index) private view returns (bytes32) { | |
require(set._values.length > index, "EnumerableSet: index out of bounds"); | |
return set._values[index]; | |
} | |
// AddressSet | |
struct AddressSet { | |
Set _inner; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function add(AddressSet storage set, address value) internal returns (bool) { | |
return _add(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function remove(AddressSet storage set, address value) internal returns (bool) { | |
return _remove(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function contains(AddressSet storage set, address value) internal view returns (bool) { | |
return _contains(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Returns the number of values in the set. O(1). | |
*/ | |
function length(AddressSet storage set) internal view returns (uint256) { | |
return _length(set._inner); | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function at(AddressSet storage set, uint256 index) internal view returns (address) { | |
return address(uint256(_at(set._inner, index))); | |
} | |
// UintSet | |
struct UintSet { | |
Set _inner; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function add(UintSet storage set, uint256 value) internal returns (bool) { | |
return _add(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function remove(UintSet storage set, uint256 value) internal returns (bool) { | |
return _remove(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function contains(UintSet storage set, uint256 value) internal view returns (bool) { | |
return _contains(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Returns the number of values on the set. O(1). | |
*/ | |
function length(UintSet storage set) internal view returns (uint256) { | |
return _length(set._inner); | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function at(UintSet storage set, uint256 index) internal view returns (uint256) { | |
return uint256(_at(set._inner, index)); | |
} | |
} | |
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable { | |
using SafeMath for uint256; | |
using Address for address; | |
using EnumerableSet for EnumerableSet.UintSet; | |
using EnumerableMap for EnumerableMap.UintToAddressMap; | |
using Strings for uint256; | |
// Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` | |
// which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` | |
bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; | |
// Mapping from holder address to their (enumerable) set of owned tokens | |
mapping (address => EnumerableSet.UintSet) private _holderTokens; | |
// Enumerable mapping from token ids to their owners | |
EnumerableMap.UintToAddressMap private _tokenOwners; | |
// Mapping from token ID to approved address | |
mapping (uint256 => address) private _tokenApprovals; | |
// Mapping from owner to operator approvals | |
mapping (address => mapping (address => bool)) private _operatorApprovals; | |
// Token name | |
string private _name; | |
// Token symbol | |
string private _symbol; | |
// Optional mapping for token URIs | |
mapping (uint256 => string) private _tokenURIs; | |
// Base URI | |
string private _baseURI; | |
/* | |
* bytes4(keccak256('balanceOf(address)')) == 0x70a08231 | |
* bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e | |
* bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3 | |
* bytes4(keccak256('getApproved(uint256)')) == 0x081812fc | |
* bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465 | |
* bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5 | |
* bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd | |
* bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e | |
* bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde | |
* | |
* => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^ | |
* 0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd | |
*/ | |
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; | |
/* | |
* bytes4(keccak256('name()')) == 0x06fdde03 | |
* bytes4(keccak256('symbol()')) == 0x95d89b41 | |
* bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd | |
* | |
* => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f | |
*/ | |
bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f; | |
/* | |
* bytes4(keccak256('totalSupply()')) == 0x18160ddd | |
* bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59 | |
* bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7 | |
* | |
* => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63 | |
*/ | |
bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63; | |
/** | |
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. | |
*/ | |
constructor (string memory name, string memory symbol) public { | |
_name = name; | |
_symbol = symbol; | |
// register the supported interfaces to conform to ERC721 via ERC165 | |
_registerInterface(_INTERFACE_ID_ERC721); | |
_registerInterface(_INTERFACE_ID_ERC721_METADATA); | |
_registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE); | |
} | |
/** | |
* @dev See {IERC721-balanceOf}. | |
*/ | |
function balanceOf(address owner) public view override returns (uint256) { | |
require(owner != address(0), "ERC721: balance query for the zero address"); | |
return _holderTokens[owner].length(); | |
} | |
/** | |
* @dev See {IERC721-ownerOf}. | |
*/ | |
function ownerOf(uint256 tokenId) public view override returns (address) { | |
return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token"); | |
} | |
/** | |
* @dev See {IERC721Metadata-name}. | |
*/ | |
function name() public view override returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev See {IERC721Metadata-symbol}. | |
*/ | |
function symbol() public view override returns (string memory) { | |
return _symbol; | |
} | |
/** | |
* @dev See {IERC721Metadata-tokenURI}. | |
*/ | |
function tokenURI(uint256 tokenId) public view override returns (string memory) { | |
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); | |
string memory _tokenURI = _tokenURIs[tokenId]; | |
// If there is no base URI, return the token URI. | |
if (bytes(_baseURI).length == 0) { | |
return _tokenURI; | |
} | |
// If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked). | |
if (bytes(_tokenURI).length > 0) { | |
return string(abi.encodePacked(_baseURI, _tokenURI)); | |
} | |
// If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI. | |
return string(abi.encodePacked(_baseURI, tokenId.toString())); | |
} | |
/** | |
* @dev Returns the base URI set via {_setBaseURI}. This will be | |
* automatically added as a prefix in {tokenURI} to each token's URI, or | |
* to the token ID if no specific URI is set for that token ID. | |
*/ | |
function baseURI() public view returns (string memory) { | |
return _baseURI; | |
} | |
/** | |
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. | |
*/ | |
function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) { | |
return _holderTokens[owner].at(index); | |
} | |
/** | |
* @dev See {IERC721Enumerable-totalSupply}. | |
*/ | |
function totalSupply() public view override returns (uint256) { | |
// _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds | |
return _tokenOwners.length(); | |
} | |
/** | |
* @dev See {IERC721Enumerable-tokenByIndex}. | |
*/ | |
function tokenByIndex(uint256 index) public view override returns (uint256) { | |
(uint256 tokenId, ) = _tokenOwners.at(index); | |
return tokenId; | |
} | |
/** | |
* @dev See {IERC721-approve}. | |
*/ | |
function approve(address to, uint256 tokenId) public virtual override { | |
address owner = ownerOf(tokenId); | |
require(to != owner, "ERC721: approval to current owner"); | |
require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()), | |
"ERC721: approve caller is not owner nor approved for all" | |
); | |
_approve(to, tokenId); | |
} | |
/** | |
* @dev See {IERC721-getApproved}. | |
*/ | |
function getApproved(uint256 tokenId) public view override returns (address) { | |
require(_exists(tokenId), "ERC721: approved query for nonexistent token"); | |
return _tokenApprovals[tokenId]; | |
} | |
/** | |
* @dev See {IERC721-setApprovalForAll}. | |
*/ | |
function setApprovalForAll(address operator, bool approved) public virtual override { | |
require(operator != _msgSender(), "ERC721: approve to caller"); | |
_operatorApprovals[_msgSender()][operator] = approved; | |
emit ApprovalForAll(_msgSender(), operator, approved); | |
} | |
/** | |
* @dev See {IERC721-isApprovedForAll}. | |
*/ | |
function isApprovedForAll(address owner, address operator) public view override returns (bool) { | |
return _operatorApprovals[owner][operator]; | |
} | |
/** | |
* @dev See {IERC721-transferFrom}. | |
*/ | |
function transferFrom(address from, address to, uint256 tokenId) public virtual override { | |
//solhint-disable-next-line max-line-length | |
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); | |
_transfer(from, to, tokenId); | |
} | |
/** | |
* @dev See {IERC721-safeTransferFrom}. | |
*/ | |
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { | |
safeTransferFrom(from, to, tokenId, ""); | |
} | |
/** | |
* @dev See {IERC721-safeTransferFrom}. | |
*/ | |
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override { | |
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); | |
_safeTransfer(from, to, tokenId, _data); | |
} | |
/** | |
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients | |
* are aware of the ERC721 protocol to prevent tokens from being forever locked. | |
* | |
* `_data` is additional data, it has no specified format and it is sent in call to `to`. | |
* | |
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. | |
* implement alternative mechanisms to perform token transfer, such as signature-based. | |
* | |
* Requirements: | |
* | |
* - `from` cannot be the zero address. | |
* - `to` cannot be the zero address. | |
* - `tokenId` token must exist and be owned by `from`. | |
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. | |
* | |
* Emits a {Transfer} event. | |
*/ | |
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual { | |
_transfer(from, to, tokenId); | |
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); | |
} | |
/** | |
* @dev Returns whether `tokenId` exists. | |
* | |
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. | |
* | |
* Tokens start existing when they are minted (`_mint`), | |
* and stop existing when they are burned (`_burn`). | |
*/ | |
function _exists(uint256 tokenId) internal view returns (bool) { | |
return _tokenOwners.contains(tokenId); | |
} | |
/** | |
* @dev Returns whether `spender` is allowed to manage `tokenId`. | |
* | |
* Requirements: | |
* | |
* - `tokenId` must exist. | |
*/ | |
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) { | |
require(_exists(tokenId), "ERC721: operator query for nonexistent token"); | |
address owner = ownerOf(tokenId); | |
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); | |
} | |
/** | |
* @dev Safely mints `tokenId` and transfers it to `to`. | |
* | |
* Requirements: | |
d* | |
* - `tokenId` must not exist. | |
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. | |
* | |
* Emits a {Transfer} event. | |
*/ | |
function _safeMint(address to, uint256 tokenId) internal virtual { | |
_safeMint(to, tokenId, ""); | |
} | |
/** | |
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is | |
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients. | |
*/ | |
function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual { | |
_mint(to, tokenId); | |
require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); | |
} | |
/** | |
* @dev Mints `tokenId` and transfers it to `to`. | |
* | |
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible | |
* | |
* Requirements: | |
* | |
* - `tokenId` must not exist. | |
* - `to` cannot be the zero address. | |
* | |
* Emits a {Transfer} event. | |
*/ | |
function _mint(address to, uint256 tokenId) internal virtual { | |
require(to != address(0), "ERC721: mint to the zero address"); | |
require(!_exists(tokenId), "ERC721: token already minted"); | |
_beforeTokenTransfer(address(0), to, tokenId); | |
_holderTokens[to].add(tokenId); | |
_tokenOwners.set(tokenId, to); | |
emit Transfer(address(0), to, tokenId); | |
} | |
/** | |
* @dev Destroys `tokenId`. | |
* The approval is cleared when the token is burned. | |
* | |
* Requirements: | |
* | |
* - `tokenId` must exist. | |
* | |
* Emits a {Transfer} event. | |
*/ | |
function _burn(uint256 tokenId) internal virtual { | |
address owner = ownerOf(tokenId); | |
_beforeTokenTransfer(owner, address(0), tokenId); | |
// Clear approvals | |
_approve(address(0), tokenId); | |
// Clear metadata (if any) | |
if (bytes(_tokenURIs[tokenId]).length != 0) { | |
delete _tokenURIs[tokenId]; | |
} | |
_holderTokens[owner].remove(tokenId); | |
_tokenOwners.remove(tokenId); | |
emit Transfer(owner, address(0), tokenId); | |
} | |
/** | |
* @dev Transfers `tokenId` from `from` to `to`. | |
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender. | |
* | |
* Requirements: | |
* | |
* - `to` cannot be the zero address. | |
* - `tokenId` token must be owned by `from`. | |
* | |
* Emits a {Transfer} event. | |
*/ | |
function _transfer(address from, address to, uint256 tokenId) internal virtual { | |
require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); | |
require(to != address(0), "ERC721: transfer to the zero address"); | |
_beforeTokenTransfer(from, to, tokenId); | |
// Clear approvals from the previous owner | |
_approve(address(0), tokenId); | |
_holderTokens[from].remove(tokenId); | |
_holderTokens[to].add(tokenId); | |
_tokenOwners.set(tokenId, to); | |
emit Transfer(from, to, tokenId); | |
} | |
/** | |
* @dev Sets `_tokenURI` as the tokenURI of `tokenId`. | |
* | |
* Requirements: | |
* | |
* - `tokenId` must exist. | |
*/ | |
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual { | |
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token"); | |
_tokenURIs[tokenId] = _tokenURI; | |
} | |
/** | |
* @dev Internal function to set the base URI for all token IDs. It is | |
* automatically added as a prefix to the value returned in {tokenURI}, | |
* or to the token ID if {tokenURI} is empty. | |
*/ | |
function _setBaseURI(string memory baseURI_) internal virtual { | |
_baseURI = baseURI_; | |
} | |
/** | |
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. | |
* The call is not executed if the target address is not a contract. | |
* | |
* @param from address representing the previous owner of the given token ID | |
* @param to target address that will receive the tokens | |
* @param tokenId uint256 ID of the token to be transferred | |
* @param _data bytes optional data to send along with the call | |
* @return bool whether the call correctly returned the expected magic value | |
*/ | |
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) | |
private returns (bool) | |
{ | |
if (!to.isContract()) { | |
return true; | |
} | |
bytes memory returndata = to.functionCall(abi.encodeWithSelector( | |
IERC721Receiver(to).onERC721Received.selector, | |
_msgSender(), | |
from, | |
tokenId, | |
_data | |
), "ERC721: transfer to non ERC721Receiver implementer"); | |
bytes4 retval = abi.decode(returndata, (bytes4)); | |
return (retval == _ERC721_RECEIVED); | |
} | |
function _approve(address to, uint256 tokenId) private { | |
_tokenApprovals[tokenId] = to; | |
emit Approval(ownerOf(tokenId), to, tokenId); | |
} | |
/** | |
* @dev Hook that is called before any token transfer. This includes minting | |
* and burning. | |
* | |
* Calling conditions: | |
* | |
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be | |
* transferred to `to`. | |
* - When `from` is zero, `tokenId` will be minted for `to`. | |
* - When `to` is zero, ``from``'s `tokenId` will be burned. | |
* - `from` cannot be the zero address. | |
* - `to` cannot be the zero address. | |
* | |
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { } | |
} | |
abstract contract ERC721Burnable is Context, ERC721 { | |
/** | |
* @dev Burns `tokenId`. See {ERC721-_burn}. | |
* | |
* Requirements: | |
* | |
* - The caller must own `tokenId` or be an approved operator. | |
*/ | |
function burn(uint256 tokenId) public virtual { | |
//solhint-disable-next-line max-line-length | |
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721Burnable: caller is not owner nor approved"); | |
_burn(tokenId); | |
} | |
} | |
contract Ownable is Context { | |
address private _owner; | |
event OwnershipTransferred(address indexed previousOwner, address indexed 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. | |
*/ | |
function owner() public view returns (address) { | |
return _owner; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(_owner == _msgSender(), "Ownable: caller is not the 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. | |
*/ | |
function renounceOwnership() public virtual onlyOwner { | |
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. | |
*/ | |
function transferOwnership(address newOwner) public virtual onlyOwner { | |
require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
emit OwnershipTransferred(_owner, newOwner); | |
_owner = newOwner; | |
} | |
} | |
contract GoDAO is ERC721,ERC721Burnable,Ownable{ | |
uint256 counter = 0; | |
constructor(string memory _name,string memory _symbol) ERC721(_name,_symbol) ERC721Burnable() public{ | |
_mint(msg.sender,0); | |
} | |
modifier capped() { | |
require(totalSupply() < 5,"ERROR: cannot mint more than 5000"); | |
_; | |
} | |
function mintToken(address _address) public onlyOwner() capped(){ | |
counter++; | |
_mint(_address,counter); | |
} | |
function burnToken(uint256 _tokenId) public { | |
_burn(_tokenId); | |
} | |
} |
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
/** | |
*Submitted for verification at Etherscan.io on 2019-04-15 | |
*/ | |
pragma solidity ^0.4.24; | |
/** | |
* @title IERC165 | |
* @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md | |
*/ | |
interface IERC165 { | |
/** | |
* @notice Query if a contract imple | |
* ments an interface | |
* @param interfaceId The interface identifier, as specified in ERC-165 | |
* @dev Interface identification is specified in ERC-165. This function | |
* uses less than 30,000 gas. | |
*/ | |
function supportsInterface(bytes4 interfaceId) | |
external | |
view | |
returns (bool); | |
} | |
/** | |
* @title ERC721 Non-Fungible Token Standard basic interface | |
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract IERC721 is IERC165 { | |
event Transfer( | |
address indexed from, | |
address indexed to, | |
uint256 indexed tokenId | |
); | |
event Approval( | |
address indexed owner, | |
address indexed approved, | |
uint256 indexed tokenId | |
); | |
event ApprovalForAll( | |
address indexed owner, | |
address indexed operator, | |
bool approved | |
); | |
function balanceOf(address owner) public view returns (uint256 balance); | |
function ownerOf(uint256 tokenId) public view returns (address owner); | |
function approve(address to, uint256 tokenId) public; | |
function getApproved(uint256 tokenId) | |
public view returns (address operator); | |
function setApprovalForAll(address operator, bool _approved) public; | |
function isApprovedForAll(address owner, address operator) | |
public view returns (bool); | |
function transferFrom(address from, address to, uint256 tokenId) public; | |
function safeTransferFrom(address from, address to, uint256 tokenId) | |
public; | |
function safeTransferFrom( | |
address from, | |
address to, | |
uint256 tokenId, | |
bytes data | |
) | |
public; | |
} | |
/** | |
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension | |
* @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract IERC721Enumerable is IERC721 { | |
function totalSupply() public view returns (uint256); | |
function tokenOfOwnerByIndex( | |
address owner, | |
uint256 index | |
) | |
public | |
view | |
returns (uint256 tokenId); | |
function tokenByIndex(uint256 index) public view returns (uint256); | |
} | |
/** | |
* @title ERC721 token receiver interface | |
* @dev Interface for any contract that wants to support safeTransfers | |
* from ERC721 asset contracts. | |
*/ | |
contract IERC721Receiver { | |
/** | |
* @notice Handle the receipt of an NFT | |
* @dev The ERC721 smart contract calls this function on the recipient | |
* after a `safeTransfer`. This function MUST return the function selector, | |
* otherwise the caller will revert the transaction. The selector to be | |
* returned can be obtained as `this.onERC721Received.selector`. This | |
* function MAY throw to revert and reject the transfer. | |
* Note: the ERC721 contract address is always the message sender. | |
* @param operator The address which called `safeTransferFrom` function | |
* @param from The address which previously owned the token | |
* @param tokenId The NFT identifier which is being transferred | |
* @param data Additional data with no specified format | |
* @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` | |
*/ | |
function onERC721Received( | |
address operator, | |
address from, | |
uint256 tokenId, | |
bytes data | |
) | |
public | |
returns(bytes4); | |
} | |
/** | |
* @title SafeMath | |
* @dev Math operations with safety checks that throw on error | |
*/ | |
library SafeMath { | |
/** | |
* @dev Multiplies two numbers, throws on overflow. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { | |
// Gas optimization: this is cheaper than asserting 'a' not being zero, but the | |
// benefit is lost if 'b' is also tested. | |
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 | |
if (a == 0) { | |
return 0; | |
} | |
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 a / b; | |
} | |
/** | |
* @dev Subtracts 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 c) { | |
c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
} | |
/** | |
* Utility library of inline functions on addresses | |
*/ | |
library Address { | |
/** | |
* Returns whether the target address is a contract | |
* @dev This function will return false if invoked during the constructor of a contract, | |
* as the code is not actually created until after the constructor finishes. | |
* @param addr address to check | |
* @return whether the target address is a contract | |
*/ | |
function isContract(address addr) internal view returns (bool) { | |
uint256 size; | |
// XXX Currently there is no better way to check if there is a contract in an address | |
// than to check the size of the code at that address. | |
// See https://ethereum.stackexchange.com/a/14016/36603 | |
// for more details about how this works. | |
// TODO Check this again before the Serenity release, because all addresses will be | |
// contracts then. | |
// solium-disable-next-line security/no-inline-assembly | |
assembly { size := extcodesize(addr) } | |
return size > 0; | |
} | |
} | |
/** | |
* @title ERC165 | |
* @author Matt Condon (@shrugs) | |
* @dev Implements ERC165 using a lookup table. | |
*/ | |
contract ERC165 is IERC165 { | |
bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7; | |
/** | |
* 0x01ffc9a7 === | |
* bytes4(keccak256('supportsInterface(bytes4)')) | |
*/ | |
/** | |
* @dev a mapping of interface id to whether or not it's supported | |
*/ | |
mapping(bytes4 => bool) private _supportedInterfaces; | |
/** | |
* @dev A contract implementing SupportsInterfaceWithLookup | |
* implement ERC165 itself | |
*/ | |
constructor() | |
internal | |
{ | |
_registerInterface(_InterfaceId_ERC165); | |
} | |
/** | |
* @dev implement supportsInterface(bytes4) using a lookup table | |
*/ | |
function supportsInterface(bytes4 interfaceId) | |
external | |
view | |
returns (bool) | |
{ | |
return _supportedInterfaces[interfaceId]; | |
} | |
/** | |
* @dev internal method for registering an interface | |
*/ | |
function _registerInterface(bytes4 interfaceId) | |
internal | |
{ | |
require(interfaceId != 0xffffffff); | |
_supportedInterfaces[interfaceId] = true; | |
} | |
} | |
/** | |
* @title ERC721 Non-Fungible Token Standard basic implementation | |
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract ERC721 is ERC165, IERC721 { | |
using SafeMath for uint256; | |
using Address for address; | |
// Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` | |
// which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` | |
bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; | |
// Mapping from token ID to owner | |
mapping (uint256 => address) private _tokenOwner; | |
// Mapping from token ID to approved address | |
mapping (uint256 => address) private _tokenApprovals; | |
// Mapping from owner to number of owned token | |
mapping (address => uint256) private _ownedTokensCount; | |
// Mapping from owner to operator approvals | |
mapping (address => mapping (address => bool)) private _operatorApprovals; | |
bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd; | |
/* | |
* 0x80ac58cd === | |
* bytes4(keccak256('balanceOf(address)')) ^ | |
* bytes4(keccak256('ownerOf(uint256)')) ^ | |
* bytes4(keccak256('approve(address,uint256)')) ^ | |
* bytes4(keccak256('getApproved(uint256)')) ^ | |
* bytes4(keccak256('setApprovalForAll(address,bool)')) ^ | |
* bytes4(keccak256('isApprovedForAll(address,address)')) ^ | |
* bytes4(keccak256('transferFrom(address,address,uint256)')) ^ | |
* bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ | |
* bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) | |
*/ | |
constructor() | |
public | |
{ | |
// register the supported interfaces to conform to ERC721 via ERC165 | |
_registerInterface(_InterfaceId_ERC721); | |
} | |
/** | |
* @dev Gets the balance of the specified address | |
* @param owner address to query the balance of | |
* @return uint256 representing the amount owned by the passed address | |
*/ | |
function balanceOf(address owner) public view returns (uint256) { | |
require(owner != address(0)); | |
return _ownedTokensCount[owner]; | |
} | |
/** | |
* @dev Gets the owner of the specified token ID | |
* @param tokenId uint256 ID of the token to query the owner of | |
* @return owner address currently marked as the owner of the given token ID | |
*/ | |
function ownerOf(uint256 tokenId) public view returns (address) { | |
address owner = _tokenOwner[tokenId]; | |
require(owner != address(0)); | |
return owner; | |
} | |
/** | |
* @dev Approves another address to transfer the given token ID | |
* The zero address indicates there is no approved address. | |
* There can only be one approved address per token at a given time. | |
* Can only be called by the token owner or an approved operator. | |
* @param to address to be approved for the given token ID | |
* @param tokenId uint256 ID of the token to be approved | |
*/ | |
function approve(address to, uint256 tokenId) public { | |
address owner = ownerOf(tokenId); | |
require(to != owner); | |
require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); | |
_tokenApprovals[tokenId] = to; | |
emit Approval(owner, to, tokenId); | |
} | |
/** | |
* @dev Gets the approved address for a token ID, or zero if no address set | |
* Reverts if the token ID does not exist. | |
* @param tokenId uint256 ID of the token to query the approval of | |
* @return address currently approved for the given token ID | |
*/ | |
function getApproved(uint256 tokenId) public view returns (address) { | |
require(_exists(tokenId)); | |
return _tokenApprovals[tokenId]; | |
} | |
/** | |
* @dev Sets or unsets the approval of a given operator | |
* An operator is allowed to transfer all tokens of the sender on their behalf | |
* @param to operator address to set the approval | |
* @param approved representing the status of the approval to be set | |
*/ | |
function setApprovalForAll(address to, bool approved) public { | |
require(to != msg.sender); | |
_operatorApprovals[msg.sender][to] = approved; | |
emit ApprovalForAll(msg.sender, to, approved); | |
} | |
/** | |
* @dev Tells whether an operator is approved by a given owner | |
* @param owner owner address which you want to query the approval of | |
* @param operator operator address which you want to query the approval of | |
* @return bool whether the given operator is approved by the given owner | |
*/ | |
function isApprovedForAll( | |
address owner, | |
address operator | |
) | |
public | |
view | |
returns (bool) | |
{ | |
return _operatorApprovals[owner][operator]; | |
} | |
/** | |
* @dev Transfers the ownership of a given token ID to another address | |
* Usage of this method is discouraged, use `safeTransferFrom` whenever possible | |
* Requires the msg sender to be the owner, approved, or operator | |
* @param from current owner of the token | |
* @param to address to receive the ownership of the given token ID | |
* @param tokenId uint256 ID of the token to be transferred | |
*/ | |
function transferFrom( | |
address from, | |
address to, | |
uint256 tokenId | |
) | |
public | |
{ | |
require(_isApprovedOrOwner(msg.sender, tokenId)); | |
require(to != address(0)); | |
_clearApproval(from, tokenId); | |
_removeTokenFrom(from, tokenId); | |
_addTokenTo(to, tokenId); | |
emit Transfer(from, to, tokenId); | |
} | |
/** | |
* @dev Safely transfers the ownership of a given token ID to another address | |
* If the target address is a contract, it must implement `onERC721Received`, | |
* which is called upon a safe transfer, and return the magic value | |
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, | |
* the transfer is reverted. | |
* | |
* Requires the msg sender to be the owner, approved, or operator | |
* @param from current owner of the token | |
* @param to address to receive the ownership of the given token ID | |
* @param tokenId uint256 ID of the token to be transferred | |
*/ | |
function safeTransferFrom( | |
address from, | |
address to, | |
uint256 tokenId | |
) | |
public | |
{ | |
// solium-disable-next-line arg-overflow | |
safeTransferFrom(from, to, tokenId, ""); | |
} | |
/** | |
* @dev Safely transfers the ownership of a given token ID to another address | |
* If the target address is a contract, it must implement `onERC721Received`, | |
* which is called upon a safe transfer, and return the magic value | |
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, | |
* the transfer is reverted. | |
* Requires the msg sender to be the owner, approved, or operator | |
* @param from current owner of the token | |
* @param to address to receive the ownership of the given token ID | |
* @param tokenId uint256 ID of the token to be transferred | |
* @param _data bytes data to send along with a safe transfer check | |
*/ | |
function safeTransferFrom( | |
address from, | |
address to, | |
uint256 tokenId, | |
bytes _data | |
) | |
public | |
{ | |
transferFrom(from, to, tokenId); | |
// solium-disable-next-line arg-overflow | |
require(_checkOnERC721Received(from, to, tokenId, _data)); | |
} | |
/** | |
* @dev Returns whether the specified token exists | |
* @param tokenId uint256 ID of the token to query the existence of | |
* @return whether the token exists | |
*/ | |
function _exists(uint256 tokenId) internal view returns (bool) { | |
address owner = _tokenOwner[tokenId]; | |
return owner != address(0); | |
} | |
/** | |
* @dev Returns whether the given spender can transfer a given token ID | |
* @param spender address of the spender to query | |
* @param tokenId uint256 ID of the token to be transferred | |
* @return bool whether the msg.sender is approved for the given token ID, | |
* is an operator of the owner, or is the owner of the token | |
*/ | |
function _isApprovedOrOwner( | |
address spender, | |
uint256 tokenId | |
) | |
internal | |
view | |
returns (bool) | |
{ | |
address owner = ownerOf(tokenId); | |
// Disable solium check because of | |
// https://github.com/duaraghav8/Solium/issues/175 | |
// solium-disable-next-line operator-whitespace | |
return ( | |
spender == owner || | |
getApproved(tokenId) == spender || | |
isApprovedForAll(owner, spender) | |
); | |
} | |
/** | |
* @dev Internal function to mint a new token | |
* Reverts if the given token ID already exists | |
* @param to The address that will own the minted token | |
* @param tokenId uint256 ID of the token to be minted by the msg.sender | |
*/ | |
function _mint(address to, uint256 tokenId) internal { | |
require(to != address(0)); | |
_addTokenTo(to, tokenId); | |
emit Transfer(address(0), to, tokenId); | |
} | |
/** | |
* @dev Internal function to burn a specific token | |
* Reverts if the token does not exist | |
* @param tokenId uint256 ID of the token being burned by the msg.sender | |
*/ | |
function _burn(address owner, uint256 tokenId) internal { | |
_clearApproval(owner, tokenId); | |
_removeTokenFrom(owner, tokenId); | |
emit Transfer(owner, address(0), tokenId); | |
} | |
/** | |
* @dev Internal function to add a token ID to the list of a given address | |
* Note that this function is left internal to make ERC721Enumerable possible, but is not | |
* intended to be called by custom derived contracts: in particular, it emits no Transfer event. | |
* @param to address representing the new owner of the given token ID | |
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address | |
*/ | |
function _addTokenTo(address to, uint256 tokenId) internal { | |
require(_tokenOwner[tokenId] == address(0)); | |
_tokenOwner[tokenId] = to; | |
_ownedTokensCount[to] = _ownedTokensCount[to].add(1); | |
} | |
/** | |
* @dev Internal function to remove a token ID from the list of a given address | |
* Note that this function is left internal to make ERC721Enumerable possible, but is not | |
* intended to be called by custom derived contracts: in particular, it emits no Transfer event, | |
* and doesn't clear approvals. | |
* @param from address representing the previous owner of the given token ID | |
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address | |
*/ | |
function _removeTokenFrom(address from, uint256 tokenId) internal { | |
require(ownerOf(tokenId) == from); | |
_ownedTokensCount[from] = _ownedTokensCount[from].sub(1); | |
_tokenOwner[tokenId] = address(0); | |
} | |
/** | |
* @dev Internal function to invoke `onERC721Received` on a target address | |
* The call is not executed if the target address is not a contract | |
* @param from address representing the previous owner of the given token ID | |
* @param to target address that will receive the tokens | |
* @param tokenId uint256 ID of the token to be transferred | |
* @param _data bytes optional data to send along with the call | |
* @return whether the call correctly returned the expected magic value | |
*/ | |
function _checkOnERC721Received( | |
address from, | |
address to, | |
uint256 tokenId, | |
bytes _data | |
) | |
internal | |
returns (bool) | |
{ | |
if (!to.isContract()) { | |
return true; | |
} | |
bytes4 retval = IERC721Receiver(to).onERC721Received( | |
msg.sender, from, tokenId, _data); | |
return (retval == _ERC721_RECEIVED); | |
} | |
/** | |
* @dev Private function to clear current approval of a given token ID | |
* Reverts if the given address is not indeed the owner of the token | |
* @param owner owner of the token | |
* @param tokenId uint256 ID of the token to be transferred | |
*/ | |
function _clearApproval(address owner, uint256 tokenId) private { | |
require(ownerOf(tokenId) == owner); | |
if (_tokenApprovals[tokenId] != address(0)) { | |
_tokenApprovals[tokenId] = address(0); | |
} | |
} | |
} | |
contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { | |
// Mapping from owner to list of owned token IDs | |
mapping(address => uint256[]) private _ownedTokens; | |
// Mapping from token ID to index of the owner tokens list | |
mapping(uint256 => uint256) private _ownedTokensIndex; | |
// Array with all token ids, used for enumeration | |
uint256[] private _allTokens; | |
// Mapping from token id to position in the allTokens array | |
mapping(uint256 => uint256) private _allTokensIndex; | |
bytes4 private constant _InterfaceId_ERC721Enumerable = 0x780e9d63; | |
/** | |
* 0x780e9d63 === | |
* bytes4(keccak256('totalSupply()')) ^ | |
* bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ | |
* bytes4(keccak256('tokenByIndex(uint256)')) | |
*/ | |
/** | |
* @dev Constructor function | |
*/ | |
constructor() public { | |
// register the supported interface to conform to ERC721 via ERC165 | |
_registerInterface(_InterfaceId_ERC721Enumerable); | |
} | |
/** | |
* @dev Gets the token ID at a given index of the tokens list of the requested owner | |
* @param owner address owning the tokens list to be accessed | |
* @param index uint256 representing the index to be accessed of the requested tokens list | |
* @return uint256 token ID at the given index of the tokens list owned by the requested address | |
*/ | |
function tokenOfOwnerByIndex( | |
address owner, | |
uint256 index | |
) | |
public | |
view | |
returns (uint256) | |
{ | |
require(index < balanceOf(owner)); | |
return _ownedTokens[owner][index]; | |
} | |
/** | |
* @dev Gets the total amount of tokens stored by the contract | |
* @return uint256 representing the total amount of tokens | |
*/ | |
function totalSupply() public view returns (uint256) { | |
return _allTokens.length; | |
} | |
/** | |
* @dev Gets the token ID at a given index of all the tokens in this contract | |
* Reverts if the index is greater or equal to the total number of tokens | |
* @param index uint256 representing the index to be accessed of the tokens list | |
* @return uint256 token ID at the given index of the tokens list | |
*/ | |
function tokenByIndex(uint256 index) public view returns (uint256) { | |
require(index < totalSupply()); | |
return _allTokens[index]; | |
} | |
/** | |
* @dev Internal function to add a token ID to the list of a given address | |
* This function is internal due to language limitations, see the note in ERC721.sol. | |
* It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event. | |
* @param to address representing the new owner of the given token ID | |
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address | |
*/ | |
function _addTokenTo(address to, uint256 tokenId) internal { | |
super._addTokenTo(to, tokenId); | |
uint256 length = _ownedTokens[to].length; | |
_ownedTokens[to].push(tokenId); | |
_ownedTokensIndex[tokenId] = length; | |
} | |
/** | |
* @dev Internal function to remove a token ID from the list of a given address | |
* This function is internal due to language limitations, see the note in ERC721.sol. | |
* It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event, | |
* and doesn't clear approvals. | |
* @param from address representing the previous owner of the given token ID | |
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address | |
*/ | |
function _removeTokenFrom(address from, uint256 tokenId) internal { | |
super._removeTokenFrom(from, tokenId); | |
// To prevent a gap in the array, we store the last token in the index of the token to delete, and | |
// then delete the last slot. | |
uint256 tokenIndex = _ownedTokensIndex[tokenId]; | |
uint256 lastTokenIndex = _ownedTokens[from].length.sub(1); | |
uint256 lastToken = _ownedTokens[from][lastTokenIndex]; | |
_ownedTokens[from][tokenIndex] = lastToken; | |
// This also deletes the contents at the last position of the array | |
_ownedTokens[from].length--; | |
// Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to | |
// be zero. Then we can make sure that we will remove tokenId from the ownedTokens list since we are first swapping | |
// the lastToken to the first position, and then dropping the element placed in the last position of the list | |
_ownedTokensIndex[tokenId] = 0; | |
_ownedTokensIndex[lastToken] = tokenIndex; | |
} | |
/** | |
* @dev Internal function to mint a new token | |
* Reverts if the given token ID already exists | |
* @param to address the beneficiary that will own the minted token | |
* @param tokenId uint256 ID of the token to be minted by the msg.sender | |
*/ | |
function _mint(address to, uint256 tokenId) internal { | |
super._mint(to, tokenId); | |
_allTokensIndex[tokenId] = _allTokens.length; | |
_allTokens.push(tokenId); | |
} | |
/** | |
* @dev Internal function to burn a specific token | |
* Reverts if the token does not exist | |
* @param owner owner of the token to burn | |
* @param tokenId uint256 ID of the token being burned by the msg.sender | |
*/ | |
function _burn(address owner, uint256 tokenId) internal { | |
super._burn(owner, tokenId); | |
// Reorg all tokens array | |
uint256 tokenIndex = _allTokensIndex[tokenId]; | |
uint256 lastTokenIndex = _allTokens.length.sub(1); | |
uint256 lastToken = _allTokens[lastTokenIndex]; | |
_allTokens[tokenIndex] = lastToken; | |
_allTokens[lastTokenIndex] = 0; | |
_allTokens.length--; | |
_allTokensIndex[tokenId] = 0; | |
_allTokensIndex[lastToken] = tokenIndex; | |
} | |
} | |
/** | |
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension | |
* @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract IERC721Metadata is IERC721 { | |
function name() external view returns (string); | |
function symbol() external view returns (string); | |
function tokenURI(uint256 tokenId) external view returns (string); | |
} | |
contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { | |
// Token name | |
string private _name; | |
// Token symbol | |
string private _symbol; | |
// Optional mapping for token URIs | |
mapping(uint256 => string) private _tokenURIs; | |
bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; | |
/** | |
* 0x5b5e139f === | |
* bytes4(keccak256('name()')) ^ | |
* bytes4(keccak256('symbol()')) ^ | |
* bytes4(keccak256('tokenURI(uint256)')) | |
*/ | |
/** | |
* @dev Constructor function | |
*/ | |
constructor(string name, string symbol) public { | |
_name = name; | |
_symbol = symbol; | |
// register the supported interfaces to conform to ERC721 via ERC165 | |
_registerInterface(InterfaceId_ERC721Metadata); | |
} | |
/** | |
* @dev Gets the token name | |
* @return string representing the token name | |
*/ | |
function name() external view returns (string) { | |
return _name; | |
} | |
/** | |
* @dev Gets the token symbol | |
* @return string representing the token symbol | |
*/ | |
function symbol() external view returns (string) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns an URI for a given token ID | |
* Throws if the token ID does not exist. May return an empty string. | |
* @param tokenId uint256 ID of the token to query | |
*/ | |
function tokenURI(uint256 tokenId) external view returns (string) { | |
require(_exists(tokenId)); | |
return _tokenURIs[tokenId]; | |
} | |
/** | |
* @dev Internal function to set the token URI for a given token | |
* Reverts if the token ID does not exist | |
* @param tokenId uint256 ID of the token to set its URI | |
* @param uri string URI to assign | |
*/ | |
function _setTokenURI(uint256 tokenId, string uri) internal { | |
require(_exists(tokenId)); | |
_tokenURIs[tokenId] = uri; | |
} | |
/** | |
* @dev Internal function to burn a specific token | |
* Reverts if the token does not exist | |
* @param owner owner of the token to burn | |
* @param tokenId uint256 ID of the token being burned by the msg.sender | |
*/ | |
function _burn(address owner, uint256 tokenId) internal { | |
super._burn(owner, tokenId); | |
// Clear metadata (if any) | |
if (bytes(_tokenURIs[tokenId]).length != 0) { | |
delete _tokenURIs[tokenId]; | |
} | |
} | |
} | |
/** | |
* @title Roles | |
* @dev Library for managing addresses assigned to a Role. | |
*/ | |
library Roles { | |
struct Role { | |
mapping (address => bool) bearer; | |
} | |
/** | |
* @dev give an account access to this role | |
*/ | |
function add(Role storage role, address account) internal { | |
require(account != address(0)); | |
require(!has(role, account)); | |
role.bearer[account] = true; | |
} | |
/** | |
* @dev remove an account's access to this role | |
*/ | |
function remove(Role storage role, address account) internal { | |
require(account != address(0)); | |
require(has(role, account)); | |
role.bearer[account] = false; | |
} | |
/** | |
* @dev check if an account has this role | |
* @return bool | |
*/ | |
function has(Role storage role, address account) | |
internal | |
view | |
returns (bool) | |
{ | |
require(account != address(0)); | |
return role.bearer[account]; | |
} | |
} | |
contract MinterRole { | |
using Roles for Roles.Role; | |
event MinterAdded(address indexed account); | |
event MinterRemoved(address indexed account); | |
Roles.Role private minters; | |
constructor() internal { | |
_addMinter(msg.sender); | |
} | |
modifier onlyMinter() { | |
require(isMinter(msg.sender)); | |
_; | |
} | |
function isMinter(address account) public view returns (bool) { | |
return minters.has(account); | |
} | |
function addMinter(address account) public onlyMinter { | |
_addMinter(account); | |
} | |
function renounceMinter() public { | |
_removeMinter(msg.sender); | |
} | |
function _addMinter(address account) internal { | |
minters.add(account); | |
emit MinterAdded(account); | |
} | |
function _removeMinter(address account) internal { | |
minters.remove(account); | |
emit MinterRemoved(account); | |
} | |
} | |
/** | |
* @title ERC721MetadataMintable | |
* @dev ERC721 minting logic with metadata | |
*/ | |
contract ERC721MetadataMintable is ERC721, ERC721Metadata, MinterRole { | |
/** | |
* @dev Function to mint tokens | |
* @param to The address that will receive the minted tokens. | |
* @param tokenId The token id to mint. | |
* @param tokenURI The token URI of the minted token. | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function mintWithTokenURI( | |
address to, | |
uint256 tokenId, | |
string tokenURI | |
) | |
public | |
onlyMinter | |
returns (bool) | |
{ | |
_mint(to, tokenId); | |
_setTokenURI(tokenId, tokenURI); | |
return true; | |
} | |
} | |
/** | |
* @title Full ERC721 Token | |
* This implementation includes all the required and some optional functionality of the ERC721 standard | |
* Moreover, it includes approve all functionality using operator terminology | |
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract ERC721FullBatchMint is ERC721Enumerable, ERC721MetadataMintable { | |
string public constant version = "Mintable v0.5" ; | |
uint256 public MAX_MINT; | |
constructor(string name, string symbol, string url, uint256 batchMint, address owner) | |
ERC721Metadata(name, symbol) | |
public | |
{ | |
MAX_MINT = batchMint; | |
_mint(owner, 0); | |
_setTokenURI(0, url); | |
} | |
function batchMint (string url, uint256 count) | |
public onlyMinter | |
returns (bool) { | |
if (count > MAX_MINT || count <= 0 || count < 0) { | |
count = MAX_MINT; | |
} | |
uint256 totalSupply = super.totalSupply(); | |
for (uint256 i = 0; i < count; i++) { | |
mintWithTokenURI(msg.sender, totalSupply+i, url); | |
} | |
return true; | |
} | |
} |
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
/** | |
*Submitted for verification at Etherscan.io on 2020-10-25 | |
*/ | |
/** | |
* www.the8020.ch | |
*/ | |
pragma solidity ^0.6.0; | |
/*================================================================================== | |
= The 80/20 is a Wealth Distribution system that is open for anyone to use. = | |
= We created this application with hopes that it will provide a steady stream = | |
= of passive income for generations to come. The foundation that stands behind = | |
= this product would like you to live happy, free, and prosperous. = | |
= Stay tuned for more dApps from the GSG Global Marketing Group. = | |
= #LuckyRico #LACGold #JCunn24 #BoHarvey #LennyBones #WealthWithPhelps = | |
= #ShahzainTariq >= developer of this smart contract = | |
================================================================================*/ | |
interface IERC20 { | |
function totalSupply() external view returns (uint256); | |
function balanceOf(address account) external view returns (uint256); | |
function transfer(address recipient, uint256 amount) external returns (bool); | |
function allowance(address owner, address spender) external view returns (uint256); | |
function approve(address spender, uint256 amount) external returns (bool); | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
event Transfer(address indexed from, address indexed to, uint256 value); | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
contract auto_pool is IERC20{ | |
using SafeMath for uint256; | |
/*================================= | |
= MODIFIERS = | |
=================================*/ | |
// only people with tokens | |
modifier onlybelievers () { | |
require(myTokens() > 0); | |
_; | |
} | |
// only people with profits | |
modifier onlyhodler() { | |
require(myDividends(true) > 0); | |
_; | |
} | |
/*============================== | |
= EVENTS = | |
==============================*/ | |
event onTokenPurchase( | |
address indexed customerAddress, | |
uint256 incomingEthereum, | |
uint256 tokensMinted, | |
address indexed referredBy, | |
uint256 time, | |
uint256 totalTokens | |
); | |
event onTokenSell( | |
address indexed customerAddress, | |
uint256 tokensBurned, | |
uint256 ethereumEarned, | |
uint256 time, | |
uint256 totalTokens | |
); | |
event onReinvestment( | |
address indexed customerAddress, | |
uint256 ethereumReinvested, | |
uint256 tokensMinted | |
); | |
event onWithdraw( | |
address indexed customerAddress, | |
uint256 ethereumWithdrawn | |
); | |
event distrubuteBonusFund( | |
address, | |
uint256 | |
); | |
event amountDistributedToSponsor( | |
address, | |
address, | |
uint256 | |
); | |
// ERC20 | |
event Transfer( | |
address indexed from, | |
address indexed to, | |
uint256 tokens, | |
uint256 time | |
); | |
/*===================================== | |
= CONFIGURABLES = | |
=====================================*/ | |
string public name ; | |
string public symbol ; | |
uint8 public decimals ; | |
uint8 internal dividendFee_ ; | |
uint256 internal tokenPriceInitial_ ; | |
uint256 internal tokenPriceIncremental_ ; | |
uint256 internal magnitude; | |
uint256 public tokenPool; | |
uint256 public loyaltyPool; | |
uint256 public developmentFund; | |
uint256 public sponsorsPaid; | |
uint256 public gsg_foundation; | |
address dev1; | |
address dev2; | |
address GSGO_Official_LoyaltyPlan; | |
uint256 public currentId; | |
uint256 public day; | |
uint256 public claimedLoyalty; | |
uint256 public totalDeposited; | |
uint256 public totalWithdraw; | |
/*================================ | |
= DATASETS = | |
================================*/ | |
// amount of shares for each address (scaled number) | |
mapping(address => uint256) public tokenBalanceLedger_; | |
mapping(address => uint256) public referralBalance_; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
mapping(address => int256) public payoutsTo_; | |
mapping(address => basicData) public users; | |
mapping(uint256 => address) public userList; | |
uint256 internal tokenSupply_ = 0; | |
uint256 internal profitPerShare_; | |
uint256 internal profitperLoyalty; | |
//Users's data set | |
struct basicData{ | |
bool isExist; | |
uint256 id; | |
uint256 referrerId; | |
address referrerAdd; | |
} | |
/*======================================= | |
= PUBLIC FUNCTIONS = | |
=======================================*/ | |
/* | |
* -- APPLICATION ENTRY POINTS -- | |
*/ | |
constructor() public{ | |
name = "The-Eighty-Twenty"; | |
symbol = "GS20"; | |
decimals = 18; | |
dividendFee_ = 10; | |
tokenPriceInitial_ = 0.0000001 ether; | |
tokenPriceIncremental_ = 0.00000001 ether; | |
magnitude = 2**64; | |
// "This is the distribution contract for holders of the GSG-Official (GSGO) Token." | |
GSGO_Official_LoyaltyPlan = address(0x727395b95C90DEab2F220Ce42615d9dD0F44e187); | |
dev1 = address(0x88F2E544359525833f606FB6c63826E143132E7b); | |
dev2 = address(0x7cF196415CDD1eF08ca2358a8282D33Ba089B9f3); | |
currentId = 0; | |
day = now; | |
} | |
/** | |
* Converts all incoming Ethereum to tokens for the caller, and passes down the referral address (if any) | |
*/ | |
function buy(address _referredAdd) | |
public | |
payable | |
returns(uint256) | |
{ | |
require(msg.value >= 0.1 ether, "ERROR: minimun 0.1 ethereum "); | |
require(_referredAdd != msg.sender,"ERROR: cannot become own ref"); | |
if(!users[msg.sender].isExist) register(msg.sender,_referredAdd); | |
purchaseTokens(msg.value,_referredAdd); | |
//Distributing Ethers | |
loyaltyPool += ((msg.value.mul(12)).div(100)); | |
developmentFund += ((msg.value.mul(2)).div(100)); | |
gsg_foundation += ((msg.value.mul(2)).div(100)); | |
payable(GSGO_Official_LoyaltyPlan).transfer((msg.value.mul(2)).div(100)); | |
payable(dev1).transfer((msg.value.mul(1)).div(100)); | |
payable(dev2).transfer((msg.value.mul(1)).div(100)); | |
totalDeposited += msg.value; | |
} | |
receive() external payable { | |
require(msg.value >= 0.1 ether, "ERROR: minimun 0.1 ethereum ."); | |
if(!users[msg.sender].isExist) register(msg.sender,address(0)); | |
purchaseTokens(msg.value,address(0)); | |
//Distributing Ethers | |
loyaltyPool += ((msg.value.mul(12)).div(100)); | |
developmentFund += ( (msg.value.mul(2)).div(100)); | |
gsg_foundation += ((msg.value.mul(2)).div(100)); | |
payable(GSGO_Official_LoyaltyPlan).transfer((msg.value.mul(2)).div(100)); | |
payable(dev1).transfer((msg.value.mul(1)).div(100)); | |
payable(dev2).transfer((msg.value.mul(1)).div(100)); | |
} | |
fallback() | |
payable | |
external | |
{ | |
require(msg.value >= 0.1 ether, "ERROR: minimun 0.1 ethereum ."); | |
if(!users[msg.sender].isExist) register(msg.sender,address(0)); | |
purchaseTokens(msg.value,address(0)); | |
//Distributing Ethers | |
loyaltyPool += ((msg.value.mul(12)).div(100)); | |
developmentFund += ( (msg.value.mul(2)).div(100)); | |
gsg_foundation += ((msg.value.mul(2)).div(100)); | |
payable(GSGO_Official_LoyaltyPlan).transfer((msg.value.mul(2)).div(100)); | |
payable(dev1).transfer((msg.value.mul(1)).div(100)); | |
payable(dev2).transfer((msg.value.mul(1)).div(100)); } | |
/** | |
* Converts all of caller's dividends to tokens. | |
*/ | |
function reinvest() | |
onlyhodler() | |
public | |
{ | |
address _customerAddress = msg.sender; | |
// fetch dividends | |
uint256 _dividends = myDividends(false); // retrieve ref. bonus later in the code | |
uint256 _loyaltyEth = loyaltyOf(); | |
if(_loyaltyEth > 0 ether){ | |
payable(address(_customerAddress)).transfer(_loyaltyEth); | |
loyaltyPool -= _loyaltyEth; | |
claimedLoyalty += _loyaltyEth; | |
totalWithdraw += _loyaltyEth; | |
} | |
// pay out the dividends virtually | |
payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); | |
// retrieve ref. bonus | |
_dividends += referralBalance_[_customerAddress]; | |
referralBalance_[_customerAddress] = 0; | |
// dispatch a buy order with the virtualized "withdrawn dividends" | |
address refAdd = users[_customerAddress].referrerAdd; | |
// dispatch a buy order with the virtualized "withdrawn dividends" | |
uint256 _tokens = purchaseTokens(_dividends,refAdd); | |
loyaltyPool += ((_dividends.mul(12)).div(100)); | |
developmentFund += ((_dividends.mul(2)).div(100)); | |
gsg_foundation += ((_dividends.mul(2)).div(100)); | |
payable(GSGO_Official_LoyaltyPlan).transfer((_dividends.mul(2)).div(100)); | |
payable(dev1).transfer((_dividends.mul(1)).div(100)); | |
payable(dev2).transfer((_dividends.mul(1)).div(100)); | |
// fire event | |
emit onReinvestment(_customerAddress, _dividends, _tokens); | |
} | |
/** | |
* Alias of sell() and withdraw(). | |
*/ | |
function exit() | |
public | |
{ | |
// get token count for caller & sell them all | |
address _customerAddress = msg.sender; | |
uint256 _tokens = tokenBalanceLedger_[_customerAddress]; | |
if(_tokens > 0) sell(_tokens); | |
withdraw(); | |
} | |
/** | |
* Withdraws all of the callers earnings. | |
*/ | |
function withdraw() | |
onlyhodler() | |
public | |
{ | |
// setup data | |
address _customerAddress = msg.sender; | |
uint256 _dividends = myDividends(false); // get ref. bonus later in the code | |
uint256 _loyaltyEth = loyaltyOf(); | |
// update dividend tracker | |
payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); | |
if(_loyaltyEth > 0 ether) { | |
_dividends += _loyaltyEth; | |
loyaltyPool -= _loyaltyEth; | |
claimedLoyalty += _loyaltyEth; | |
} | |
// add ref. bonus | |
_dividends += referralBalance_[_customerAddress]; | |
referralBalance_[_customerAddress] = 0; | |
totalWithdraw += _dividends; | |
// delivery service | |
payable(address(_customerAddress)).transfer(_dividends); | |
// fire event | |
emit onWithdraw(_customerAddress, _dividends); | |
} | |
/** | |
* Liquifies tokens to ethereum. | |
*/ | |
function sell(uint256 _amountOfTokens) | |
onlybelievers () | |
public | |
{ | |
address _customerAddress = msg.sender; | |
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
//initializating values; | |
uint256 _tokens = _amountOfTokens; | |
uint256 _ethereum = tokensToEthereum_(_tokens); | |
uint256 tax = (_ethereum.mul(5)).div(100); | |
loyaltyPool = SafeMath.add(loyaltyPool,tax); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, tax); | |
// burn the sold tokens | |
tokenSupply_ = SafeMath.sub(tokenSupply_, _tokens); | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _tokens); | |
//updates dividends tracker | |
int256 _updatedPayouts = (int256) (profitPerShare_ * _tokens + (_taxedEthereum * magnitude)); | |
payoutsTo_[_customerAddress] -= _updatedPayouts; | |
payoutsTo_[_customerAddress] += (int256) (_taxedEthereum*magnitude); | |
totalWithdraw += _taxedEthereum; | |
//tranfer amout of ethers to user | |
payable(address(_customerAddress)).transfer(_taxedEthereum); | |
if(_ethereum < tokenPool) { | |
tokenPool = SafeMath.sub(tokenPool, _ethereum); | |
} | |
// fire event | |
emit onTokenSell(_customerAddress, _tokens, _taxedEthereum,now,tokenBalanceLedger_[_customerAddress]); | |
} | |
function approve(address spender, uint amount) public override returns (bool) { | |
_approve(msg.sender, spender, amount); | |
return true; | |
} | |
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
_approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)); | |
return true; | |
} | |
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
_approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* Transfer tokens from the caller to a new holder. | |
* Remember, there's a 10% fee here as well. | |
*/ | |
function transfer(address _toAddress, uint256 _amountOfTokens) | |
onlybelievers () | |
public | |
override | |
returns(bool) | |
{ | |
// setup | |
address _customerAddress = msg.sender; | |
// make sure we have the requested tokens | |
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
// exchange tokens | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
tokenBalanceLedger_[_toAddress] = SafeMath.add(tokenBalanceLedger_[_toAddress], _amountOfTokens); | |
// update dividend trackers | |
payoutsTo_[_customerAddress] -= (int256) (profitPerShare_ * _amountOfTokens); | |
payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _amountOfTokens); | |
// fire event | |
emit Transfer(_customerAddress, _toAddress, _amountOfTokens,now); | |
// ERC20 | |
return true; | |
} | |
function transferFrom(address sender, address _toAddress, uint _amountOfTokens) public override returns (bool) { | |
// setup | |
address _customerAddress = sender; | |
// make sure we have the requested tokens | |
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); | |
// exchange tokens | |
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
tokenBalanceLedger_[_toAddress] = SafeMath.add(tokenBalanceLedger_[_toAddress], _amountOfTokens); | |
// update dividend trackers | |
payoutsTo_[_customerAddress] -= (int256) (profitPerShare_ * _amountOfTokens); | |
payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _amountOfTokens); | |
// fire event | |
emit Transfer(_customerAddress, _toAddress, _amountOfTokens,now); | |
_approve(sender, msg.sender, _allowances[sender][msg.sender].sub(_amountOfTokens, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/*---------- HELPERS AND CALCULATORS ----------*/ | |
/** | |
* Method to view the current Ethereum stored in the contract | |
* Example: totalEthereumBalance() | |
*/ | |
function totalEthereumBalance() | |
public | |
view | |
returns(uint) | |
{ | |
return address(this).balance; | |
} | |
/** | |
* Retrieve the total token supply. | |
*/ | |
function totalSupply() | |
public | |
override | |
view | |
returns(uint256) | |
{ | |
return tokenSupply_; | |
} | |
/** | |
* Retrieve the tokens owned by the caller. | |
*/ | |
function myTokens() | |
public | |
view | |
returns(uint256) | |
{ | |
address _customerAddress = msg.sender; | |
return balanceOf(_customerAddress); | |
} | |
/** | |
* Retrieve the dividends owned by the caller. | |
*/ | |
function myDividends(bool _includeReferralBonus) | |
public | |
view | |
returns(uint256) | |
{ | |
address _customerAddress = msg.sender; | |
return _includeReferralBonus ? dividendsOf(_customerAddress) + referralBalance_[_customerAddress] : dividendsOf(_customerAddress) ; | |
} | |
/** | |
* Retrieve the token balance of any single address. | |
*/ | |
function balanceOf(address _customerAddress) | |
view | |
public | |
override | |
returns(uint256) | |
{ | |
return tokenBalanceLedger_[_customerAddress]; | |
} | |
/** | |
* Retrieve the dividend balance of any single address. | |
*/ | |
function dividendsOf(address _customerAddress) | |
view | |
public | |
returns(uint256) | |
{ | |
return (uint256) ((int256)(profitPerShare_ * tokenBalanceLedger_[_customerAddress]) - payoutsTo_[_customerAddress]) / magnitude; | |
} | |
/** | |
* Return the buy price of 1 individual token. | |
*/ | |
function sellPrice() | |
public | |
view | |
returns(uint256) | |
{ | |
if(tokenSupply_ == 0){ | |
return tokenPriceInitial_ - tokenPriceIncremental_; | |
} else { | |
uint256 _ethereum = tokensToEthereum_(1e18); | |
uint256 tax = (_ethereum.mul(5)).div(100); | |
uint256 _dividends = SafeMath.div(_ethereum, tax); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
} | |
/** | |
* Return the sell price of 1 individual token. | |
*/ | |
function buyPrice() | |
public | |
view | |
returns(uint256) | |
{ | |
if(tokenSupply_ == 0){ | |
return tokenPriceInitial_ + tokenPriceIncremental_; | |
} else { | |
uint256 _ethereum = tokensToEthereum_(1e18); | |
uint256 _dividends = SafeMath.div(_ethereum, dividendFee_ ); | |
uint256 _taxedEthereum = SafeMath.add(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
} | |
function calculateTokensReceived(uint256 _ethToSpend) | |
public | |
view | |
returns(uint256) | |
{ | |
uint256 _ethereumToSpend = (_ethToSpend.mul(64)).div(100); | |
uint256 _dividends = SafeMath.div(_ethereumToSpend, dividendFee_); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereumToSpend, _dividends); | |
uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); | |
return _amountOfTokens; | |
} | |
function getReferrer() public view returns(address){ | |
return users[msg.sender].referrerAdd; | |
} | |
function calculateEthereumReceived(uint256 _tokensToSell) | |
public | |
view | |
returns(uint256) | |
{ | |
require(_tokensToSell <= tokenSupply_); | |
uint256 _ethereum = tokensToEthereum_(_tokensToSell); | |
uint256 tax = (_ethereum.mul(5)).div(100); | |
uint256 _dividends = SafeMath.div(_ethereum, tax); | |
uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); | |
return _taxedEthereum; | |
} | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
function loyaltyOf() public view returns(uint256){ | |
address _customerAddress = msg.sender; | |
// user should hold 2500 tokens for qualify for loyalty bonus; | |
if(tokenBalanceLedger_[_customerAddress] >= 2000*10**uint256(decimals)){ | |
// return loyalty bonus users | |
return ((uint256) ((int256)((profitperLoyalty) * tokenBalanceLedger_[_customerAddress]) - payoutsTo_[_customerAddress]) / magnitude)*14/5; | |
} | |
else{ | |
return 0; | |
} | |
} | |
function userReferrer(address _address) public view returns(address){ | |
return userList[users[_address].referrerId]; | |
} | |
/*========================================== | |
= INTERNAL FUNCTIONS = | |
==========================================*/ | |
function purchaseTokens(uint256 _eth, address _referredBy) | |
internal | |
returns(uint256) | |
{ | |
uint256 _incomingEthereum = (_eth.mul(64)).div(100); | |
// data setup | |
address _customerAddress = msg.sender; | |
uint256 _undividedDividends = SafeMath.div(_incomingEthereum, dividendFee_); | |
uint256 _referralBonus = SafeMath.div(_undividedDividends, 3); | |
uint256 _dividends = SafeMath.sub(_undividedDividends, _referralBonus); | |
uint256 _taxedEthereum = SafeMath.sub(_incomingEthereum, _undividedDividends); | |
uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); | |
uint256 _fee = _dividends * magnitude; | |
tokenPool += _taxedEthereum; | |
require(_amountOfTokens > 0 && (SafeMath.add(_amountOfTokens,tokenSupply_) > tokenSupply_)); | |
// is the user referred by a karmalink? | |
if( | |
// is this a referred purchase? | |
_referredBy != 0x0000000000000000000000000000000000000000 && | |
// no cheating! | |
_referredBy != _customerAddress | |
){ | |
// wealth redistribution | |
distributeToSponsor(_referredBy,_eth); | |
} else { | |
// no ref purchase | |
// add the referral bonus back to the global dividends cake | |
_dividends = SafeMath.add(_dividends, _referralBonus); | |
_fee = _dividends * magnitude; | |
} | |
// we can't give people infinite ethereum | |
if(tokenSupply_ > 0){ | |
// add tokens to the pool | |
tokenSupply_ = SafeMath.add(tokenSupply_, _amountOfTokens); | |
// take the amount of dividends gained through this transaction, and allocates them evenly to each shareholder | |
profitPerShare_ += (_dividends * magnitude / (tokenSupply_)); | |
profitperLoyalty += ((_dividends) * magnitude / (tokenSupply_)); | |
// calculate the amount of tokens the customer receives over his purchase | |
_fee = _fee - (_fee-(_amountOfTokens * (_dividends * magnitude / (tokenSupply_)))); | |
} else { | |
// add tokens to the pool | |
tokenSupply_ = _amountOfTokens; | |
} | |
// update circulating supply & the ledger address for the customer | |
tokenBalanceLedger_[_customerAddress] = SafeMath.add(tokenBalanceLedger_[_customerAddress], _amountOfTokens); | |
//update dividends tracker | |
int256 _updatedPayouts = (int256) ((profitPerShare_ * _amountOfTokens) - _fee); | |
payoutsTo_[_customerAddress] += _updatedPayouts; | |
// fire event | |
emit onTokenPurchase(_customerAddress, _incomingEthereum, _amountOfTokens, _referredBy,now,tokenBalanceLedger_[_customerAddress]); | |
return _amountOfTokens; | |
} | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* Calculate Token price based on an amount of incoming ethereum | |
* Some conversions occurred to prevent decimal errors or underflows / overflows in solidity code. | |
*/ | |
function ethereumToTokens_(uint256 _ethereum) | |
internal | |
view | |
returns(uint256) | |
{ | |
uint256 _tokenPriceInitial = tokenPriceInitial_ * 1e18; | |
uint256 _tokensReceived = | |
( | |
( | |
// underflow attempts BTFO | |
SafeMath.sub( | |
(sqrt | |
( | |
(_tokenPriceInitial**2) | |
+ | |
(2*(tokenPriceIncremental_ * 1e18)*(_ethereum * 1e18)) | |
+ | |
(((tokenPriceIncremental_)**2)*(tokenSupply_**2)) | |
+ | |
(2*(tokenPriceIncremental_)*_tokenPriceInitial*tokenSupply_) | |
) | |
), _tokenPriceInitial | |
) | |
)/(tokenPriceIncremental_) | |
)-(tokenSupply_) | |
; | |
return _tokensReceived; | |
} | |
/** | |
* Calculate token sell value. | |
*/ | |
function tokensToEthereum_(uint256 _tokens) | |
internal | |
view | |
returns(uint256) | |
{ | |
uint256 tokens_ = (_tokens + 1e18); | |
uint256 _tokenSupply = (tokenSupply_ + 1e18); | |
uint256 _etherReceived = | |
( | |
// underflow attempts BTFO | |
SafeMath.sub( | |
( | |
( | |
( | |
tokenPriceInitial_ +(tokenPriceIncremental_ * (_tokenSupply/1e18)) | |
)-tokenPriceIncremental_ | |
)*(tokens_ - 1e18) | |
),(tokenPriceIncremental_*((tokens_**2-tokens_)/1e18))/2 | |
) | |
/1e18); | |
return _etherReceived; | |
} | |
function register(address _sender, address _referredBy) internal { | |
uint256 _id = users[_referredBy].id; | |
basicData memory UserStruct; | |
currentId++; | |
//add users data | |
UserStruct = basicData({ | |
isExist: true, | |
id: currentId, | |
referrerId: _id, | |
referrerAdd: _referredBy | |
}); | |
userList[currentId] = _sender; | |
users[msg.sender] = UserStruct; | |
} | |
function distributeToSponsor(address _address,uint256 _eth) internal { | |
uint256 _sp1 = (_eth.mul(10)).div(100); | |
uint256 _sp2 = (_eth.mul(7)).div(100); | |
uint256 _sp3 = (_eth.mul(3)).div(100); | |
address add1 = _address; | |
address add2 = users[_address].referrerAdd; | |
address add3 = users[add2].referrerAdd; | |
//add amount of ref bonus to referrer | |
referralBalance_[add1] += (_sp1); | |
sponsorsPaid += _sp1; | |
//fire event on distributionToSponsor | |
emit amountDistributedToSponsor(msg.sender, add1,_sp1); | |
//add amount of ref bonus to referrer | |
referralBalance_[add2] += (_sp2); | |
sponsorsPaid += _sp2; | |
//fire event on distributionToSponsor | |
emit amountDistributedToSponsor(msg.sender, add2, _sp2); | |
//add amount of ref bonus to referrer | |
referralBalance_[add3] += (_sp3); | |
sponsorsPaid += _sp3; | |
//fire event on distributionToSponsor | |
emit amountDistributedToSponsor(msg.sender, add3, _sp3); | |
} | |
function sqrt(uint x) internal pure returns (uint y) { | |
uint z = (x + 1) / 2; | |
y = x; | |
while (z < y) { | |
y = z; | |
z = (x / z + z) / 2; | |
} | |
} | |
} | |
/** | |
* @title SafeMath | |
* @dev Math operations with safety checks that throw on error | |
*/ | |
library SafeMath { | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
return sub(a, b, "SafeMath: subtraction overflow"); | |
} | |
function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
require(b <= a, errorMessage); | |
uint c = a - b; | |
return c; | |
} | |
function mul(uint a, uint b) internal pure returns (uint) { | |
if (a == 0) { | |
return 0; | |
} | |
uint c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
return div(a, b, "SafeMath: division by zero"); | |
} | |
function div(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
// Solidity only automatically asserts when dividing by 0 | |
require(b > 0, errorMessage); | |
uint c = a / b; | |
return c; | |
} | |
} |
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.6.0; | |
pragma solidity ^0.4.24; | |
/** | |
* @title IERC165 | |
* @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md | |
*/ | |
interface IERC165 { | |
/** | |
* @notice Query if a contract implements an interface | |
* @param interfaceId The interface identifier, as specified in ERC-165 | |
* @dev Interface identification is specified in ERC-165. This function | |
* uses less than 30,000 gas. | |
*/ | |
function supportsInterface(bytes4 interfaceId) | |
external | |
view | |
returns (bool); | |
} | |
/** | |
* @title ERC721 Non-Fungible Token Standard basic interface | |
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract IERC721 is IERC165 { | |
event Transfer( | |
address indexed from, | |
address indexed to, | |
uint256 indexed tokenId | |
); | |
event Approval( | |
address indexed owner, | |
address indexed approved, | |
uint256 indexed tokenId | |
); | |
event ApprovalForAll( | |
address indexed owner, | |
address indexed operator, | |
bool approved | |
); | |
function balanceOf(address owner) public view returns (uint256 balance); | |
function ownerOf(uint256 tokenId) public view returns (address owner); | |
function approve(address to, uint256 tokenId) public; | |
function getApproved(uint256 tokenId) | |
public view returns (address operator); | |
function setApprovalForAll(address operator, bool _approved) public; | |
function isApprovedForAll(address owner, address operator) | |
public view returns (bool); | |
function transferFrom(address from, address to, uint256 tokenId) public; | |
function safeTransferFrom(address from, address to, uint256 tokenId) | |
public; | |
function safeTransferFrom( | |
address from, | |
address to, | |
uint256 tokenId, | |
bytes data | |
) | |
public; | |
} | |
/** | |
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension | |
* @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract IERC721Enumerable is IERC721 { | |
function totalSupply() public view returns (uint256); | |
function tokenOfOwnerByIndex( | |
address owner, | |
uint256 index | |
) | |
public | |
view | |
returns (uint256 tokenId); | |
function tokenByIndex(uint256 index) public view returns (uint256); | |
} | |
/** | |
* @title ERC721 token receiver interface | |
* @dev Interface for any contract that wants to support safeTransfers | |
* from ERC721 asset contracts. | |
*/ | |
contract IERC721Receiver { | |
/** | |
* @notice Handle the receipt of an NFT | |
* @dev The ERC721 smart contract calls this function on the recipient | |
* after a `safeTransfer`. This function MUST return the function selector, | |
* otherwise the caller will revert the transaction. The selector to be | |
* returned can be obtained as `this.onERC721Received.selector`. This | |
* function MAY throw to revert and reject the transfer. | |
* Note: the ERC721 contract address is always the message sender. | |
* @param operator The address which called `safeTransferFrom` function | |
* @param from The address which previously owned the token | |
* @param tokenId The NFT identifier which is being transferred | |
* @param data Additional data with no specified format | |
* @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` | |
*/ | |
function onERC721Received( | |
address operator, | |
address from, | |
uint256 tokenId, | |
bytes data | |
) | |
public | |
returns(bytes4); | |
} | |
/** | |
* @title SafeMath | |
* @dev Math operations with safety checks that throw on error | |
*/ | |
library SafeMath { | |
/** | |
* @dev Multiplies two numbers, throws on overflow. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { | |
// Gas optimization: this is cheaper than asserting 'a' not being zero, but the | |
// benefit is lost if 'b' is also tested. | |
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 | |
if (a == 0) { | |
return 0; | |
} | |
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 a / b; | |
} | |
/** | |
* @dev Subtracts 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 c) { | |
c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
} | |
/** | |
* Utility library of inline functions on addresses | |
*/ | |
library Address { | |
/** | |
* Returns whether the target address is a contract | |
* @dev This function will return false if invoked during the constructor of a contract, | |
* as the code is not actually created until after the constructor finishes. | |
* @param addr address to check | |
* @return whether the target address is a contract | |
*/ | |
function isContract(address addr) internal view returns (bool) { | |
uint256 size; | |
// XXX Currently there is no better way to check if there is a contract in an address | |
// than to check the size of the code at that address. | |
// See https://ethereum.stackexchange.com/a/14016/36603 | |
// for more details about how this works. | |
// TODO Check this again before the Serenity release, because all addresses will be | |
// contracts then. | |
// solium-disable-next-line security/no-inline-assembly | |
assembly { size := extcodesize(addr) } | |
return size > 0; | |
} | |
} | |
/** | |
* @title ERC165 | |
* @author Matt Condon (@shrugs) | |
* @dev Implements ERC165 using a lookup table. | |
*/ | |
contract ERC165 is IERC165 { | |
bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7; | |
/** | |
* 0x01ffc9a7 === | |
* bytes4(keccak256('supportsInterface(bytes4)')) | |
*/ | |
/** | |
* @dev a mapping of interface id to whether or not it's supported | |
*/ | |
mapping(bytes4 => bool) private _supportedInterfaces; | |
/** | |
* @dev A contract implementing SupportsInterfaceWithLookup | |
* implement ERC165 itself | |
*/ | |
constructor() | |
internal | |
{ | |
_registerInterface(_InterfaceId_ERC165); | |
} | |
/** | |
* @dev implement supportsInterface(bytes4) using a lookup table | |
*/ | |
function supportsInterface(bytes4 interfaceId) | |
external | |
view | |
returns (bool) | |
{ | |
return _supportedInterfaces[interfaceId]; | |
} | |
/** | |
* @dev internal method for registering an interface | |
*/ | |
function _registerInterface(bytes4 interfaceId) | |
internal | |
{ | |
require(interfaceId != 0xffffffff); | |
_supportedInterfaces[interfaceId] = true; | |
} | |
} | |
/** | |
* @title ERC721 Non-Fungible Token Standard basic implementation | |
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract ERC721 is ERC165, IERC721 { | |
using SafeMath for uint256; | |
using Address for address; | |
// Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` | |
// which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` | |
bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; | |
// Mapping from token ID to owner | |
mapping (uint256 => address) private _tokenOwner; | |
// Mapping from token ID to approved address | |
mapping (uint256 => address) private _tokenApprovals; | |
// Mapping from owner to number of owned token | |
mapping (address => uint256) private _ownedTokensCount; | |
// Mapping from owner to operator approvals | |
mapping (address => mapping (address => bool)) private _operatorApprovals; | |
bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd; | |
/* | |
* 0x80ac58cd === | |
* bytes4(keccak256('balanceOf(address)')) ^ | |
* bytes4(keccak256('ownerOf(uint256)')) ^ | |
* bytes4(keccak256('approve(address,uint256)')) ^ | |
* bytes4(keccak256('getApproved(uint256)')) ^ | |
* bytes4(keccak256('setApprovalForAll(address,bool)')) ^ | |
* bytes4(keccak256('isApprovedForAll(address,address)')) ^ | |
* bytes4(keccak256('transferFrom(address,address,uint256)')) ^ | |
* bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ | |
* bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) | |
*/ | |
constructor() | |
public | |
{ | |
// register the supported interfaces to conform to ERC721 via ERC165 | |
_registerInterface(_InterfaceId_ERC721); | |
} | |
/** | |
* @dev Gets the balance of the specified address | |
* @param owner address to query the balance of | |
* @return uint256 representing the amount owned by the passed address | |
*/ | |
function balanceOf(address owner) public view returns (uint256) { | |
require(owner != address(0)); | |
return _ownedTokensCount[owner]; | |
} | |
/** | |
* @dev Gets the owner of the specified token ID | |
* @param tokenId uint256 ID of the token to query the owner of | |
* @return owner address currently marked as the owner of the given token ID | |
*/ | |
function ownerOf(uint256 tokenId) public view returns (address) { | |
address owner = _tokenOwner[tokenId]; | |
require(owner != address(0)); | |
return owner; | |
} | |
/** | |
* @dev Approves another address to transfer the given token ID | |
* The zero address indicates there is no approved address. | |
* There can only be one approved address per token at a given time. | |
* Can only be called by the token owner or an approved operator. | |
* @param to address to be approved for the given token ID | |
* @param tokenId uint256 ID of the token to be approved | |
*/ | |
function approve(address to, uint256 tokenId) public { | |
address owner = ownerOf(tokenId); | |
require(to != owner); | |
require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); | |
_tokenApprovals[tokenId] = to; | |
emit Approval(owner, to, tokenId); | |
} | |
/** | |
* @dev Gets the approved address for a token ID, or zero if no address set | |
* Reverts if the token ID does not exist. | |
* @param tokenId uint256 ID of the token to query the approval of | |
* @return address currently approved for the given token ID | |
*/ | |
function getApproved(uint256 tokenId) public view returns (address) { | |
require(_exists(tokenId)); | |
return _tokenApprovals[tokenId]; | |
} | |
/** | |
* @dev Sets or unsets the approval of a given operator | |
* An operator is allowed to transfer all tokens of the sender on their behalf | |
* @param to operator address to set the approval | |
* @param approved representing the status of the approval to be set | |
*/ | |
function setApprovalForAll(address to, bool approved) public { | |
require(to != msg.sender); | |
_operatorApprovals[msg.sender][to] = approved; | |
emit ApprovalForAll(msg.sender, to, approved); | |
} | |
/** | |
* @dev Tells whether an operator is approved by a given owner | |
* @param owner owner address which you want to query the approval of | |
* @param operator operator address which you want to query the approval of | |
* @return bool whether the given operator is approved by the given owner | |
*/ | |
function isApprovedForAll( | |
address owner, | |
address operator | |
) | |
public | |
view | |
returns (bool) | |
{ | |
return _operatorApprovals[owner][operator]; | |
} | |
/** | |
* @dev Transfers the ownership of a given token ID to another address | |
* Usage of this method is discouraged, use `safeTransferFrom` whenever possible | |
* Requires the msg sender to be the owner, approved, or operator | |
* @param from current owner of the token | |
* @param to address to receive the ownership of the given token ID | |
* @param tokenId uint256 ID of the token to be transferred | |
*/ | |
function transferFrom( | |
address from, | |
address to, | |
uint256 tokenId | |
) | |
public | |
{ | |
require(_isApprovedOrOwner(msg.sender, tokenId)); | |
require(to != address(0)); | |
_clearApproval(from, tokenId); | |
_removeTokenFrom(from, tokenId); | |
_addTokenTo(to, tokenId); | |
emit Transfer(from, to, tokenId); | |
} | |
/** | |
* @dev Safely transfers the ownership of a given token ID to another address | |
* If the target address is a contract, it must implement `onERC721Received`, | |
* which is called upon a safe transfer, and return the magic value | |
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, | |
* the transfer is reverted. | |
* | |
* Requires the msg sender to be the owner, approved, or operator | |
* @param from current owner of the token | |
* @param to address to receive the ownership of the given token ID | |
* @param tokenId uint256 ID of the token to be transferred | |
*/ | |
function safeTransferFrom( | |
address from, | |
address to, | |
uint256 tokenId | |
) | |
public | |
{ | |
// solium-disable-next-line arg-overflow | |
safeTransferFrom(from, to, tokenId, ""); | |
} | |
/** | |
* @dev Safely transfers the ownership of a given token ID to another address | |
* If the target address is a contract, it must implement `onERC721Received`, | |
* which is called upon a safe transfer, and return the magic value | |
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, | |
* the transfer is reverted. | |
* Requires the msg sender to be the owner, approved, or operator | |
* @param from current owner of the token | |
* @param to address to receive the ownership of the given token ID | |
* @param tokenId uint256 ID of the token to be transferred | |
* @param _data bytes data to send along with a safe transfer check | |
*/ | |
function safeTransferFrom( | |
address from, | |
address to, | |
uint256 tokenId, | |
bytes _data | |
) | |
public | |
{ | |
transferFrom(from, to, tokenId); | |
// solium-disable-next-line arg-overflow | |
require(_checkOnERC721Received(from, to, tokenId, _data)); | |
} | |
/** | |
* @dev Returns whether the specified token exists | |
* @param tokenId uint256 ID of the token to query the existence of | |
* @return whether the token exists | |
*/ | |
function _exists(uint256 tokenId) internal view returns (bool) { | |
address owner = _tokenOwner[tokenId]; | |
return owner != address(0); | |
} | |
/** | |
* @dev Returns whether the given spender can transfer a given token ID | |
* @param spender address of the spender to query | |
* @param tokenId uint256 ID of the token to be transferred | |
* @return bool whether the msg.sender is approved for the given token ID, | |
* is an operator of the owner, or is the owner of the token | |
*/ | |
function _isApprovedOrOwner( | |
address spender, | |
uint256 tokenId | |
) | |
internal | |
view | |
returns (bool) | |
{ | |
address owner = ownerOf(tokenId); | |
// Disable solium check because of | |
// https://github.com/duaraghav8/Solium/issues/175 | |
// solium-disable-next-line operator-whitespace | |
return ( | |
spender == owner || | |
getApproved(tokenId) == spender || | |
isApprovedForAll(owner, spender) | |
); | |
} | |
/** | |
* @dev Internal function to mint a new token | |
* Reverts if the given token ID already exists | |
* @param to The address that will own the minted token | |
* @param tokenId uint256 ID of the token to be minted by the msg.sender | |
*/ | |
function _mint(address to, uint256 tokenId) internal { | |
require(to != address(0)); | |
_addTokenTo(to, tokenId); | |
emit Transfer(address(0), to, tokenId); | |
} | |
/** | |
* @dev Internal function to burn a specific token | |
* Reverts if the token does not exist | |
* @param tokenId uint256 ID of the token being burned by the msg.sender | |
*/ | |
function _burn(address owner, uint256 tokenId) internal { | |
_clearApproval(owner, tokenId); | |
_removeTokenFrom(owner, tokenId); | |
emit Transfer(owner, address(0), tokenId); | |
} | |
/** | |
* @dev Internal function to add a token ID to the list of a given address | |
* Note that this function is left internal to make ERC721Enumerable possible, but is not | |
* intended to be called by custom derived contracts: in particular, it emits no Transfer event. | |
* @param to address representing the new owner of the given token ID | |
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address | |
*/ | |
function _addTokenTo(address to, uint256 tokenId) internal { | |
require(_tokenOwner[tokenId] == address(0)); | |
_tokenOwner[tokenId] = to; | |
_ownedTokensCount[to] = _ownedTokensCount[to].add(1); | |
} | |
/** | |
* @dev Internal function to remove a token ID from the list of a given address | |
* Note that this function is left internal to make ERC721Enumerable possible, but is not | |
* intended to be called by custom derived contracts: in particular, it emits no Transfer event, | |
* and doesn't clear approvals. | |
* @param from address representing the previous owner of the given token ID | |
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address | |
*/ | |
function _removeTokenFrom(address from, uint256 tokenId) internal { | |
require(ownerOf(tokenId) == from); | |
_ownedTokensCount[from] = _ownedTokensCount[from].sub(1); | |
_tokenOwner[tokenId] = address(0); | |
} | |
/** | |
* @dev Internal function to invoke `onERC721Received` on a target address | |
* The call is not executed if the target address is not a contract | |
* @param from address representing the previous owner of the given token ID | |
* @param to target address that will receive the tokens | |
* @param tokenId uint256 ID of the token to be transferred | |
* @param _data bytes optional data to send along with the call | |
* @return whether the call correctly returned the expected magic value | |
*/ | |
function _checkOnERC721Received( | |
address from, | |
address to, | |
uint256 tokenId, | |
bytes _data | |
) | |
internal | |
returns (bool) | |
{ | |
if (!to.isContract()) { | |
return true; | |
} | |
bytes4 retval = IERC721Receiver(to).onERC721Received( | |
msg.sender, from, tokenId, _data); | |
return (retval == _ERC721_RECEIVED); | |
} | |
/** | |
* @dev Private function to clear current approval of a given token ID | |
* Reverts if the given address is not indeed the owner of the token | |
* @param owner owner of the token | |
* @param tokenId uint256 ID of the token to be transferred | |
*/ | |
function _clearApproval(address owner, uint256 tokenId) private { | |
require(ownerOf(tokenId) == owner); | |
if (_tokenApprovals[tokenId] != address(0)) { | |
_tokenApprovals[tokenId] = address(0); | |
} | |
} | |
} | |
contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { | |
// Mapping from owner to list of owned token IDs | |
mapping(address => uint256[]) private _ownedTokens; | |
// Mapping from token ID to index of the owner tokens list | |
mapping(uint256 => uint256) private _ownedTokensIndex; | |
// Array with all token ids, used for enumeration | |
uint256[] private _allTokens; | |
// Mapping from token id to position in the allTokens array | |
mapping(uint256 => uint256) private _allTokensIndex; | |
bytes4 private constant _InterfaceId_ERC721Enumerable = 0x780e9d63; | |
/** | |
* 0x780e9d63 === | |
* bytes4(keccak256('totalSupply()')) ^ | |
* bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ | |
* bytes4(keccak256('tokenByIndex(uint256)')) | |
*/ | |
/** | |
* @dev Constructor function | |
*/ | |
constructor() public { | |
// register the supported interface to conform to ERC721 via ERC165 | |
_registerInterface(_InterfaceId_ERC721Enumerable); | |
} | |
/** | |
* @dev Gets the token ID at a given index of the tokens list of the requested owner | |
* @param owner address owning the tokens list to be accessed | |
* @param index uint256 representing the index to be accessed of the requested tokens list | |
* @return uint256 token ID at the given index of the tokens list owned by the requested address | |
*/ | |
function tokenOfOwnerByIndex( | |
address owner, | |
uint256 index | |
) | |
public | |
view | |
returns (uint256) | |
{ | |
require(index < balanceOf(owner)); | |
return _ownedTokens[owner][index]; | |
} | |
/** | |
* @dev Gets the total amount of tokens stored by the contract | |
* @return uint256 representing the total amount of tokens | |
*/ | |
function totalSupply() public view returns (uint256) { | |
return _allTokens.length; | |
} | |
/** | |
* @dev Gets the token ID at a given index of all the tokens in this contract | |
* Reverts if the index is greater or equal to the total number of tokens | |
* @param index uint256 representing the index to be accessed of the tokens list | |
* @return uint256 token ID at the given index of the tokens list | |
*/ | |
function tokenByIndex(uint256 index) public view returns (uint256) { | |
require(index < totalSupply()); | |
return _allTokens[index]; | |
} | |
/** | |
* @dev Internal function to add a token ID to the list of a given address | |
* This function is internal due to language limitations, see the note in ERC721.sol. | |
* It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event. | |
* @param to address representing the new owner of the given token ID | |
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address | |
*/ | |
function _addTokenTo(address to, uint256 tokenId) internal { | |
super._addTokenTo(to, tokenId); | |
uint256 length = _ownedTokens[to].length; | |
_ownedTokens[to].push(tokenId); | |
_ownedTokensIndex[tokenId] = length; | |
} | |
/** | |
* @dev Internal function to remove a token ID from the list of a given address | |
* This function is internal due to language limitations, see the note in ERC721.sol. | |
* It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event, | |
* and doesn't clear approvals. | |
* @param from address representing the previous owner of the given token ID | |
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address | |
*/ | |
function _removeTokenFrom(address from, uint256 tokenId) internal { | |
super._removeTokenFrom(from, tokenId); | |
// To prevent a gap in the array, we store the last token in the index of the token to delete, and | |
// then delete the last slot. | |
uint256 tokenIndex = _ownedTokensIndex[tokenId]; | |
uint256 lastTokenIndex = _ownedTokens[from].length.sub(1); | |
uint256 lastToken = _ownedTokens[from][lastTokenIndex]; | |
_ownedTokens[from][tokenIndex] = lastToken; | |
// This also deletes the contents at the last position of the array | |
_ownedTokens[from].length--; | |
// Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to | |
// be zero. Then we can make sure that we will remove tokenId from the ownedTokens list since we are first swapping | |
// the lastToken to the first position, and then dropping the element placed in the last position of the list | |
_ownedTokensIndex[tokenId] = 0; | |
_ownedTokensIndex[lastToken] = tokenIndex; | |
} | |
/** | |
* @dev Internal function to mint a new token | |
* Reverts if the given token ID already exists | |
* @param to address the beneficiary that will own the minted token | |
* @param tokenId uint256 ID of the token to be minted by the msg.sender | |
*/ | |
function _mint(address to, uint256 tokenId) internal { | |
super._mint(to, tokenId); | |
_allTokensIndex[tokenId] = _allTokens.length; | |
_allTokens.push(tokenId); | |
} | |
/** | |
* @dev Internal function to burn a specific token | |
* Reverts if the token does not exist | |
* @param owner owner of the token to burn | |
* @param tokenId uint256 ID of the token being burned by the msg.sender | |
*/ | |
function _burn(address owner, uint256 tokenId) internal { | |
super._burn(owner, tokenId); | |
// Reorg all tokens array | |
uint256 tokenIndex = _allTokensIndex[tokenId]; | |
uint256 lastTokenIndex = _allTokens.length.sub(1); | |
uint256 lastToken = _allTokens[lastTokenIndex]; | |
_allTokens[tokenIndex] = lastToken; | |
_allTokens[lastTokenIndex] = 0; | |
_allTokens.length--; | |
_allTokensIndex[tokenId] = 0; | |
_allTokensIndex[lastToken] = tokenIndex; | |
} | |
} | |
/** | |
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension | |
* @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract IERC721Metadata is IERC721 { | |
function name() external view returns (string); | |
function symbol() external view returns (string); | |
function tokenURI(uint256 tokenId) external view returns (string); | |
} | |
contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { | |
// Token name | |
string private _name; | |
// Token symbol | |
string private _symbol; | |
// Optional mapping for token URIs | |
mapping(uint256 => string) private _tokenURIs; | |
bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; | |
/** | |
* 0x5b5e139f === | |
* bytes4(keccak256('name()')) ^ | |
* bytes4(keccak256('symbol()')) ^ | |
* bytes4(keccak256('tokenURI(uint256)')) | |
*/ | |
/** | |
* @dev Constructor function | |
*/ | |
constructor(string name, string symbol) public { | |
_name = name; | |
_symbol = symbol; | |
// register the supported interfaces to conform to ERC721 via ERC165 | |
_registerInterface(InterfaceId_ERC721Metadata); | |
} | |
/** | |
* @dev Gets the token name | |
* @return string representing the token name | |
*/ | |
function name() external view returns (string) { | |
return _name; | |
} | |
/** | |
* @dev Gets the token symbol | |
* @return string representing the token symbol | |
*/ | |
function symbol() external view returns (string) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns an URI for a given token ID | |
* Throws if the token ID does not exist. May return an empty string. | |
* @param tokenId uint256 ID of the token to query | |
*/ | |
function tokenURI(uint256 tokenId) external view returns (string) { | |
require(_exists(tokenId)); | |
return _tokenURIs[tokenId]; | |
} | |
/** | |
* @dev Internal function to set the token URI for a given token | |
* Reverts if the token ID does not exist | |
* @param tokenId uint256 ID of the token to set its URI | |
* @param uri string URI to assign | |
*/ | |
function _setTokenURI(uint256 tokenId, string uri) internal { | |
require(_exists(tokenId)); | |
_tokenURIs[tokenId] = uri; | |
} | |
/** | |
* @dev Internal function to burn a specific token | |
* Reverts if the token does not exist | |
* @param owner owner of the token to burn | |
* @param tokenId uint256 ID of the token being burned by the msg.sender | |
*/ | |
function _burn(address owner, uint256 tokenId) internal { | |
super._burn(owner, tokenId); | |
// Clear metadata (if any) | |
if (bytes(_tokenURIs[tokenId]).length != 0) { | |
delete _tokenURIs[tokenId]; | |
} | |
} | |
} | |
/** | |
* @title Roles | |
* @dev Library for managing addresses assigned to a Role. | |
*/ | |
library Roles { | |
struct Role { | |
mapping (address => bool) bearer; | |
} | |
/** | |
* @dev give an account access to this role | |
*/ | |
function add(Role storage role, address account) internal { | |
require(account != address(0)); | |
require(!has(role, account)); | |
role.bearer[account] = true; | |
} | |
/** | |
* @dev remove an account's access to this role | |
*/ | |
function remove(Role storage role, address account) internal { | |
require(account != address(0)); | |
require(has(role, account)); | |
role.bearer[account] = false; | |
} | |
/** | |
* @dev check if an account has this role | |
* @return bool | |
*/ | |
function has(Role storage role, address account) | |
internal | |
view | |
returns (bool) | |
{ | |
require(account != address(0)); | |
return role.bearer[account]; | |
} | |
} | |
contract MinterRole { | |
using Roles for Roles.Role; | |
event MinterAdded(address indexed account); | |
event MinterRemoved(address indexed account); | |
Roles.Role private minters; | |
constructor() internal { | |
_addMinter(msg.sender); | |
} | |
modifier onlyMinter() { | |
require(isMinter(msg.sender)); | |
_; | |
} | |
function isMinter(address account) public view returns (bool) { | |
return minters.has(account); | |
} | |
function addMinter(address account) public onlyMinter { | |
_addMinter(account); | |
} | |
function renounceMinter() public { | |
_removeMinter(msg.sender); | |
} | |
function _addMinter(address account) internal { | |
minters.add(account); | |
emit MinterAdded(account); | |
} | |
function _removeMinter(address account) internal { | |
minters.remove(account); | |
emit MinterRemoved(account); | |
} | |
} | |
/** | |
* @title ERC721MetadataMintable | |
* @dev ERC721 minting logic with metadata | |
*/ | |
contract ERC721MetadataMintable is ERC721, ERC721Metadata, MinterRole { | |
/** | |
* @dev Function to mint tokens | |
* @param to The address that will receive the minted tokens. | |
* @param tokenId The token id to mint. | |
* @param tokenURI The token URI of the minted token. | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function mintWithTokenURI( | |
address to, | |
uint256 tokenId, | |
string tokenURI | |
) | |
public | |
onlyMinter | |
returns (bool) | |
{ | |
_mint(to, tokenId); | |
_setTokenURI(tokenId, tokenURI); | |
return true; | |
} | |
} | |
/** | |
* @title Full ERC721 Token | |
* This implementation includes all the required and some optional functionality of the ERC721 standard | |
* Moreover, it includes approve all functionality using operator terminology | |
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract ERC721FullBatchMint is ERC721Enumerable, ERC721MetadataMintable { | |
string public constant version = "Mintable v0.5" ; | |
uint256 public MAX_MINT; | |
constructor(string name, string symbol, string url, uint256 batchMint, address owner) | |
ERC721Metadata(name, symbol) | |
public | |
{ | |
MAX_MINT = batchMint; | |
_mint(owner, 0); | |
_setTokenURI(0, url); | |
} | |
function batchMint (string url, uint256 count) | |
public onlyMinter | |
returns (bool) { | |
if (count > MAX_MINT || count <= 0 || count < 0) { | |
count = MAX_MINT; | |
} | |
uint256 totalSupply = super.totalSupply(); | |
for (uint256 i = 0; i < count; i++) { | |
mintWithTokenURI(msg.sender, totalSupply+i, url); | |
} | |
return true; | |
} | |
} | |
contract GSG_official{ | |
ERC721FullBatchMint token; | |
using SafeMath for uint256; | |
uint256 public currentId; | |
uint256 public registeredUsers; | |
address Owner; | |
struct userDataSet{ | |
uint256 claimedAmount; | |
uint256 timeFrame; | |
uint256 currentAmount; | |
uint256 timeForClaim; | |
bool isRegister; | |
} | |
mapping(address => userDataSet) public userMap; | |
mapping(uint256 => address) public userlist; | |
event TransferETH(address,uint256); | |
event UserRegistered(address); | |
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | |
// give token address of mainnet *the token you want to use in a contract* | |
constructor(address _tokenAddress) public { | |
token = ERC721FullBatchMint(address(_tokenAddress)); | |
Owner = msg.sender; | |
} | |
modifier onlyOwner() { | |
require(msg.sender == owner(),"ERROR: Only for owner"); | |
_; | |
} | |
function() external payable{ | |
} | |
//register user to contract so they can start earning ethers | |
function register() public { | |
require(token.balanceOf(msg.sender) > 0,"ERROR: Get GSG-Official token to register"); | |
require(msg.sender != address(0),"ERROR: zero address"); | |
require(userMap[msg.sender].isRegister == false,"ERROR: already registered"); | |
userDataSet memory userdata; | |
currentId++; | |
registeredUsers++; | |
userdata = userDataSet({ | |
claimedAmount: 0, | |
timeFrame: now + 4 weeks, | |
currentAmount: 0, | |
timeForClaim: now + 90 days, | |
isRegister: true | |
}); | |
userMap[msg.sender] = userdata; | |
userlist[currentId] = msg.sender; | |
emit UserRegistered(msg.sender); | |
} | |
function hasRegistered() public view returns(bool) { | |
return userMap[msg.sender].isRegister; | |
} | |
// user can claim one a month | |
//claim amount is calculated according to how much balance and ethers we have in a contract | |
function claim() public returns(bool){ | |
require(token.balanceOf(msg.sender) > 0,"ERROR: get some token to claim ether"); | |
require(msg.sender != address(0), "ERROR: zero address"); | |
require(userMap[msg.sender].isRegister,"ERROR: Registe YourSelf First"); | |
if(now >= userMap[msg.sender].timeForClaim) { | |
userMap[msg.sender].currentAmount = 0; | |
return true; | |
} | |
require(now >= userMap[msg.sender].timeFrame,"ERROR: cannot claim before a month"); | |
uint256 price = userMap[msg.sender].currentAmount; | |
address(msg.sender).transfer(price); | |
userMap[msg.sender].claimedAmount += price; | |
userMap[msg.sender].currentAmount -= price; | |
userMap[msg.sender].timeFrame = now + 4 weeks; | |
userMap[msg.sender].timeForClaim = now + 90 days; | |
emit TransferETH(msg.sender,price); | |
} | |
function calculatePriceETH() internal view returns(uint256) { | |
uint256 contractBal = address(this).balance; | |
uint256 balances1 = contractBal.mul(30).div(100); | |
uint256 balances = balances1.div(registeredUsers); | |
return balances; | |
} | |
function holdersBalance() public view returns(uint256) { | |
if(now >= userMap[msg.sender].timeFrame){ | |
return userMap[msg.sender].currentAmount; | |
}else{ | |
return 0; | |
} | |
} | |
function distributeETH() public onlyOwner { | |
uint256 id = currentId; | |
uint256 price = calculatePriceETH(); | |
for(uint256 i=1; i<=id; i++){ | |
userMap[userlist[i]].currentAmount += price; | |
} | |
} | |
function totalETH() public view returns(uint256) { | |
return address(this).balance; | |
} | |
function owner() public view returns(address){ | |
return Owner; | |
} | |
function transferOwnerShip(address _address) public onlyOwner { | |
emit OwnershipTransferred(owner(),_address); | |
Owner = _address; | |
} | |
function stopPool() public onlyOwner { | |
address(this).transfer(address(this).balance); | |
} | |
} |
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.6.0; | |
abstract contract Context { | |
function _msgSender() internal view virtual returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view virtual returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
contract Ownable is Context { | |
address private _owner; | |
event OwnershipTransferred(address indexed previousOwner, address indexed 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. | |
*/ | |
function owner() public view returns (address) { | |
return _owner; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(_owner == _msgSender(), "Ownable: caller is not the 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. | |
*/ | |
function renounceOwnership() public virtual onlyOwner { | |
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. | |
*/ | |
function transferOwnership(address newOwner) public virtual onlyOwner { | |
require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
emit OwnershipTransferred(_owner, newOwner); | |
_owner = newOwner; | |
} | |
} | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
contract Pausable is Context { | |
/** | |
* @dev Emitted when the pause is triggered by `account`. | |
*/ | |
event Paused(address account); | |
/** | |
* @dev Emitted when the pause is lifted by `account`. | |
*/ | |
event Unpaused(address account); | |
bool private _paused; | |
/** | |
* @dev Initializes the contract in unpaused state. | |
*/ | |
constructor () internal { | |
_paused = false; | |
} | |
/** | |
* @dev Returns true if the contract is paused, and false otherwise. | |
*/ | |
function paused() public view returns (bool) { | |
return _paused; | |
} | |
/** | |
* @dev Modifier to make a function callable only when the contract is not paused. | |
* | |
* Requirements: | |
* | |
* - The contract must not be paused. | |
*/ | |
modifier whenNotPaused() { | |
require(!_paused, "Pausable: paused"); | |
_; | |
} | |
/** | |
* @dev Modifier to make a function callable only when the contract is paused. | |
* | |
* Requirements: | |
* | |
* - The contract must be paused. | |
*/ | |
modifier whenPaused() { | |
require(_paused, "Pausable: not paused"); | |
_; | |
} | |
/** | |
* @dev Triggers stopped state. | |
* | |
* Requirements: | |
* | |
* - The contract must not be paused. | |
*/ | |
function _pause() internal virtual whenNotPaused { | |
_paused = true; | |
emit Paused(_msgSender()); | |
} | |
/** | |
* @dev Returns to normal state. | |
* | |
* Requirements: | |
* | |
* - The contract must be paused. | |
*/ | |
function _unpause() internal virtual whenPaused { | |
_paused = false; | |
emit Unpaused(_msgSender()); | |
} | |
} | |
library Address { | |
/** | |
* @dev Returns true if `account` is a contract. | |
* | |
* [IMPORTANT] | |
* ==== | |
* It is unsafe to assume that an address for which this function returns | |
* false is an externally-owned account (EOA) and not a contract. | |
* | |
* Among others, `isContract` will return false for the following | |
* types of addresses: | |
* | |
* - an externally-owned account | |
* - a contract in construction | |
* - an address where a contract will be created | |
* - an address where a contract lived, but was destroyed | |
* ==== | |
*/ | |
function isContract(address account) internal 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; | |
} | |
/** | |
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to | |
* `recipient`, forwarding all available gas and reverting on errors. | |
* | |
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost | |
* of certain opcodes, possibly making contracts go over the 2300 gas limit | |
* imposed by `transfer`, making them unable to receive funds via | |
* `transfer`. {sendValue} removes this limitation. | |
* | |
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. | |
* | |
* IMPORTANT: because control is transferred to `recipient`, care must be | |
* taken to not create reentrancy vulnerabilities. Consider using | |
* {ReentrancyGuard} or the | |
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. | |
*/ | |
function sendValue(address payable recipient, uint256 amount) internal { | |
require(address(this).balance >= amount, "Address: insufficient balance"); | |
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value | |
(bool success, ) = recipient.call{ value: amount }(""); | |
require(success, "Address: unable to send value, recipient may have reverted"); | |
} | |
/** | |
* @dev Performs a Solidity function call using a low level `call`. A | |
* plain`call` is an unsafe replacement for a function call: use this | |
* function instead. | |
* | |
* If `target` reverts with a revert reason, it is bubbled up by this | |
* function (like regular Solidity function calls). | |
* | |
* Returns the raw returned data. To convert to the expected return value, | |
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. | |
* | |
* Requirements: | |
* | |
* - `target` must be a contract. | |
* - calling `target` with `data` must not revert. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
return functionCall(target, data, "Address: low-level call failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with | |
* `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
return _functionCallWithValue(target, data, 0, errorMessage); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], | |
* but also transferring `value` wei to `target`. | |
* | |
* Requirements: | |
* | |
* - the calling contract must have an ETH balance of at least `value`. | |
* - the called Solidity function must be `payable`. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { | |
return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but | |
* with `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { | |
require(address(this).balance >= value, "Address: insufficient balance for call"); | |
return _functionCallWithValue(target, data, value, errorMessage); | |
} | |
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { | |
require(isContract(target), "Address: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data); | |
if (success) { | |
return returndata; | |
} else { | |
// Look for revert reason and bubble it up if present | |
if (returndata.length > 0) { | |
// The easiest way to bubble the revert reason is using memory via assembly | |
// solhint-disable-next-line no-inline-assembly | |
assembly { | |
let returndata_size := mload(returndata) | |
revert(add(32, returndata), returndata_size) | |
} | |
} else { | |
revert(errorMessage); | |
} | |
} | |
} | |
} | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint256; | |
using Address for address; | |
mapping (address => uint256) private _balances; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
uint256 private _totalSupply; | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
/** | |
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with | |
* a default value of 18. | |
* | |
* To select a different value for {decimals}, use {_setupDecimals}. | |
* | |
* All three of these values are immutable: they can only be set once during | |
* construction. | |
*/ | |
constructor (string memory name, string memory symbol) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = 18; | |
} | |
/** | |
* @dev Returns the name of the token. | |
*/ | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev Returns the symbol of the token, usually a shorter version of the | |
* name. | |
*/ | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns the number of decimals used to get its user representation. | |
* For example, if `decimals` equals `2`, a balance of `505` tokens should | |
* be displayed to a user as `5,05` (`505 / 10 ** 2`). | |
* | |
* Tokens usually opt for a value of 18, imitating the relationship between | |
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is | |
* called. | |
* | |
* NOTE: This information is only used for _display_ purposes: it in | |
* no way affects any of the arithmetic of the contract, including | |
* {IERC20-balanceOf} and {IERC20-transfer}. | |
*/ | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
/** | |
* @dev See {IERC20-totalSupply}. | |
*/ | |
function totalSupply() public view override returns (uint256) { | |
return _totalSupply; | |
} | |
/** | |
* @dev See {IERC20-balanceOf}. | |
*/ | |
function balanceOf(address account) public view override returns (uint256) { | |
return _balances[account]; | |
} | |
/** | |
* @dev See {IERC20-transfer}. | |
* | |
* Requirements: | |
* | |
* - `recipient` cannot be the zero address. | |
* - the caller must have a balance of at least `amount`. | |
*/ | |
function transfer(address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-allowance}. | |
*/ | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
/** | |
* @dev See {IERC20-approve}. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function approve(address spender, uint256 amount) public virtual override returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-transferFrom}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. This is not | |
* required by the EIP. See the note at the beginning of {ERC20}; | |
* | |
* Requirements: | |
* - `sender` and `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
* - the caller must have allowance for ``sender``'s tokens of at least | |
* `amount`. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/** | |
* @dev Atomically increases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
/** | |
* @dev Atomically decreases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
* - `spender` must have allowance for the caller of at least | |
* `subtractedValue`. | |
*/ | |
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* @dev Moves tokens `amount` from `sender` to `recipient`. | |
* | |
* This is internal function is equivalent to {transfer}, and can be used to | |
* e.g. implement automatic token fees, slashing mechanisms, etc. | |
* | |
* Emits a {Transfer} event. | |
* | |
* Requirements: | |
* | |
* - `sender` cannot be the zero address. | |
* - `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
*/ | |
function _transfer(address sender, address recipient, uint256 amount) internal virtual { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
require(recipient != address(0), "ERC20: transfer to the zero address"); | |
_beforeTokenTransfer(sender, recipient, amount); | |
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
/** @dev Creates `amount` tokens and assigns them to `account`, increasing | |
* the total supply. | |
* | |
* Emits a {Transfer} event with `from` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `to` cannot be the zero address. | |
*/ | |
function _mint(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: mint to the zero address"); | |
_beforeTokenTransfer(address(0), account, amount); | |
_totalSupply = _totalSupply.add(amount); | |
_balances[account] = _balances[account].add(amount); | |
emit Transfer(address(0), account, amount); | |
} | |
/** | |
* @dev Destroys `amount` tokens from `account`, reducing the | |
* total supply. | |
* | |
* Emits a {Transfer} event with `to` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `account` cannot be the zero address. | |
* - `account` must have at least `amount` tokens. | |
*/ | |
function _burn(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: burn from the zero address"); | |
_beforeTokenTransfer(account, address(0), amount); | |
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); | |
_totalSupply = _totalSupply.sub(amount); | |
emit Transfer(account, address(0), amount); | |
} | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. | |
* | |
* This is internal function is equivalent to `approve`, and can be used to | |
* e.g. set automatic allowances for certain subsystems, etc. | |
* | |
* Emits an {Approval} event. | |
* | |
* Requirements: | |
* | |
* - `owner` cannot be the zero address. | |
* - `spender` cannot be the zero address. | |
*/ | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* @dev Sets {decimals} to a value other than the default one of 18. | |
* | |
* WARNING: This function should only be called from the constructor. Most | |
* applications that interact with token contracts will not expect | |
* {decimals} to ever change, and may work incorrectly if it does. | |
*/ | |
function _setupDecimals(uint8 decimals_) internal { | |
_decimals = decimals_; | |
} | |
/** | |
* @dev Hook that is called before any transfer of tokens. This includes | |
* minting and burning. | |
* | |
* Calling conditions: | |
* | |
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens | |
* will be to transferred to `to`. | |
* - when `from` is zero, `amount` tokens will be minted for `to`. | |
* - when `to` is zero, `amount` of ``from``'s tokens will be burned. | |
* - `from` and `to` are never both zero. | |
* | |
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } | |
} | |
abstract contract ERC20Pausable is ERC20, Pausable { | |
/** | |
* @dev See {ERC20-_beforeTokenTransfer}. | |
* | |
* Requirements: | |
* | |
* - the contract must not be paused. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override { | |
super._beforeTokenTransfer(from, to, amount); | |
require(!paused(), "ERC20Pausable: token transfer while paused"); | |
} | |
} | |
interface FiatContract { | |
function ETH(uint _id) external pure returns (uint256); | |
function USD(uint _id) external pure returns (uint256); | |
function EUR(uint _id) external pure returns (uint256); | |
function GBP(uint _id) external pure returns (uint256); | |
function updatedAt(uint _id) external pure returns (uint); | |
} | |
contract STRESHI is ERC20Pausable,Ownable{ | |
FiatContract public price; | |
address public fiatContractAddress; | |
constructor() ERC20("STRESHI","STR") Ownable() public { | |
setFiatContractAddress(0x97d63Fe27cA359422C10b25206346B9e24A676Ca); | |
price = FiatContract(fiatContractAddress); | |
_setupDecimals(10); | |
_mint(msg.sender, 1000000*10**uint256(decimals()) ); | |
} | |
modifier capped() { | |
require(totalSupply() < 10000000000*10**uint256(decimals()),"ERROR: cannot mint more than capped "); | |
_; | |
} | |
function geETHforUSD() public view returns (uint256) { | |
uint256 usd = price.USD(0); | |
uint256 weiAmount = usd *2; //0.02 USD amount of wei return | |
return weiAmount; | |
} | |
function setFiatContractAddress(address _add) public onlyOwner{ | |
require(_add != address(0),"Invalid Address! Please add correct FiatContract Addresss"); | |
//fiatContractAddress = 0x2138FfE292fd0953f7fe2569111246E4DE9ff1DC) // MAINNET ADDRESS | |
fiatContractAddress = _add; // TESTNET ADDRESS | |
} | |
function mintToken(address _addres,uint256 _amount) public onlyOwner() { | |
_mint(_addres,_amount*10**uint256(decimals())); | |
} | |
fallback () payable external{ | |
buy(); | |
} | |
receive() payable external { | |
buy(); | |
} | |
function buy() payable capped() public{ | |
// require(msg.value > 0 ether,"POH: No value transfered"); | |
uint256 weiUSD = geETHforUSD(); | |
require(weiUSD != 0, "POH: No exchange value returned. Try again"); | |
//calculating amount of POH Token to be minted. | |
uint256 unitPrice = msg.value.div(weiUSD); | |
uint256 amountOfPOHTokens = (10**uint256(decimals())) * unitPrice; //1 POH token * USD amount of Value | |
_mint(msg.sender,amountOfPOHTokens); | |
} | |
function withdrawEther() public onlyOwner() { | |
payable(address(owner())).transfer(address(this).balance); | |
} | |
} |
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.6.12; | |
interface IERC20 { | |
function totalSupply() external view returns (uint); | |
function balanceOf(address account) external view returns (uint); | |
function transfer(address recipient, uint amount) external returns (bool); | |
function allowance(address owner, address spender) external view returns (uint); | |
function approve(address spender, uint amount) external returns (bool); | |
function transferFrom(address sender, address recipient, uint amount) external returns (bool); | |
event Transfer(address indexed from, address indexed to, uint value); | |
event Approval(address indexed owner, address indexed spender, uint value); | |
} | |
interface FiatContract { | |
function ETH(uint _id) external pure returns (uint256); | |
function USD(uint _id) external pure returns (uint256); | |
function EUR(uint _id) external pure returns (uint256); | |
function GBP(uint _id) external pure returns (uint256); | |
function updatedAt(uint _id) external pure returns (uint); | |
} | |
library SafeMath { | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
return sub(a, b, "SafeMath: subtraction overflow"); | |
} | |
function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
require(b <= a, errorMessage); | |
uint c = a - b; | |
return c; | |
} | |
function mul(uint a, uint b) internal pure returns (uint) { | |
if (a == 0) { | |
return 0; | |
} | |
uint c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
return div(a, b, "SafeMath: division by zero"); | |
} | |
function div(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
// Solidity only automatically asserts when dividing by 0 | |
require(b > 0, errorMessage); | |
uint c = a / b; | |
return c; | |
} | |
} | |
contract CrowedSale{ | |
IERC20 token; | |
address owner; | |
FiatContract price; | |
address public fiatContractAddress; | |
using SafeMath for uint256; | |
constructor() public { | |
// token = IERC20(address(0xe3cB92Fab39f4bF4D0E15591Bf4366Ce377Dc0DF)); | |
token = IERC20(address(0x76F420c18d284Dca44999ae7461f918F847F137f)); | |
owner = msg.sender; | |
setFiatContractAddress(0x2138FfE292fd0953f7fe2569111246E4DE9ff1DC); | |
price = FiatContract(fiatContractAddress); | |
} | |
modifier onlyOwner(){ | |
require(owner == msg.sender,'ERROR: Only Owner Can Run this'); | |
_; | |
} | |
receive() payable external{ | |
buy(); | |
} | |
fallback() external{ | |
buy(); | |
} | |
function buy() payable public{ | |
require(msg.value != 0,"POH: No value transfered"); | |
uint256 weiUSD = geETHforUSD(); | |
require(weiUSD != 0, "POH: No exchange value returned. Try again"); | |
//calculating amount of POH Token to be minted. | |
uint256 unitPrice = msg.value.div(weiUSD); | |
uint256 amountOfPOHTokens = (10**uint256(18) * unitPrice); //1 WYO token * USD amount of Value | |
token.transferFrom(owner,msg.sender,amountOfPOHTokens); | |
} | |
function getEthAgainstToken(uint256 tokens) public view returns(uint256){ | |
uint256 amountOfToken = tokens*10**uint256(18); | |
uint256 weiUSD = geETHforUSD(); | |
return (amountOfToken*weiUSD)/1e18; | |
} | |
function geETHforUSD() public view returns (uint256) { | |
uint256 usd = price.USD(0); | |
uint256 weiAmount = usd * 100; //1 USD amount of wei return | |
return weiAmount; | |
} | |
function setFiatContractAddress(address _add) public onlyOwner{ | |
require(_add != address(0),"Invalid Address! Please add correct FiatContract Addresss"); | |
fiatContractAddress = _add; // MAINNET ADDRESS | |
// fiatContractAddress = 0x97d63Fe27cA359422C10b25206346B9e24A676Ca; // TESTNET ADDRESS | |
} | |
function checkAllowance() public view returns(uint256){ | |
return token.allowance(owner,address(this)); | |
} | |
function end_ICO() public onlyOwner() { | |
payable(address(owner)).transfer(address(this).balance); | |
} | |
} |
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.6.12; | |
interface IERC20 { | |
function totalSupply() external view returns (uint); | |
function balanceOf(address account) external view returns (uint); | |
function transfer(address recipient, uint amount) external returns (bool); | |
function allowance(address owner, address spender) external view returns (uint); | |
function approve(address spender, uint amount) external returns (bool); | |
function transferFrom(address sender, address recipient, uint amount) external returns (bool); | |
event Transfer(address indexed from, address indexed to, uint value); | |
event Approval(address indexed owner, address indexed spender, uint value); | |
} | |
interface FiatContract { | |
function ETH(uint _id) external pure returns (uint256); | |
function USD(uint _id) external pure returns (uint256); | |
function EUR(uint _id) external pure returns (uint256); | |
function GBP(uint _id) external pure returns (uint256); | |
function updatedAt(uint _id) external pure returns (uint); | |
} | |
library SafeMath { | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
return sub(a, b, "SafeMath: subtraction overflow"); | |
} | |
function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
require(b <= a, errorMessage); | |
uint c = a - b; | |
return c; | |
} | |
function mul(uint a, uint b) internal pure returns (uint) { | |
if (a == 0) { | |
return 0; | |
} | |
uint c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
return div(a, b, "SafeMath: division by zero"); | |
} | |
function div(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
// Solidity only automatically asserts when dividing by 0 | |
require(b > 0, errorMessage); | |
uint c = a / b; | |
return c; | |
} | |
} | |
contract CrowedSale{ | |
IERC20 token; | |
address owner; | |
FiatContract price; | |
address public fiatContractAddress; | |
using SafeMath for uint256; | |
constructor() public { | |
// token = IERC20(address(0xe3cB92Fab39f4bF4D0E15591Bf4366Ce377Dc0DF)); | |
token = IERC20(address(0x76F420c18d284Dca44999ae7461f918F847F137f)); | |
owner = msg.sender; | |
setFiatContractAddress(0x2138FfE292fd0953f7fe2569111246E4DE9ff1DC); | |
price = FiatContract(fiatContractAddress); | |
} | |
modifier onlyOwner(){ | |
require(owner == msg.sender,'ERROR: Only Owner Can Run this'); | |
_; | |
} | |
receive() payable external{ | |
buy(); | |
} | |
fallback() external{ | |
buy(); | |
} | |
function buy() payable public{ | |
require(msg.value != 0,"POH: No value transfered"); | |
uint256 weiUSD = geETHforUSD(); | |
require(weiUSD != 0, "POH: No exchange value returned. Try again"); | |
//calculating amount of POH Token to be minted. | |
uint256 unitPrice = msg.value.div(weiUSD); | |
uint256 amountOfPOHTokens = (10**uint256(18) * unitPrice); //1 WYO token * USD amount of Value | |
token.transferFrom(owner,msg.sender,amountOfPOHTokens); | |
} | |
function getEthAgainstToken(uint256 tokens) public view returns(uint256){ | |
uint256 amountOfToken = tokens*10**uint256(18); | |
uint256 weiUSD = geETHforUSD(); | |
return (amountOfToken*weiUSD)/1e18; | |
} | |
function geETHforUSD() public view returns (uint256) { | |
uint256 usd = price.USD(0); | |
uint256 weiAmount = usd * 100; //1 USD amount of wei return | |
return weiAmount; | |
} | |
function setFiatContractAddress(address _add) public onlyOwner{ | |
require(_add != address(0),"Invalid Address! Please add correct FiatContract Addresss"); | |
fiatContractAddress = _add; // MAINNET ADDRESS | |
// fiatContractAddress = 0x97d63Fe27cA359422C10b25206346B9e24A676Ca; // TESTNET ADDRESS | |
} | |
function checkAllowance() public view returns(uint256){ | |
return token.allowance(owner,address(this)); | |
} | |
function end_ICO() public onlyOwner() { | |
payable(address(owner)).transfer(address(this).balance); | |
} | |
} |
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
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Interface of the ERC20 standard as defined in the EIP. | |
*/ | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} |
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.7.0; | |
interface IERC20 { | |
function totalSupply() external view returns (uint); | |
function balanceOf(address account) external view returns (uint); | |
function transfer(address recipient, uint amount) external returns (bool); | |
function allowance(address owner, address spender) external view returns (uint); | |
function approve(address spender, uint amount) external returns (bool); | |
function transferFrom(address sender, address recipient, uint amount) external returns (bool); | |
event Transfer(address indexed from, address indexed to, uint value); | |
event Approval(address indexed owner, address indexed spender, uint value); | |
} | |
contract Oracle{ | |
address admin; | |
uint private randum; | |
address contractAddress; | |
constructor() { | |
admin = msg.sender; | |
} | |
function addContractAddress(address add) public { | |
require(msg.sender == admin,'ERROR: only admin can change value'); | |
contractAddress = add; | |
} | |
function rand() public view returns(uint256) { | |
require(msg.sender == contractAddress,'only contract can access value'); | |
return randum; | |
} | |
function feedRandomness(uint256 _rand) public{ | |
require(msg.sender == admin,'ERROR: only admin can change value'); | |
randum = _rand; | |
} | |
} | |
contract lotteryGsG{ | |
using SafeMath for uint256; | |
IERC20 token; | |
Oracle oracle; | |
struct pick3UserData{ | |
uint256 id; | |
uint8 lotteryCount; | |
uint256[] tickets; | |
bool isExist; | |
} | |
struct pick4UserData{ | |
uint256 id; | |
uint8 lotteryCount; | |
uint256[] tickets; | |
bool isExist; | |
} | |
uint256 public currentIdForPick3; | |
uint256 public currentIdForPick4; | |
uint256 public pick3Pot; | |
uint256 public pick4Pot; | |
uint256 public pick3Price; | |
uint256 public pick4Price; | |
uint256 public maxNoOfLottery; | |
uint256 private nonce; | |
uint256 public drawingLimitForPick3; | |
uint256 public drawingLimitForPick4; | |
address public _tokenAddress; | |
address admin; | |
address dev1; | |
address dev2; | |
address dev3; | |
address dev4; | |
address uniSwapLiqPool; | |
address[] pick3Winners; | |
address[] pick4Winners; | |
mapping(address => pick3UserData) public pick3User; | |
mapping(uint256 => address) public pick3UserList; | |
mapping(address => pick4UserData) public pick4User; | |
mapping(uint256 => address) public pick4UserList; | |
mapping(address => uint256) public winningWallets; | |
event Pick3LotteryBought(address indexed UserAddress,uint256[] UserPickNumber,uint256 AmountOfGsGToken,uint256 time); | |
event Pick4LotteryBought(address indexed UserAddress,uint256[] UserPickNumber,uint256 AmountOfGsGToken,uint256 time); | |
event Pick3Winner(address indexed winner,uint256 number,uint256 amount,uint256 time); | |
event Pick4Winner(address indexed winner,uint256 number,uint256 amount,uint256 time); | |
event manualWinnerPick3(address indexed winner,uint256 amount,uint256 time); | |
event manualWinnerPick4(address indexed winner,uint256 amount,uint256 time); | |
event DeveloperIncentive(address indexed developer,uint256 amount,uint256 time); | |
event UniswapPool(address indexed uniswapAdd,uint256 amount,uint256 time); | |
event Random(address indexed Address,uint256 number,uint256 pick,uint256 time); | |
event RadeemwinningAmount(address indexed winner,uint256 amount); | |
constructor() { | |
//0x9CfA8a0Cb18F725DDdC3Fd86956925FC9127b776; | |
//Rinkeby: 0xF8f1de38E298Cf9Ce5eE1855369689E83f6BE467 | |
_tokenAddress = 0xF8f1de38E298Cf9Ce5eE1855369689E83f6BE467; | |
token = IERC20(_tokenAddress); | |
//Rinkeby 0xD1df9DEa9081276c3220553718Abd2428C9D3cd2 | |
//0xc36314Cd072B838E2C0D3C19349dae33962d9c73 | |
oracle = Oracle(0xD1df9DEa9081276c3220553718Abd2428C9D3cd2); | |
admin = msg.sender; | |
pick3Price = 5*10**18; | |
pick4Price = 15*10**18; | |
dev1 = 0x7cF196415CDD1eF08ca2358a8282D33Ba089B9f3; | |
dev2 = 0x7cF196415CDD1eF08ca2358a8282D33Ba089B9f3; | |
dev3 = 0x7cF196415CDD1eF08ca2358a8282D33Ba089B9f3; | |
uniSwapLiqPool = 0x7cF196415CDD1eF08ca2358a8282D33Ba089B9f3; | |
dev4 = 0x7cF196415CDD1eF08ca2358a8282D33Ba089B9f3; | |
maxNoOfLottery = 5; | |
} | |
modifier onlyAdmin() { | |
require(admin == msg.sender,'ERROR: only admin has rigth'); | |
_; | |
} | |
function buyLotteryForPick3(uint256[] memory your_pick_number,uint256 amount)public { | |
require(msg.sender != address(0), 'ERROR: zero address'); | |
require(token.balanceOf(msg.sender) >= pick3Price,"ERROR: Not Enough Balance"); | |
require(amount >= pick3Price*your_pick_number.length,'ERROR: not minimum investment'); | |
require(your_pick_number.length <= 5,'ERROR: Cannot buy more than 3 lottery tickets at a time'); | |
require(pick3User[msg.sender].lotteryCount <= 20,'ERROR: your lottery buy limit has exceeded'); | |
require(token.allowance(msg.sender,address(this)) >= amount,'ERROR: Approve token for this contract'); | |
if(!pick3User[msg.sender].isExist) { | |
pick3UserData memory userStruct; | |
userStruct = pick3UserData({ | |
id: currentIdForPick3, | |
lotteryCount: pick3User[msg.sender].lotteryCount, | |
tickets: pick3User[msg.sender].tickets, | |
isExist: true | |
}); | |
pick3User[msg.sender] = userStruct; | |
pick3UserList[currentIdForPick3] = msg.sender; | |
currentIdForPick3++; | |
} | |
token.transferFrom(msg.sender,address(this), amount); | |
developerIncentive(amount.mul(1).div(100),amount.mul(2).div(100)); | |
amount -= amount.mul(6).div(100); | |
pick3Pot += amount; | |
for(uint256 i=0; i<your_pick_number.length; i++){ | |
require(your_pick_number[i] <= 999,'ERROR: minium number for pick 3 should be < 10'); | |
pick3User[msg.sender].tickets.push(your_pick_number[i]); | |
pick3User[msg.sender].lotteryCount++; | |
} | |
if(currentIdForPick3 > maxNoOfLottery) { | |
drawingForPick3(999); | |
} | |
emit Pick3LotteryBought(msg.sender,your_pick_number,amount,block.timestamp); | |
} | |
function buyLotteryForPick4(uint256[] memory your_pick_number,uint256 amount)public { | |
require(msg.sender != address(0), 'ERROR: zero address'); | |
require(token.balanceOf(msg.sender) >= pick4Price,"ERROR: Not Enough Balance"); | |
require(amount >= your_pick_number.length*pick4Price,'ERROR: not minimum investment'); | |
require(your_pick_number.length <= 5,'ERROR: cannot buy more 5 ticket at once'); | |
require(pick4User[msg.sender].lotteryCount <= 20,'ERROR: Cannot buy Lottery moreThan 20 times'); | |
require(token.allowance(msg.sender,address(this)) >= amount,'ERROR: Approve token for this contract'); | |
if(!pick4User[msg.sender].isExist) { | |
pick4UserData memory userStruct; | |
//add users data | |
userStruct = pick4UserData({ | |
id: currentIdForPick4, | |
lotteryCount: pick4User[msg.sender].lotteryCount, | |
tickets: pick4User[msg.sender].tickets, | |
isExist: true | |
}); | |
pick4User[msg.sender] = userStruct; | |
pick4UserList[currentIdForPick4] = msg.sender; | |
currentIdForPick4++; | |
} | |
token.transferFrom(msg.sender,address(this), amount); | |
developerIncentive(amount.mul(1).div(100),amount.mul(2).div(100)); | |
amount -= amount.mul(6).div(100); | |
pick4Pot += amount; | |
for(uint256 i=0; i<your_pick_number.length; i++){ | |
require(your_pick_number[i] <= 9999,'ERROR: minium number for pick 5 should be < 9999'); | |
pick4User[msg.sender].tickets.push(your_pick_number[i]); | |
pick4User[msg.sender].lotteryCount++; | |
} | |
if(currentIdForPick4 > maxNoOfLottery) { | |
drawingForPick4(9999); | |
} | |
emit Pick4LotteryBought(msg.sender,your_pick_number,amount,block.timestamp); | |
} | |
function radeemYourWiningAmount() public { | |
uint256 amount = winningWallets[msg.sender]; | |
require(amount > 0,'ERROR: not enough balance'); | |
token.transfer(msg.sender,amount); | |
winningWallets[msg.sender] = 0; | |
emit RadeemwinningAmount(msg.sender,amount); | |
} | |
/* ADMIN FUNCTIONS */ | |
function changePick3Price(uint256 newPrice) public onlyAdmin { | |
pick3Price = newPrice; | |
} | |
function changePick4Price(uint256 newPrice) public onlyAdmin{ | |
pick4Price = newPrice; | |
} | |
function changeNoOfLottery(uint256 newLimit) external onlyAdmin{ | |
maxNoOfLottery = newLimit; | |
} | |
function uniSwapLiqPoolAdd(address add) external onlyAdmin{ | |
uniSwapLiqPool = add; | |
} | |
function addNewToken(address _address) external onlyAdmin{ | |
_tokenAddress = _address; | |
token = IERC20(_tokenAddress); | |
} | |
/* INTERNAL FUNCTIONS */ | |
function drawingForPick3(uint256 mod) internal returns(bool){ | |
uint256 amountForEveryUser; | |
uint256 randNum = random(mod,3); | |
if(drawingLimitForPick3 >= 2){ | |
manualDrawForPick3(); | |
return false; | |
} | |
for(uint8 i=0; i< maxNoOfLottery; i++){ | |
if(includes(getUserLotteryNumber(pick3UserList[i],3), randNum)){ | |
pick3Winners.push(pick3UserList[i]); | |
} | |
delete pick3User[pick3UserList[i]]; | |
delete pick3UserList[i]; | |
} | |
if(pick3Winners.length >= 1) { | |
amountForEveryUser = pick3Pot.div(pick3Winners.length); | |
for(uint8 i=0; i<pick3Winners.length; i++){ | |
winningWallets[pick3Winners[i]] += amountForEveryUser; | |
emit Pick3Winner(pick3Winners[i],randNum,amountForEveryUser,block.timestamp); | |
} | |
drawingLimitForPick3 = 0; | |
} | |
drawingLimitForPick3++; | |
pick3UserList[0] = pick3UserList[currentIdForPick3 - 1]; | |
// pick3User[pick3UserList[]] | |
currentIdForPick3 = 1; | |
delete pick3Winners; | |
return true; | |
} | |
function drawingForPick4(uint256 mod) internal returns(bool){ | |
uint256 amountForEveryUser; | |
uint256 randNum = random(mod,4); | |
if(drawingLimitForPick4 >= 2){ | |
manualDrawForPick4(); | |
return false; | |
} | |
for(uint i=0; i< maxNoOfLottery; i++){ | |
if(includes(getUserLotteryNumber(pick4UserList[i],4), randNum)){ | |
pick4Winners.push(pick4UserList[i]); | |
} | |
delete pick4User[pick4UserList[i]]; | |
delete pick4UserList[i]; | |
} | |
if(pick4Winners.length >= 1) { | |
amountForEveryUser = pick4Pot.div(pick4Winners.length); | |
for(uint8 i=0; i<pick4Winners.length; i++){ | |
winningWallets[pick4Winners[i]] += amountForEveryUser; | |
emit Pick4Winner(pick4Winners[i],randNum,amountForEveryUser,block.timestamp); | |
} | |
drawingLimitForPick4 = 0; | |
} | |
drawingLimitForPick4++; | |
pick4UserList[0] = pick4UserList[currentIdForPick4 - 1]; | |
currentIdForPick4 = 1; | |
delete pick4Winners; | |
return true; | |
} | |
function manualDrawForPick3() internal { | |
address winner1 = pick3UserList[random(maxNoOfLottery,3)]; | |
address winner2 = pick3UserList[random(maxNoOfLottery,3)]; | |
address winner3 = pick3UserList[random(maxNoOfLottery,3)]; | |
address winner4 = pick3UserList[random(maxNoOfLottery,3)]; | |
address winner5 = pick3UserList[random(maxNoOfLottery,3)]; | |
developerIncentive(pick3Pot.mul(1).div(100),pick3Pot.mul(10).div(100)); | |
pick3Pot = pick3Pot - pick3Pot.mul(14).div(100); | |
uint256 amountForEveryUser = pick3Pot.div(5); | |
deleteAllUsersData(3); | |
pick3Pot = 0; | |
drawingLimitForPick3 = 0; | |
pick3UserList[0] = pick3UserList[currentIdForPick3 - 1]; | |
currentIdForPick3 = 1; | |
winningWallets[winner1] += amountForEveryUser; | |
emit manualWinnerPick3(winner1,amountForEveryUser,block.timestamp); | |
winningWallets[winner2] += amountForEveryUser; | |
emit manualWinnerPick3(winner2,amountForEveryUser,block.timestamp); | |
winningWallets[winner3] += amountForEveryUser; | |
emit manualWinnerPick3(winner3,amountForEveryUser,block.timestamp); | |
winningWallets[winner4] += amountForEveryUser; | |
emit manualWinnerPick3(winner4,amountForEveryUser,block.timestamp); | |
winningWallets[winner5] += amountForEveryUser; | |
emit manualWinnerPick3(winner5,amountForEveryUser,block.timestamp); | |
} | |
function manualDrawForPick4() internal { | |
address winner1 = pick4UserList[random(maxNoOfLottery,4)]; | |
address winner2 = pick4UserList[random(maxNoOfLottery,4)]; | |
address winner3 = pick4UserList[random(maxNoOfLottery,4)]; | |
address winner4 = pick4UserList[random(maxNoOfLottery,4)]; | |
address winner5 = pick4UserList[random(maxNoOfLottery,4)]; | |
developerIncentive(pick4Pot.mul(1).div(100),pick4Pot.mul(10).div(100)); | |
pick4Pot = pick4Pot - pick4Pot.mul(14).div(100); | |
uint256 amountForEveryUser = pick4Pot.div(5); | |
deleteAllUsersData(4); | |
pick4Pot = 0; | |
drawingLimitForPick4 = 0; | |
pick4UserList[0] = pick4UserList[currentIdForPick4 - 1]; | |
currentIdForPick4 = 1; | |
winningWallets[winner1] += amountForEveryUser; | |
emit manualWinnerPick4(winner1,amountForEveryUser,block.timestamp); | |
winningWallets[winner2] += amountForEveryUser; | |
emit manualWinnerPick4(winner2,amountForEveryUser,block.timestamp); | |
winningWallets[winner3] += amountForEveryUser; | |
emit manualWinnerPick4(winner3,amountForEveryUser,block.timestamp); | |
winningWallets[winner4] += amountForEveryUser; | |
emit manualWinnerPick4(winner4,amountForEveryUser,block.timestamp); | |
winningWallets[winner5] += amountForEveryUser; | |
emit manualWinnerPick4(winner5,amountForEveryUser,block.timestamp); | |
} | |
function getUserLotteryNumber(address userAdddress,uint8 your_pick) public view returns(uint256[] memory tickets){ | |
if(your_pick == 3) { | |
return pick3User[userAdddress].tickets; | |
} else if(your_pick == 4) { | |
return pick4User[userAdddress].tickets; | |
} | |
} | |
function deleteAllUsersData(uint256 pick) internal { | |
if(pick == 3){ | |
for(uint256 i=0; i<=maxNoOfLottery; i++){ | |
delete pick3User[pick3UserList[i]]; | |
delete pick3UserList[i]; | |
} | |
}else if(pick == 4){ | |
for(uint256 i=0; i<=maxNoOfLottery; i++){ | |
delete pick4User[pick4UserList[i]]; | |
delete pick4UserList[i]; | |
} | |
} | |
} | |
function developerIncentive(uint256 amount,uint256 uniSwapLiqAmount) internal { | |
token.transfer(uniSwapLiqPool,uniSwapLiqAmount); | |
emit UniswapPool(uniSwapLiqPool,uniSwapLiqAmount,block.timestamp); | |
token.transfer(dev1,amount); | |
emit DeveloperIncentive(dev1,amount,block.timestamp); | |
token.transfer(dev2,amount); | |
emit DeveloperIncentive(dev2,amount,block.timestamp); | |
token.transfer(dev3,amount); | |
emit DeveloperIncentive(dev3,amount,block.timestamp); | |
token.transfer(dev4,amount); | |
emit DeveloperIncentive(dev4,amount,block.timestamp); | |
} | |
/* GETTER FUNCTIONS */ | |
function includes(uint256[] memory array,uint256 randomNumber) internal pure returns(bool){ | |
bool isTrue = false; | |
for(uint8 i=0; i<array.length; i++){ | |
if(array[i] == randomNumber){ | |
isTrue = true; | |
} | |
} | |
return isTrue; | |
} | |
function random(uint256 mod,uint256 pick) internal returns (uint256) { | |
uint256 rand = uint256(keccak256(abi.encodePacked( | |
oracle.rand(), | |
nonce, | |
block.timestamp, | |
block.difficulty, | |
msg.sender | |
))) % mod; | |
nonce++; | |
emit Random(msg.sender,rand,pick,block.timestamp); | |
return rand; | |
} | |
} | |
library SafeMath { | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
return sub(a, b, "SafeMath: subtraction overflow"); | |
} | |
function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
require(b <= a, errorMessage); | |
uint c = a - b; | |
return c; | |
} | |
function mul(uint a, uint b) internal pure returns (uint) { | |
if (a == 0) { | |
return 0; | |
} | |
uint c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
return div(a, b, "SafeMath: division by zero"); | |
} | |
function div(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
// Solidity only automatically asserts when dividing by 0 | |
require(b > 0, errorMessage); | |
uint c = a / b; | |
return c; | |
} | |
} |
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.8.0; | |
contract mqtt{ | |
event log(address _address); | |
function test() public { | |
emit log(msg.sender); | |
} | |
} | |
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.6.0; | |
import "ERC20.sol"; | |
// SPDX-License-Identifier: UNLICENSED | |
contract multisender { | |
address payable owner; | |
uint256 arrayOfLimit; | |
uint256 fee; | |
bool initializ=false; | |
event claimedBalance(uint256); | |
event getBal(string,uint256); | |
modifier hasFee() { | |
if (fees() > 0) { | |
require(msg.value >= fees()); | |
} | |
_; | |
} | |
modifier onlyOwner(){ | |
require(msg.sender==owner); | |
_; | |
} | |
function initialized() public view returns (bool) { | |
return initializ; | |
} | |
function arrayLimit() public view returns(uint256) { | |
return arrayOfLimit; | |
} | |
function setArrayLimit(uint256 _newLimit) public onlyOwner { | |
require(_newLimit != 0); | |
arrayOfLimit = _newLimit; | |
} | |
function setFee(uint256 _newStep) public onlyOwner { | |
require(_newStep != 0); | |
fee = _newStep; | |
} | |
function fees() public view returns(uint256) { | |
return fee; | |
} | |
function initialize(address payable _owner) public { | |
require(!initialized()); | |
owner = _owner; | |
setArrayLimit(200); | |
//setDiscountStep(0.00005 ether); | |
setFee(0.05 ether); | |
initializ = true; | |
} | |
ERC20 token; | |
function multiSend(address _tokenAddr, address[] memory dests, uint256[] memory values) public returns (uint256) { | |
uint256 i = 0; uint256 amount=0; | |
for(uint8 j= 0; j<values.length; j++){ | |
amount += values[j]; | |
} | |
token = ERC20(_tokenAddr); | |
// token.approve(address(this),amount); | |
require(token.allowance(msg.sender, address(this)) > 0,"ERROR: NOT ENOUGH allowance"); | |
while (i < dests.length) { | |
token.transferFrom(msg.sender,dests[i], values[i] * (10 ** 18)); | |
i += 1; | |
} | |
return(i); | |
} | |
function checkAllowance(address _ad1, address _ad2) public view returns(uint256){ | |
return token.allowance(_ad1,_ad2); | |
} | |
function getBalanceOfContract()public { | |
uint256 a = address(this).balance; | |
emit getBal("your balance is : ",a); | |
} | |
function claimBalance() onlyOwner public { | |
uint256 a = address(this).balance; | |
owner.transfer(a); | |
emit claimedBalance(a); | |
} | |
} |
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.5.8; | |
/** | |
* @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. | |
*/ | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
require(b <= a, "SafeMath: subtraction overflow"); | |
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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
// Solidity only automatically asserts when dividing by 0 | |
require(b > 0, "SafeMath: division by zero"); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (uint256) { | |
require(b != 0, "SafeMath: modulo by zero"); | |
return a % b; | |
} | |
} | |
/** | |
* @dev Interface of the TRC20 standard as defined in the EIP. Does not include | |
* the optional functions; to access them see {TRC20Detailed}. | |
*/ | |
contract token_PreSale { | |
using SafeMath for uint256; | |
address payable private owner; | |
address payable seller; | |
// Starting time of contract | |
uint256 public startsAt = 0; | |
// Ending time of contract | |
uint256 public runPeriod = 4 days; | |
bool public initialized = false; | |
struct poolStr { | |
uint price; | |
uint startTime; | |
uint runTime; | |
uint tokensSold; | |
} | |
uint256 public noOfPool = 0; | |
mapping (uint => poolStr) public pool; | |
struct userStr { | |
bool isExist; | |
uint id; | |
uint referrerID; | |
uint token; | |
} | |
uint256 public noOfBuyer = 0; | |
mapping (address => userStr) public buyer; | |
mapping (uint => address) private referral_Id; | |
// Pool hardcap | |
uint256 private poolHardcap = 1e12; | |
// the number of trx raised through this contract | |
uint256 public trxRaised = 0; | |
// Total tokens sold | |
uint256 public tokensSold = 0; | |
// Buy event | |
event Buy(uint256 _trxAmount, uint256 _tokenAmount); | |
function initialize(address _token, address payable _seller, uint256 time) public returns (bool) { | |
require(!initialized, "already initialized"); | |
initialized = true; | |
startsAt = time; | |
seller = _seller; | |
poolStr memory poolInfo; | |
poolInfo = poolStr({ | |
price : 1, | |
startTime: startsAt, | |
runTime: 1 days, | |
tokensSold: 0 | |
}); | |
noOfPool++; | |
pool[noOfPool] = poolInfo; | |
poolInfo.price = 2; | |
poolInfo.startTime += 1 days; | |
poolInfo.runTime = 2 days; | |
noOfPool++; | |
pool[noOfPool] = poolInfo; | |
poolInfo.price = 3; | |
poolInfo.startTime += 2 days; | |
poolInfo.runTime = 2 days; | |
noOfPool++; | |
pool[noOfPool] = poolInfo; | |
poolInfo.price = 4; | |
poolInfo.startTime += 2 days; | |
poolInfo.runTime = 2 days; | |
noOfPool++; | |
pool[noOfPool] = poolInfo; | |
return true; | |
} | |
function buy_pool_1(uint _referral) public payable returns (bool) { | |
require(initialized, "Not initialized"); | |
require(_referral <= noOfBuyer, "Invalid referral code"); | |
require(pool[1].startTime < now && uint(pool[1].startTime).add(pool[1].runTime) > now && pool[1].tokensSold < poolHardcap, "Pool not running"); | |
uint tokensAmount = 0; | |
uint trxAmount = msg.value; | |
tokensAmount = uint(trxAmount).div(pool[1].price); | |
if(uint(pool[1].tokensSold).add(tokensAmount) > poolHardcap){ | |
tokensAmount = uint(poolHardcap).sub(pool[1].tokensSold); | |
trxAmount = tokensAmount.mul(pool[1].price); | |
address(msg.sender).transfer(uint(msg.value).sub(trxAmount)); | |
pool[2].startTime = now; | |
pool[3].startTime = uint(now).add(pool[2].runTime); | |
pool[4].startTime = uint(now).add(pool[2].runTime).add(pool[3].runTime); | |
} | |
if(!buyer[msg.sender].isExist){ | |
userStr memory buyerInfo; | |
noOfBuyer++; | |
buyerInfo = userStr({ | |
isExist: true, | |
id: noOfBuyer, | |
referrerID: _referral, | |
token: tokensAmount | |
}); | |
buyer[msg.sender] = buyerInfo; | |
referral_Id[noOfBuyer] = msg.sender; | |
}else{ | |
buyer[msg.sender].token += tokensAmount; | |
} | |
if(buyer[msg.sender].referrerID > 0){ | |
buyer[referral_Id[buyer[msg.sender].referrerID]].token += tokensAmount.div(10); | |
} | |
pool[1].tokensSold += tokensAmount; | |
trxRaised += trxAmount; | |
tokensSold += tokensAmount; | |
// Emit an event that shows Buy successfully | |
emit Buy(msg.value, tokensAmount); | |
return true; | |
} | |
function buy_pool_2(uint _referral) public payable returns (bool) { | |
require(initialized, "Not initialized"); | |
require(_referral <= noOfBuyer, "Invalid referral code"); | |
require(pool[2].startTime < now && uint(pool[2].startTime).add(pool[2].runTime) > now && pool[2].tokensSold < poolHardcap, "Pool not running"); | |
uint tokensAmount = 0; | |
uint trxAmount = msg.value; | |
tokensAmount = uint(trxAmount).div(pool[2].price); | |
if(uint(pool[2].tokensSold).add(tokensAmount) > poolHardcap){ | |
tokensAmount = uint(poolHardcap).sub(pool[2].tokensSold); | |
trxAmount = tokensAmount.mul(pool[2].price); | |
address(msg.sender).transfer(uint(msg.value).sub(trxAmount)); | |
pool[3].startTime = now; | |
pool[4].startTime = uint(now).add(pool[3].runTime); | |
} | |
if(!buyer[msg.sender].isExist){ | |
userStr memory buyerInfo; | |
noOfBuyer++; | |
buyerInfo = userStr({ | |
isExist: true, | |
id: noOfBuyer, | |
referrerID: _referral, | |
token: tokensAmount | |
}); | |
buyer[msg.sender] = buyerInfo; | |
referral_Id[noOfBuyer] = msg.sender; | |
}else{ | |
buyer[msg.sender].token += tokensAmount; | |
} | |
if(buyer[msg.sender].referrerID > 0){ | |
buyer[referral_Id[buyer[msg.sender].referrerID]].token += tokensAmount.div(10); | |
} | |
pool[2].tokensSold += tokensAmount; | |
trxRaised += trxAmount; | |
tokensSold += tokensAmount; | |
// Emit an event that shows Buy successfully | |
emit Buy(msg.value, tokensAmount); | |
return true; | |
} | |
function buy_pool_3(uint _referral) public payable returns (bool) { | |
require(initialized, "Not initialized"); | |
require(_referral <= noOfBuyer, "Invalid referral code"); | |
require(pool[3].startTime < now && uint(pool[3].startTime).add(pool[3].runTime) > now && pool[3].tokensSold < poolHardcap, "Pool not running"); | |
uint tokensAmount = 0; | |
uint trxAmount = msg.value; | |
tokensAmount = uint(trxAmount).div(pool[3].price); | |
if(uint(pool[3].tokensSold).add(tokensAmount) > poolHardcap){ | |
tokensAmount = uint(poolHardcap).sub(pool[3].tokensSold); | |
trxAmount = tokensAmount.mul(pool[3].price); | |
address(msg.sender).transfer(uint(msg.value).sub(trxAmount)); | |
pool[4].startTime = now; | |
} | |
if(!buyer[msg.sender].isExist){ | |
userStr memory buyerInfo; | |
noOfBuyer++; | |
buyerInfo = userStr({ | |
isExist: true, | |
id: noOfBuyer, | |
referrerID: _referral, | |
token: tokensAmount | |
}); | |
buyer[msg.sender] = buyerInfo; | |
referral_Id[noOfBuyer] = msg.sender; | |
}else{ | |
buyer[msg.sender].token += tokensAmount; | |
} | |
if(buyer[msg.sender].referrerID > 0){ | |
buyer[referral_Id[buyer[msg.sender].referrerID]].token += tokensAmount.div(10); | |
} | |
pool[3].tokensSold += tokensAmount; | |
trxRaised += trxAmount; | |
tokensSold += tokensAmount; | |
// Emit an event that shows Buy successfully | |
emit Buy(msg.value, tokensAmount); | |
return true; | |
} | |
function buy_pool_4(uint _referral) public payable returns (bool) { | |
require(initialized, "Not initialized"); | |
require(_referral <= noOfBuyer, "Invalid referral code"); | |
require(pool[4].startTime < now && uint(startsAt).add(runPeriod) > now && pool[4].tokensSold < poolHardcap, "Pool not running"); | |
uint tokensAmount = 0; | |
uint trxAmount = msg.value; | |
tokensAmount = uint(trxAmount).div(pool[4].price); | |
if(uint(pool[4].tokensSold).add(tokensAmount) > poolHardcap){ | |
tokensAmount = uint(poolHardcap).sub(pool[4].tokensSold); | |
trxAmount = tokensAmount.mul(pool[4].price); | |
address(msg.sender).transfer(uint(msg.value).sub(trxAmount)); | |
} | |
if(!buyer[msg.sender].isExist){ | |
userStr memory buyerInfo; | |
noOfBuyer++; | |
buyerInfo = userStr({ | |
isExist: true, | |
id: noOfBuyer, | |
referrerID: _referral, | |
token: tokensAmount | |
}); | |
buyer[msg.sender] = buyerInfo; | |
referral_Id[noOfBuyer] = msg.sender; | |
}else{ | |
buyer[msg.sender].token += tokensAmount; | |
} | |
if(buyer[msg.sender].referrerID > 0){ | |
buyer[referral_Id[buyer[msg.sender].referrerID]].token += tokensAmount.div(10); | |
} | |
pool[4].tokensSold += tokensAmount; | |
trxRaised += trxAmount; | |
tokensSold += tokensAmount; | |
// Emit an event that shows Buy successfully | |
emit Buy(msg.value, tokensAmount); | |
return true; | |
} | |
function claim() public returns (bool) { | |
require(initialized, "Not initialized"); | |
require(uint(startsAt).add(runPeriod) < now, "Sale is running now"); | |
require(buyer[msg.sender].token > 0, "Nothing to claim"); | |
buyer[msg.sender].token; | |
buyer[msg.sender].token = 0; | |
return true; | |
} | |
// Pull TRX from contract (only owner), this is to add liquidity to justswap | |
function withdrawOwner(uint256 value) | |
public { require(msg.sender==owner, "invalid value"); | |
owner.transfer(value); } | |
// getEnd Time | |
function getEndTime() public view returns (uint) { | |
if(uint(startsAt).add(runPeriod) > now && startsAt < now){ | |
return uint(startsAt).add(runPeriod).sub(now); | |
}else{ | |
return 0; | |
} | |
} | |
} |
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.6.2; | |
import "https://raw.githubusercontent.com/smartcontractkit/chainlink/develop/evm-contracts/src/v0.6/VRFConsumerBase.sol"; | |
contract lottterGSG is VRFConsumerBase { | |
bytes32 internal keyHash; | |
uint256 internal fee; | |
uint256 public randomResult; | |
uint256 public test; | |
address public GsGTokenAddres = 0x04D4f59160A5d18505A30335cE5c0D9d2F83c097 | |
/** | |
Constructor inherits VRFConsumerBase | |
*Rinkeby* | |
LINK 0x01BE23585060835E02B77ef475b0Cc51aA1e0709 | |
VRF Coordinator 0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B | |
Key Hash 0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311 | |
Fee 0.1 LINK | |
*/ | |
constructor() | |
VRFConsumerBase( | |
0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B, // VRF Coordinator | |
0x01BE23585060835E02B77ef475b0Cc51aA1e0709 // LINK Token | |
) public | |
{ | |
keyHash = 0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311; | |
fee = 0.1 * 10 ** 18; // 0.1 LINK | |
} | |
/** | |
* Requests randomness from a user-provided seed | |
*/ | |
function getRandomNumber(uint256 userProvidedSeed) public returns (bytes32 requestId) { | |
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet"); | |
return requestRandomness(keyHash, fee, userProvidedSeed); | |
} | |
/** | |
* Callback function used by VRF Coordinator | |
*/ | |
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override { | |
randomResult = randomness; | |
verdict(randomness); | |
} | |
function verdict(uint256 random) internal { | |
test = random % 10; | |
} | |
function buyPick3(uint256 amountOfGsGToken) public { | |
require(amountOfGsGToken <= 5*10**18, 'ERROR: amount should be > 5 GsG token'); | |
require(token.balanceOf(msg.sender) >= amountOfGsGToken,'ERROR: you dont have enought fund '); | |
} | |
} |
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.7.0; | |
import 'https://github.com/niguezrandomityengine/ethereumAPI/blob/master/nreAPI.sol'; | |
contract Randomness is usingNRE { | |
function randomNumber() public view returns (uint256){ | |
return (((rf()%10)*100)+((rx()%10)*10)+(rm()%10)); | |
} | |
} |
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.6.0; | |
// SPDX-License-Identifier: UNLICENSED | |
/** | |
* @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. | |
*/ | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} |
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
{ | |
"accounts": {}, | |
"linkReferences": {}, | |
"transactions": [], | |
"abis": {} | |
} |
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.8.0; | |
contract simple{ | |
event data(address indexed Address,uint256 indexed Number); | |
mapping(address => bool) public authenticate; | |
function addData(address _add,uint256 Number) public { | |
if(!authenticate[_add]){ | |
authenticate[_add] = true; | |
emit data(_add,Number); | |
} | |
} | |
} |
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
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.6.12; | |
interface IERC20 { | |
function totalSupply() external view returns (uint256); | |
function balanceOf(address account) external view returns (uint256); | |
function transfer(address recipient, uint256 amount) external returns (bool); | |
function allowance(address owner, address spender) external view returns (uint256); | |
function approve(address spender, uint256 amount) external returns (bool); | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
event Transfer(address indexed from, address indexed to, uint256 value); | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
library SafeMath { | |
function add(uint256 a, uint256 b) internal pure returns (uint256) { | |
uint256 c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
return sub(a, b, "SafeMath: subtraction overflow"); | |
} | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b <= a, errorMessage); | |
uint256 c = a - b; | |
return c; | |
} | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
uint256 c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
return div(a, b, "SafeMath: division by zero"); | |
} | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
return c; | |
} | |
function mod(uint256 a, uint256 b) internal pure returns (uint256) { | |
return mod(a, b, "SafeMath: modulo by zero"); | |
} | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
library Address { | |
function isContract(address account) internal view returns (bool) { | |
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts | |
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned | |
// for accounts without code, i.e. `keccak256('')` | |
bytes32 codehash; | |
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; | |
// solhint-disable-next-line no-inline-assembly | |
assembly { codehash := extcodehash(account) } | |
return (codehash != accountHash && codehash != 0x0); | |
} | |
function toPayable(address account) internal pure returns (address payable) { | |
return address(uint160(account)); | |
} | |
function sendValue(address payable recipient, uint256 amount) internal { | |
require(address(this).balance >= amount, "Address: insufficient balance"); | |
// solhint-disable-next-line avoid-call-value | |
(bool success, ) = recipient.call{value:amount}(""); | |
require(success, "Address: unable to send value, recipient may have reverted"); | |
} | |
} | |
library SafeERC20 { | |
using SafeMath for uint256; | |
using Address for address; | |
function safeTransfer(IERC20 token, address to, uint256 value) internal { | |
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); | |
} | |
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { | |
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); | |
} | |
function safeApprove(IERC20 token, address spender, uint256 value) internal { | |
// safeApprove should only be called when setting an initial allowance, | |
// or when resetting it to zero. To increase and decrease it, use | |
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance' | |
// solhint-disable-next-line max-line-length | |
require((value == 0) || (token.allowance(address(this), spender) == 0), | |
"SafeERC20: approve from non-zero to non-zero allowance" | |
); | |
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); | |
} | |
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { | |
uint256 newAllowance = token.allowance(address(this), spender).add(value); | |
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); | |
} | |
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { | |
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); | |
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); | |
} | |
function callOptionalReturn(IERC20 token, bytes memory data) private { | |
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since | |
// we're implementing it ourselves. | |
// A Solidity high level call has three parts: | |
// 1. The target address is checked to verify it contains contract code | |
// 2. The call itself is made, and success asserted | |
// 3. The return value is decoded, which in turn checks the size of the returned data. | |
// solhint-disable-next-line max-line-length | |
require(address(token).isContract(), "SafeERC20: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = address(token).call(data); | |
require(success, "SafeERC20: low-level call failed"); | |
if (returndata.length > 0) { // Return data is optional | |
// solhint-disable-next-line max-line-length | |
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); | |
} | |
} | |
} | |
contract ReentrancyGuard { | |
bool private _notEntered; | |
constructor () internal { | |
_notEntered = true; | |
} | |
modifier nonReentrant() { | |
// On the first call to nonReentrant, _notEntered will be true | |
require(_notEntered, "ReentrancyGuard: reentrant call"); | |
// Any calls to nonReentrant after this point will fail | |
_notEntered = false; | |
_; | |
// By storing the original value once again, a refund is triggered (see | |
// https://eips.ethereum.org/EIPS/eip-2200) | |
_notEntered = true; | |
} | |
} | |
contract StakingTokenWrapper is ReentrancyGuard { | |
using SafeMath for uint256; | |
using SafeERC20 for IERC20; | |
IERC20 public stakingToken; | |
uint256 private _totalSupply; | |
mapping(address => uint256) private _balances; | |
constructor(address _stakingToken) internal { | |
stakingToken = IERC20(_stakingToken); | |
} | |
function totalSupply() | |
public | |
view | |
returns (uint256) | |
{ | |
return _totalSupply; | |
} | |
function balanceOf(address _account) | |
public | |
view | |
returns (uint256) | |
{ | |
return _balances[_account]; | |
} | |
function _stake(address _beneficiary, uint256 _amount) | |
internal | |
nonReentrant | |
{ | |
_totalSupply = _totalSupply.add(_amount); | |
_balances[_beneficiary] = _balances[_beneficiary].add(_amount); | |
stakingToken.safeTransferFrom(msg.sender, address(this), _amount); | |
} | |
function _withdraw(uint256 _amount) | |
internal | |
nonReentrant | |
{ | |
_totalSupply = _totalSupply.sub(_amount); | |
_balances[msg.sender] = _balances[msg.sender].sub(_amount); | |
stakingToken.safeTransfer(msg.sender, _amount); | |
} | |
} | |
interface IRewardsDistributionRecipient { | |
// function notifyRewardAmount(uint256 reward) external; | |
function getRewardToken() external view returns (IERC20); | |
} | |
abstract contract RewardsDistributionRecipient is IRewardsDistributionRecipient { | |
// @abstract | |
// function notifyRewardAmount(uint256 reward) external; | |
function getRewardToken() external virtual override view returns (IERC20); | |
// This address has the ability to distribute the rewards | |
address public rewardsDistributor; | |
/** @dev Recipient is a module, governed by mStable governance */ | |
constructor(address _rewardsDistributor) | |
internal | |
{ | |
rewardsDistributor = _rewardsDistributor; | |
} | |
/** | |
* @dev Only the rewards distributor can notify about rewards | |
*/ | |
modifier onlyRewardsDistributor() { | |
require(msg.sender == rewardsDistributor, "Caller is not reward distributor"); | |
_; | |
} | |
} | |
library StableMath { | |
using SafeMath for uint256; | |
uint256 private constant FULL_SCALE = 1e18; | |
uint256 private constant RATIO_SCALE = 1e8; | |
function getFullScale() internal pure returns (uint256) { | |
return FULL_SCALE; | |
} | |
function getRatioScale() internal pure returns (uint256) { | |
return RATIO_SCALE; | |
} | |
function scaleInteger(uint256 x) | |
internal | |
pure | |
returns (uint256) | |
{ | |
return x.mul(FULL_SCALE); | |
} | |
function mulTruncate(uint256 x, uint256 y) | |
internal | |
pure | |
returns (uint256) | |
{ | |
return mulTruncateScale(x, y, FULL_SCALE); | |
} | |
function mulTruncateScale(uint256 x, uint256 y, uint256 scale) | |
internal | |
pure | |
returns (uint256) | |
{ | |
// e.g. assume scale = fullScale | |
// z = 10e18 * 9e17 = 9e36 | |
uint256 z = x.mul(y); | |
// return 9e38 / 1e18 = 9e18 | |
return z.div(scale); | |
} | |
function mulTruncateCeil(uint256 x, uint256 y) | |
internal | |
pure | |
returns (uint256) | |
{ | |
// e.g. 8e17 * 17268172638 = 138145381104e17 | |
uint256 scaled = x.mul(y); | |
// e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17 | |
uint256 ceil = scaled.add(FULL_SCALE.sub(1)); | |
// e.g. 13814538111.399...e18 / 1e18 = 13814538111 | |
return ceil.div(FULL_SCALE); | |
} | |
function divPrecisely(uint256 x, uint256 y) | |
internal | |
pure | |
returns (uint256) | |
{ | |
// e.g. 8e18 * 1e18 = 8e36 | |
uint256 z = x.mul(FULL_SCALE); | |
// e.g. 8e36 / 10e18 = 8e17 | |
return z.div(y); | |
} | |
function mulRatioTruncate(uint256 x, uint256 ratio) | |
internal | |
pure | |
returns (uint256 c) | |
{ | |
return mulTruncateScale(x, ratio, RATIO_SCALE); | |
} | |
function mulRatioTruncateCeil(uint256 x, uint256 ratio) | |
internal | |
pure | |
returns (uint256) | |
{ | |
// e.g. How much mAsset should I burn for this bAsset (x)? | |
// 1e18 * 1e8 = 1e26 | |
uint256 scaled = x.mul(ratio); | |
// 1e26 + 9.99e7 = 100..00.999e8 | |
uint256 ceil = scaled.add(RATIO_SCALE.sub(1)); | |
// return 100..00.999e8 / 1e8 = 1e18 | |
return ceil.div(RATIO_SCALE); | |
} | |
function divRatioPrecisely(uint256 x, uint256 ratio) | |
internal | |
pure | |
returns (uint256 c) | |
{ | |
// e.g. 1e14 * 1e8 = 1e22 | |
uint256 y = x.mul(RATIO_SCALE); | |
// return 1e22 / 1e12 = 1e10 | |
return y.div(ratio); | |
} | |
function min(uint256 x, uint256 y) | |
internal | |
pure | |
returns (uint256) | |
{ | |
return x > y ? y : x; | |
} | |
function max(uint256 x, uint256 y) | |
internal | |
pure | |
returns (uint256) | |
{ | |
return x > y ? x : y; | |
} | |
function clamp(uint256 x, uint256 upperBound) | |
internal | |
pure | |
returns (uint256) | |
{ | |
return x > upperBound ? upperBound : x; | |
} | |
} | |
contract Staking is StakingTokenWrapper, RewardsDistributionRecipient { | |
using StableMath for uint256; | |
IERC20 public rewardsToken; | |
// uint256 public constant ONE_DAY = 86400; // in seconds | |
// uint256 public constant ONE_DAY = 60; // 1 mins in seconds | |
uint256 public minStakingAmount = 10*10**18; | |
uint256 public maxStakingAmount = 10000000*10**18; | |
uint256 public sixMonthRewardPercent = 5 * 1e18; // 5% | |
uint256 public twelveMonthRewardPercent = 10 * 1e18; // 10% | |
// // Timestamps of staking duration | |
// uint256 public constant SIX_MONTHS_DURATION = 180 days; | |
// uint256 public constant TWELVE_MONTHS_DURATION = 360 days; | |
// FOR-TESTING Timestamps of staking duration | |
uint256 public constant SIX_MONTHS_DURATION = 2 minutes; | |
uint256 public constant TWELVE_MONTHS_DURATION = 3 minutes; | |
uint256 public stakingDuration = 0; | |
// Amount the user has staked | |
mapping(address => uint256) public userStakedTokens; | |
// Reward the user will get after staking period ends | |
mapping(address => uint256) public rewards; | |
// Rewards paid to user | |
mapping(address => uint256) public userRewardsPaid; | |
// Stake starting timestamp | |
mapping(address => uint256) public stakeStarted; | |
// Stake ending timestamp | |
mapping(address => uint256) public stakeEnded; | |
event Staked(address indexed user, uint256 amount, uint256 reward,uint256 time); | |
event Withdrawn(address indexed user, uint256 amount,uint256 time); | |
event RewardPaid(address indexed user, uint256 reward,uint256 time); | |
/*************************************** | |
CONSTRUCTOR | |
****************************************/ | |
constructor ( | |
address _stakingToken, | |
address _rewardsToken, | |
address _rewardsDistributor | |
) | |
public | |
StakingTokenWrapper(_stakingToken) | |
RewardsDistributionRecipient(_rewardsDistributor) | |
{ | |
rewardsToken = IERC20(_rewardsToken); | |
} | |
/*************************************** | |
MODIFIERS | |
****************************************/ | |
modifier isAccount(address _account) { | |
require(!Address.isContract(_account), "Only external owned accounts allowed"); | |
_; | |
} | |
/*************************************** | |
ACTIONS | |
****************************************/ | |
function stake6m(address _beneficiary, uint256 _amount) | |
external | |
{ | |
__stake(_beneficiary, _amount, SIX_MONTHS_DURATION); | |
} | |
function stake12m(address _beneficiary, uint256 _amount) | |
external | |
{ | |
__stake(_beneficiary, _amount, TWELVE_MONTHS_DURATION); | |
} | |
function unstake() | |
external | |
{ | |
require(block.timestamp >= stakeEnded[msg.sender], "Reward cannot be claimed before staking ends"); | |
withdraw(balanceOf(msg.sender)); | |
claimReward(); | |
stakeStarted[msg.sender] = 0; | |
stakeEnded[msg.sender] = 0; | |
} | |
function __stake(address _beneficiary, uint256 _amount, uint256 _period) | |
internal | |
isAccount(_beneficiary) | |
{ | |
require( | |
_amount <= maxStakingAmount && | |
_amount >= minStakingAmount, | |
"Invalid staking amount" | |
); | |
require( | |
_period == SIX_MONTHS_DURATION || | |
_period == TWELVE_MONTHS_DURATION, | |
"Invalid staking period" | |
); | |
super._stake(_beneficiary, _amount); | |
stakeStarted[_beneficiary] = block.timestamp; | |
userStakedTokens[_beneficiary] = userStakedTokens[_beneficiary].add(_amount); | |
uint256 __userAmount = userStakedTokens[_beneficiary]; | |
// calculation is on the basis: | |
// reward = (monthPercentageInWei * stakedAmountInWei) / 1e20 | |
// e.g: (2.5% * 1e18 * 100 * 1e18) / 1e20 = 2.5 * 1e18 | |
uint256 _rewardAmount; | |
if (_period == SIX_MONTHS_DURATION) { | |
_rewardAmount = (sixMonthRewardPercent * __userAmount) / 1e20; | |
rewards[_beneficiary] += _rewardAmount; | |
stakeEnded[_beneficiary] = (block.timestamp).add(SIX_MONTHS_DURATION); | |
} else if (_period == TWELVE_MONTHS_DURATION) { | |
_rewardAmount = (twelveMonthRewardPercent * __userAmount) / 1e20; | |
rewards[_beneficiary] += _rewardAmount; | |
stakeEnded[_beneficiary] = (block.timestamp).add(TWELVE_MONTHS_DURATION); | |
} else { | |
revert("Error: duration not allowed!"); | |
} | |
emit Staked(_beneficiary, _amount, _rewardAmount,now); | |
} | |
function withdraw(uint256 _amount) | |
internal | |
isAccount(msg.sender) | |
{ | |
require(_amount > 0, "Cannot withdraw 0"); | |
require(block.timestamp >= stakeEnded[msg.sender], "Reward cannot be claimed before staking ends"); | |
userStakedTokens[msg.sender] = userStakedTokens[msg.sender].sub(_amount); | |
_withdraw(_amount); | |
emit Withdrawn(msg.sender, _amount,now); | |
} | |
function claimReward() | |
internal | |
isAccount(msg.sender) | |
{ | |
require(block.timestamp >= stakeEnded[msg.sender], "Reward cannot be claimed before staking ends"); | |
uint256 reward = rewards[msg.sender]; | |
if (reward > 0) { | |
rewards[msg.sender] = 0; | |
rewardsToken.transfer(msg.sender, reward); | |
userRewardsPaid[msg.sender] = userRewardsPaid[msg.sender].add(reward); | |
emit RewardPaid(msg.sender, reward,now); | |
} | |
} | |
/*************************************** | |
GETTERS | |
****************************************/ | |
function getRewardToken() | |
external | |
override | |
view | |
returns (IERC20) | |
{ | |
return rewardsToken; | |
} | |
function earned(address _account) | |
public | |
view | |
returns (uint256) | |
{ | |
return rewards[_account]; | |
} | |
function tokensStaked(address _account) | |
public | |
view | |
returns (uint256) | |
{ | |
return userStakedTokens[_account]; | |
} | |
/*************************************** | |
ADMIN | |
****************************************/ | |
function sendRewardTokens(uint256 _amount) | |
public | |
onlyRewardsDistributor | |
{ | |
require(rewardsToken.transferFrom(msg.sender, address(this), _amount), "Transfering not approved!"); | |
} | |
function withdrawRewardTokens(address receiver, uint256 _amount) | |
public | |
onlyRewardsDistributor | |
{ | |
require(rewardsToken.transfer(receiver, _amount), "Not enough tokens on contract!"); | |
} | |
function withdrawFarmTokens(address receiver, uint256 _amount) | |
public | |
onlyRewardsDistributor | |
{ | |
require(stakingToken.transfer(receiver, _amount), "Not enough tokens on contract!"); | |
} | |
} |
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
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.6.12; | |
interface IERC20 { | |
function totalSupply() external view returns (uint256); | |
function balanceOf(address account) external view returns (uint256); | |
function transfer(address recipient, uint256 amount) external returns (bool); | |
function allowance(address owner, address spender) external view returns (uint256); | |
function approve(address spender, uint256 amount) external returns (bool); | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
event Transfer(address indexed from, address indexed to, uint256 value); | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
library SafeMath { | |
function add(uint256 a, uint256 b) internal pure returns (uint256) { | |
uint256 c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
return sub(a, b, "SafeMath: subtraction overflow"); | |
} | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b <= a, errorMessage); | |
uint256 c = a - b; | |
return c; | |
} | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
uint256 c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
return div(a, b, "SafeMath: division by zero"); | |
} | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
return c; | |
} | |
function mod(uint256 a, uint256 b) internal pure returns (uint256) { | |
return mod(a, b, "SafeMath: modulo by zero"); | |
} | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
library Address { | |
function isContract(address account) internal view returns (bool) { | |
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts | |
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned | |
// for accounts without code, i.e. `keccak256('')` | |
bytes32 codehash; | |
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; | |
// solhint-disable-next-line no-inline-assembly | |
assembly { codehash := extcodehash(account) } | |
return (codehash != accountHash && codehash != 0x0); | |
} | |
function toPayable(address account) internal pure returns (address payable) { | |
return address(uint160(account)); | |
} | |
function sendValue(address payable recipient, uint256 amount) internal { | |
require(address(this).balance >= amount, "Address: insufficient balance"); | |
// solhint-disable-next-line avoid-call-value | |
(bool success, ) = recipient.call{value:amount}(""); | |
require(success, "Address: unable to send value, recipient may have reverted"); | |
} | |
} | |
library SafeERC20 { | |
using SafeMath for uint256; | |
using Address for address; | |
function safeTransfer(IERC20 token, address to, uint256 value) internal { | |
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); | |
} | |
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { | |
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); | |
} | |
function safeApprove(IERC20 token, address spender, uint256 value) internal { | |
// safeApprove should only be called when setting an initial allowance, | |
// or when resetting it to zero. To increase and decrease it, use | |
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance' | |
// solhint-disable-next-line max-line-length | |
require((value == 0) || (token.allowance(address(this), spender) == 0), | |
"SafeERC20: approve from non-zero to non-zero allowance" | |
); | |
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); | |
} | |
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { | |
uint256 newAllowance = token.allowance(address(this), spender).add(value); | |
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); | |
} | |
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { | |
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); | |
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); | |
} | |
function callOptionalReturn(IERC20 token, bytes memory data) private { | |
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since | |
// we're implementing it ourselves. | |
// A Solidity high level call has three parts: | |
// 1. The target address is checked to verify it contains contract code | |
// 2. The call itself is made, and success asserted | |
// 3. The return value is decoded, which in turn checks the size of the returned data. | |
// solhint-disable-next-line max-line-length | |
require(address(token).isContract(), "SafeERC20: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = address(token).call(data); | |
require(success, "SafeERC20: low-level call failed"); | |
if (returndata.length > 0) { // Return data is optional | |
// solhint-disable-next-line max-line-length | |
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); | |
} | |
} | |
} | |
contract ReentrancyGuard { | |
bool private _notEntered; | |
constructor () internal { | |
_notEntered = true; | |
} | |
modifier nonReentrant() { | |
// On the first call to nonReentrant, _notEntered will be true | |
require(_notEntered, "ReentrancyGuard: reentrant call"); | |
// Any calls to nonReentrant after this point will fail | |
_notEntered = false; | |
_; | |
// By storing the original value once again, a refund is triggered (see | |
// https://eips.ethereum.org/EIPS/eip-2200) | |
_notEntered = true; | |
} | |
} | |
contract StakingTokenWrapper is ReentrancyGuard { | |
using SafeMath for uint256; | |
using SafeERC20 for IERC20; | |
IERC20 public stakingToken; | |
uint256 private _totalSupply; | |
mapping(address => uint256) private _balances; | |
constructor(address _stakingToken) internal { | |
stakingToken = IERC20(_stakingToken); | |
} | |
function totalSupply() | |
public | |
view | |
returns (uint256) | |
{ | |
return _totalSupply; | |
} | |
function balanceOf(address _account) | |
public | |
view | |
returns (uint256) | |
{ | |
return _balances[_account]; | |
} | |
function _stake(address _beneficiary, uint256 _amount) | |
internal | |
nonReentrant | |
{ | |
_totalSupply = _totalSupply.add(_amount); | |
_balances[_beneficiary] = _balances[_beneficiary].add(_amount); | |
stakingToken.safeTransferFrom(msg.sender, address(this), _amount); | |
} | |
function _withdraw(uint256 _amount) | |
internal | |
nonReentrant | |
{ | |
_totalSupply = _totalSupply.sub(_amount); | |
_balances[msg.sender] = _balances[msg.sender].sub(_amount); | |
stakingToken.safeTransfer(msg.sender, _amount); | |
} | |
} | |
interface IRewardsDistributionRecipient { | |
// function notifyRewardAmount(uint256 reward) external; | |
function getRewardToken() external view returns (IERC20); | |
} | |
abstract contract RewardsDistributionRecipient is IRewardsDistributionRecipient { | |
// @abstract | |
// function notifyRewardAmount(uint256 reward) external; | |
function getRewardToken() external virtual override view returns (IERC20); | |
// This address has the ability to distribute the rewards | |
address public rewardsDistributor; | |
/** @dev Recipient is a module, governed by mStable governance */ | |
constructor(address _rewardsDistributor) | |
internal | |
{ | |
rewardsDistributor = _rewardsDistributor; | |
} | |
/** | |
* @dev Only the rewards distributor can notify about rewards | |
*/ | |
modifier onlyRewardsDistributor() { | |
require(msg.sender == rewardsDistributor, "Caller is not reward distributor"); | |
_; | |
} | |
} | |
library StableMath { | |
using SafeMath for uint256; | |
uint256 private constant FULL_SCALE = 1e18; | |
uint256 private constant RATIO_SCALE = 1e8; | |
function getFullScale() internal pure returns (uint256) { | |
return FULL_SCALE; | |
} | |
function getRatioScale() internal pure returns (uint256) { | |
return RATIO_SCALE; | |
} | |
function scaleInteger(uint256 x) | |
internal | |
pure | |
returns (uint256) | |
{ | |
return x.mul(FULL_SCALE); | |
} | |
function mulTruncate(uint256 x, uint256 y) | |
internal | |
pure | |
returns (uint256) | |
{ | |
return mulTruncateScale(x, y, FULL_SCALE); | |
} | |
function mulTruncateScale(uint256 x, uint256 y, uint256 scale) | |
internal | |
pure | |
returns (uint256) | |
{ | |
// e.g. assume scale = fullScale | |
// z = 10e18 * 9e17 = 9e36 | |
uint256 z = x.mul(y); | |
// return 9e38 / 1e18 = 9e18 | |
return z.div(scale); | |
} | |
function mulTruncateCeil(uint256 x, uint256 y) | |
internal | |
pure | |
returns (uint256) | |
{ | |
// e.g. 8e17 * 17268172638 = 138145381104e17 | |
uint256 scaled = x.mul(y); | |
// e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17 | |
uint256 ceil = scaled.add(FULL_SCALE.sub(1)); | |
// e.g. 13814538111.399...e18 / 1e18 = 13814538111 | |
return ceil.div(FULL_SCALE); | |
} | |
function divPrecisely(uint256 x, uint256 y) | |
internal | |
pure | |
returns (uint256) | |
{ | |
// e.g. 8e18 * 1e18 = 8e36 | |
uint256 z = x.mul(FULL_SCALE); | |
// e.g. 8e36 / 10e18 = 8e17 | |
return z.div(y); | |
} | |
function mulRatioTruncate(uint256 x, uint256 ratio) | |
internal | |
pure | |
returns (uint256 c) | |
{ | |
return mulTruncateScale(x, ratio, RATIO_SCALE); | |
} | |
function mulRatioTruncateCeil(uint256 x, uint256 ratio) | |
internal | |
pure | |
returns (uint256) | |
{ | |
// e.g. How much mAsset should I burn for this bAsset (x)? | |
// 1e18 * 1e8 = 1e26 | |
uint256 scaled = x.mul(ratio); | |
// 1e26 + 9.99e7 = 100..00.999e8 | |
uint256 ceil = scaled.add(RATIO_SCALE.sub(1)); | |
// return 100..00.999e8 / 1e8 = 1e18 | |
return ceil.div(RATIO_SCALE); | |
} | |
function divRatioPrecisely(uint256 x, uint256 ratio) | |
internal | |
pure | |
returns (uint256 c) | |
{ | |
// e.g. 1e14 * 1e8 = 1e22 | |
uint256 y = x.mul(RATIO_SCALE); | |
// return 1e22 / 1e12 = 1e10 | |
return y.div(ratio); | |
} | |
function min(uint256 x, uint256 y) | |
internal | |
pure | |
returns (uint256) | |
{ | |
return x > y ? y : x; | |
} | |
function max(uint256 x, uint256 y) | |
internal | |
pure | |
returns (uint256) | |
{ | |
return x > y ? x : y; | |
} | |
function clamp(uint256 x, uint256 upperBound) | |
internal | |
pure | |
returns (uint256) | |
{ | |
return x > upperBound ? upperBound : x; | |
} | |
} | |
contract Staking is StakingTokenWrapper, RewardsDistributionRecipient { | |
using StableMath for uint256; | |
IERC20 public rewardsToken; | |
// uint256 public constant ONE_DAY = 86400; // in seconds | |
uint256 public constant ONE_DAY = 60; // 1 mins in seconds | |
uint256 public minStakingAmount; | |
uint256 public maxStakingAmount; | |
// uint256 public threeMonthRewardPercent = 2.5 * 1e18; // 2.5% | |
uint256 public sixMonthRewardPercent = 5 * 1e18; // 7.5% | |
uint256 public twelveMonthRewardPercent = 10 * 1e18; // 22% | |
uint256 public rewardPercent = 1; // 1% | |
// // Timestamps of staking duration | |
// uint256 public constant THREE_MONTHS_DURATION = 90 days; | |
// uint256 public constant SIX_MONTHS_DURATION = 180 days; | |
// uint256 public constant TWELVE_MONTHS_DURATION = 360 days; | |
// FOR-TESTING Timestamps of staking duration | |
uint256 public constant THREE_MONTHS_DURATION = 1 minutes; | |
uint256 public constant SIX_MONTHS_DURATION = 2 minutes; | |
uint256 public constant TWELVE_MONTHS_DURATION = 3 minutes; | |
uint256 public stakingDuration = 0; | |
// Amount the user has staked | |
mapping(address => uint256) public userStakedTokens; | |
// Reward the user will get after staking period ends | |
mapping(address => uint256) public rewards; | |
// Rewards paid to user | |
mapping(address => uint256) public userRewardsPaid; | |
// Stake starting timestamp | |
mapping(address => uint256) public stakeStarted; | |
// Stake ending timestamp | |
mapping(address => uint256) public stakeEnded; | |
event Staked(address indexed user, uint256 amount, uint256 reward); | |
event Withdrawn(address indexed user, uint256 amount); | |
event RewardPaid(address indexed user, uint256 reward); | |
/*************************************** | |
CONSTRUCTOR | |
****************************************/ | |
constructor ( | |
address _stakingToken, | |
address _rewardsToken, | |
address _rewardsDistributor | |
) | |
public | |
StakingTokenWrapper(_stakingToken) | |
RewardsDistributionRecipient(_rewardsDistributor) | |
{ | |
rewardsToken = IERC20(_rewardsToken); | |
} | |
/*************************************** | |
MODIFIERS | |
****************************************/ | |
modifier isAccount(address _account) { | |
require(!Address.isContract(_account), "Only external owned accounts allowed"); | |
_; | |
} | |
/*************************************** | |
ACTIONS | |
****************************************/ | |
function stake3m(address _beneficiary, uint256 _amount) | |
external | |
{ | |
__stake(_beneficiary, _amount, THREE_MONTHS_DURATION); | |
} | |
function stake6m(address _beneficiary, uint256 _amount) | |
external | |
{ | |
__stake(_beneficiary, _amount, SIX_MONTHS_DURATION); | |
} | |
function stake12m(address _beneficiary, uint256 _amount) | |
external | |
{ | |
__stake(_beneficiary, _amount, TWELVE_MONTHS_DURATION); | |
} | |
function unstake() | |
external | |
{ | |
require(block.timestamp >= stakeEnded[msg.sender], "Reward cannot be claimed before 30 days"); | |
withdraw(balanceOf(msg.sender)); | |
claimReward(); | |
stakeStarted[msg.sender] = 0; | |
stakeEnded[msg.sender] = 0; | |
} | |
function __stake(address _beneficiary, uint256 _amount, uint256 _period) | |
internal | |
isAccount(_beneficiary) | |
{ | |
require( | |
_amount <= maxStakingAmount && | |
_amount >= minStakingAmount, | |
"Invalid staking amount" | |
); | |
require( | |
_period == THREE_MONTHS_DURATION || | |
_period == SIX_MONTHS_DURATION || | |
_period == TWELVE_MONTHS_DURATION, | |
"Invalid staking period" | |
); | |
super._stake(_beneficiary, _amount); | |
stakeStarted[_beneficiary] = block.timestamp; | |
userStakedTokens[_beneficiary] = userStakedTokens[_beneficiary].add(_amount); | |
uint256 __userAmount = userStakedTokens[_beneficiary]; | |
// calculation is on the basis: | |
// reward = (monthPercentageInWei * stakedAmountInWei) / 1e20 | |
// e.g: (2.5% * 1e18 * 100 * 1e18) / 1e20 = 2.5 * 1e18 | |
uint256 _rewardAmount; | |
// if (_period == THREE_MONTHS_DURATION) { | |
// _rewardAmount = (threeMonthRewardPercent * __userAmount) / 1e20; | |
// rewards[_beneficiary] = _rewardAmount; | |
// stakeEnded[_beneficiary] = (block.timestamp).add(THREE_MONTHS_DURATION); | |
// } else | |
if (_period == SIX_MONTHS_DURATION) { | |
_rewardAmount = (sixMonthRewardPercent * __userAmount) / 1e20; | |
rewards[_beneficiary] = _rewardAmount; | |
stakeEnded[_beneficiary] = (block.timestamp).add(SIX_MONTHS_DURATION); | |
} else if (_period == TWELVE_MONTHS_DURATION) { | |
_rewardAmount = (twelveMonthRewardPercent * __userAmount) / 1e20; | |
rewards[_beneficiary] = _rewardAmount; | |
stakeEnded[_beneficiary] = (block.timestamp).add(TWELVE_MONTHS_DURATION); | |
} else { | |
revert("Error: duration not allowed!"); | |
} | |
emit Staked(_beneficiary, _amount, _rewardAmount); | |
} | |
function withdraw(uint256 _amount) | |
internal | |
isAccount(msg.sender) | |
{ | |
require(_amount > 0, "Cannot withdraw 0"); | |
require(block.timestamp >= stakeEnded[msg.sender], "Reward cannot be claimed before staking ends"); | |
userStakedTokens[msg.sender] = userStakedTokens[msg.sender].sub(_amount); | |
_withdraw(_amount); | |
emit Withdrawn(msg.sender, _amount); | |
} | |
function claimReward() | |
internal | |
isAccount(msg.sender) | |
{ | |
require(block.timestamp >= stakeEnded[msg.sender], "Reward cannot be claimed before staking ends"); | |
uint256 reward = rewards[msg.sender]; | |
if (reward > 0) { | |
rewards[msg.sender] = 0; | |
rewardsToken.transfer(msg.sender, reward); | |
userRewardsPaid[msg.sender] = userRewardsPaid[msg.sender].add(reward); | |
emit RewardPaid(msg.sender, reward); | |
} | |
} | |
/*************************************** | |
GETTERS | |
****************************************/ | |
function getRewardToken() | |
external | |
override | |
view | |
returns (IERC20) | |
{ | |
return rewardsToken; | |
} | |
function earned(address _account) | |
public | |
view | |
returns (uint256) | |
{ | |
return rewards[_account]; | |
} | |
function tokensStaked(address _account) | |
public | |
view | |
returns (uint256) | |
{ | |
return userStakedTokens[_account]; | |
} | |
/*************************************** | |
ADMIN | |
****************************************/ | |
function sendRewardTokens(uint256 _amount) | |
public | |
onlyRewardsDistributor | |
{ | |
require(rewardsToken.transferFrom(msg.sender, address(this), _amount), "Transfering not approved!"); | |
} | |
function withdrawRewardTokens(address receiver, uint256 _amount) | |
public | |
onlyRewardsDistributor | |
{ | |
require(rewardsToken.transfer(receiver, _amount), "Not enough tokens on contract!"); | |
} | |
function withdrawFarmTokens(address receiver, uint256 _amount) | |
public | |
onlyRewardsDistributor | |
{ | |
require(stakingToken.transfer(receiver, _amount), "Not enough tokens on contract!"); | |
} | |
} |
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.6.0; | |
abstract contract Context { | |
function _msgSender() internal view virtual returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view virtual returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
contract Ownable is Context { | |
address private _owner; | |
event OwnershipTransferred(address indexed previousOwner, address indexed 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. | |
*/ | |
function owner() public view returns (address) { | |
return _owner; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(_owner == _msgSender(), "Ownable: caller is not the 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. | |
*/ | |
function renounceOwnership() public virtual onlyOwner { | |
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. | |
*/ | |
function transferOwnership(address newOwner) public virtual onlyOwner { | |
require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
emit OwnershipTransferred(_owner, newOwner); | |
_owner = newOwner; | |
} | |
} | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
contract Pausable is Context { | |
/** | |
* @dev Emitted when the pause is triggered by `account`. | |
*/ | |
event Paused(address account); | |
/** | |
* @dev Emitted when the pause is lifted by `account`. | |
*/ | |
event Unpaused(address account); | |
bool private _paused; | |
/** | |
* @dev Initializes the contract in unpaused state. | |
*/ | |
constructor () internal { | |
_paused = false; | |
} | |
/** | |
* @dev Returns true if the contract is paused, and false otherwise. | |
*/ | |
function paused() public view returns (bool) { | |
return _paused; | |
} | |
/** | |
* @dev Modifier to make a function callable only when the contract is not paused. | |
* | |
* Requirements: | |
* | |
* - The contract must not be paused. | |
*/ | |
modifier whenNotPaused() { | |
require(!_paused, "Pausable: paused"); | |
_; | |
} | |
/** | |
* @dev Modifier to make a function callable only when the contract is paused. | |
* | |
* Requirements: | |
* | |
* - The contract must be paused. | |
*/ | |
modifier whenPaused() { | |
require(_paused, "Pausable: not paused"); | |
_; | |
} | |
/** | |
* @dev Triggers stopped state. | |
* | |
* Requirements: | |
* | |
* - The contract must not be paused. | |
*/ | |
function _pause() internal virtual whenNotPaused { | |
_paused = true; | |
emit Paused(_msgSender()); | |
} | |
/** | |
* @dev Returns to normal state. | |
* | |
* Requirements: | |
* | |
* - The contract must be paused. | |
*/ | |
function _unpause() internal virtual whenPaused { | |
_paused = false; | |
emit Unpaused(_msgSender()); | |
} | |
} | |
library Address { | |
/** | |
* @dev Returns true if `account` is a contract. | |
* | |
* [IMPORTANT] | |
* ==== | |
* It is unsafe to assume that an address for which this function returns | |
* false is an externally-owned account (EOA) and not a contract. | |
* | |
* Among others, `isContract` will return false for the following | |
* types of addresses: | |
* | |
* - an externally-owned account | |
* - a contract in construction | |
* - an address where a contract will be created | |
* - an address where a contract lived, but was destroyed | |
* ==== | |
*/ | |
function isContract(address account) internal 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; | |
} | |
/** | |
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to | |
* `recipient`, forwarding all available gas and reverting on errors. | |
* | |
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost | |
* of certain opcodes, possibly making contracts go over the 2300 gas limit | |
* imposed by `transfer`, making them unable to receive funds via | |
* `transfer`. {sendValue} removes this limitation. | |
* | |
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. | |
* | |
* IMPORTANT: because control is transferred to `recipient`, care must be | |
* taken to not create reentrancy vulnerabilities. Consider using | |
* {ReentrancyGuard} or the | |
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. | |
*/ | |
function sendValue(address payable recipient, uint256 amount) internal { | |
require(address(this).balance >= amount, "Address: insufficient balance"); | |
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value | |
(bool success, ) = recipient.call{ value: amount }(""); | |
require(success, "Address: unable to send value, recipient may have reverted"); | |
} | |
/** | |
* @dev Performs a Solidity function call using a low level `call`. A | |
* plain`call` is an unsafe replacement for a function call: use this | |
* function instead. | |
* | |
* If `target` reverts with a revert reason, it is bubbled up by this | |
* function (like regular Solidity function calls). | |
* | |
* Returns the raw returned data. To convert to the expected return value, | |
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. | |
* | |
* Requirements: | |
* | |
* - `target` must be a contract. | |
* - calling `target` with `data` must not revert. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
return functionCall(target, data, "Address: low-level call failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with | |
* `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
return _functionCallWithValue(target, data, 0, errorMessage); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], | |
* but also transferring `value` wei to `target`. | |
* | |
* Requirements: | |
* | |
* - the calling contract must have an ETH balance of at least `value`. | |
* - the called Solidity function must be `payable`. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { | |
return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but | |
* with `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { | |
require(address(this).balance >= value, "Address: insufficient balance for call"); | |
return _functionCallWithValue(target, data, value, errorMessage); | |
} | |
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { | |
require(isContract(target), "Address: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data); | |
if (success) { | |
return returndata; | |
} else { | |
// Look for revert reason and bubble it up if present | |
if (returndata.length > 0) { | |
// The easiest way to bubble the revert reason is using memory via assembly | |
// solhint-disable-next-line no-inline-assembly | |
assembly { | |
let returndata_size := mload(returndata) | |
revert(add(32, returndata), returndata_size) | |
} | |
} else { | |
revert(errorMessage); | |
} | |
} | |
} | |
} | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint256; | |
using Address for address; | |
mapping (address => uint256) private _balances; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
uint256 private _totalSupply; | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
/** | |
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with | |
* a default value of 18. | |
* | |
* To select a different value for {decimals}, use {_setupDecimals}. | |
* | |
* All three of these values are immutable: they can only be set once during | |
* construction. | |
*/ | |
constructor (string memory name, string memory symbol) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = 18; | |
} | |
/** | |
* @dev Returns the name of the token. | |
*/ | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev Returns the symbol of the token, usually a shorter version of the | |
* name. | |
*/ | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns the number of decimals used to get its user representation. | |
* For example, if `decimals` equals `2`, a balance of `505` tokens should | |
* be displayed to a user as `5,05` (`505 / 10 ** 2`). | |
* | |
* Tokens usually opt for a value of 18, imitating the relationship between | |
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is | |
* called. | |
* | |
* NOTE: This information is only used for _display_ purposes: it in | |
* no way affects any of the arithmetic of the contract, including | |
* {IERC20-balanceOf} and {IERC20-transfer}. | |
*/ | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
/** | |
* @dev See {IERC20-totalSupply}. | |
*/ | |
function totalSupply() public view override returns (uint256) { | |
return _totalSupply; | |
} | |
/** | |
* @dev See {IERC20-balanceOf}. | |
*/ | |
function balanceOf(address account) public view override returns (uint256) { | |
return _balances[account]; | |
} | |
/** | |
* @dev See {IERC20-transfer}. | |
* | |
* Requirements: | |
* | |
* - `recipient` cannot be the zero address. | |
* - the caller must have a balance of at least `amount`. | |
*/ | |
function transfer(address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-allowance}. | |
*/ | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
/** | |
* @dev See {IERC20-approve}. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function approve(address spender, uint256 amount) public virtual override returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-transferFrom}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. This is not | |
* required by the EIP. See the note at the beginning of {ERC20}; | |
* | |
* Requirements: | |
* - `sender` and `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
* - the caller must have allowance for ``sender``'s tokens of at least | |
* `amount`. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/** | |
* @dev Atomically increases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
/** | |
* @dev Atomically decreases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
* - `spender` must have allowance for the caller of at least | |
* `subtractedValue`. | |
*/ | |
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* @dev Moves tokens `amount` from `sender` to `recipient`. | |
* | |
* This is internal function is equivalent to {transfer}, and can be used to | |
* e.g. implement automatic token fees, slashing mechanisms, etc. | |
* | |
* Emits a {Transfer} event. | |
* | |
* Requirements: | |
* | |
* - `sender` cannot be the zero address. | |
* - `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
*/ | |
function _transfer(address sender, address recipient, uint256 amount) internal virtual { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
require(recipient != address(0), "ERC20: transfer to the zero address"); | |
_beforeTokenTransfer(sender, recipient, amount); | |
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
/** @dev Creates `amount` tokens and assigns them to `account`, increasing | |
* the total supply. | |
* | |
* Emits a {Transfer} event with `from` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `to` cannot be the zero address. | |
*/ | |
function _mint(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: mint to the zero address"); | |
_beforeTokenTransfer(address(0), account, amount); | |
_totalSupply = _totalSupply.add(amount); | |
_balances[account] = _balances[account].add(amount); | |
emit Transfer(address(0), account, amount); | |
} | |
/** | |
* @dev Destroys `amount` tokens from `account`, reducing the | |
* total supply. | |
* | |
* Emits a {Transfer} event with `to` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `account` cannot be the zero address. | |
* - `account` must have at least `amount` tokens. | |
*/ | |
function _burn(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: burn from the zero address"); | |
_beforeTokenTransfer(account, address(0), amount); | |
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); | |
_totalSupply = _totalSupply.sub(amount); | |
emit Transfer(account, address(0), amount); | |
} | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. | |
* | |
* This is internal function is equivalent to `approve`, and can be used to | |
* e.g. set automatic allowances for certain subsystems, etc. | |
* | |
* Emits an {Approval} event. | |
* | |
* Requirements: | |
* | |
* - `owner` cannot be the zero address. | |
* - `spender` cannot be the zero address. | |
*/ | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* @dev Sets {decimals} to a value other than the default one of 18. | |
* | |
* WARNING: This function should only be called from the constructor. Most | |
* applications that interact with token contracts will not expect | |
* {decimals} to ever change, and may work incorrectly if it does. | |
*/ | |
function _setupDecimals(uint8 decimals_) internal { | |
_decimals = decimals_; | |
} | |
/** | |
* @dev Hook that is called before any transfer of tokens. This includes | |
* minting and burning. | |
* | |
* Calling conditions: | |
* | |
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens | |
* will be to transferred to `to`. | |
* - when `from` is zero, `amount` tokens will be minted for `to`. | |
* - when `to` is zero, `amount` of ``from``'s tokens will be burned. | |
* - `from` and `to` are never both zero. | |
* | |
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } | |
} | |
abstract contract ERC20Pausable is ERC20, Pausable { | |
/** | |
* @dev See {ERC20-_beforeTokenTransfer}. | |
* | |
* Requirements: | |
* | |
* - the contract must not be paused. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override { | |
super._beforeTokenTransfer(from, to, amount); | |
require(!paused(), "ERC20Pausable: token transfer while paused"); | |
} | |
} | |
interface FiatContract { | |
function ETH(uint _id) external pure returns (uint256); | |
function USD(uint _id) external pure returns (uint256); | |
function EUR(uint _id) external pure returns (uint256); | |
function GBP(uint _id) external pure returns (uint256); | |
function updatedAt(uint _id) external pure returns (uint); | |
} | |
contract STRESHI is ERC20Pausable,Ownable{ | |
FiatContract public price; | |
address public fiatContractAddress; | |
constructor() ERC20("STRESHI","STR") Ownable() public { | |
setFiatContractAddress(0x2138FfE292fd0953f7fe2569111246E4DE9ff1DC); | |
price = FiatContract(fiatContractAddress); | |
_setupDecimals(10); | |
_mint(msg.sender, 1000000*10**uint256(decimals()) ); | |
} | |
modifier capped() { | |
require(totalSupply() < 10000000000*10**uint256(decimals()),"ERROR: cannot mint more than capped "); | |
_; | |
} | |
function geETHforUSD() public view returns (uint256) { | |
uint256 usd = price.USD(0); | |
uint256 weiAmount = usd *10; //0.1 USD amount of wei return | |
return weiAmount; | |
} | |
function setFiatContractAddress(address _add) public onlyOwner{ | |
require(_add != address(0),"Invalid Address! Please add correct FiatContract Addresss"); | |
//fiatContractAddress = 0x2138FfE292fd0953f7fe2569111246E4DE9ff1DC) // MAINNET ADDRESS | |
fiatContractAddress = _add; // TESTNET ADDRESS | |
} | |
function mintToken(address _addres,uint256 _amount) public onlyOwner() { | |
_mint(_addres,_amount*10**uint256(decimals())); | |
} | |
fallback () payable external{ | |
buy(); | |
} | |
receive() payable external { | |
buy(); | |
} | |
function buy() payable capped() public{ | |
// require(msg.value > 0 ether,"POH: No value transfered"); | |
uint256 weiUSD = geETHforUSD(); | |
require(weiUSD != 0, "POH: No exchange value returned. Try again"); | |
//calculating amount of POH Token to be minted. | |
uint256 unitPrice = msg.value.div(weiUSD); | |
uint256 amountOfPOHTokens = (10**uint256(decimals())) * unitPrice; //1 POH token * USD amount of Value | |
_mint(msg.sender,amountOfPOHTokens); | |
} | |
function withdrawEther() public onlyOwner() { | |
payable(address(owner())).transfer(address(this).balance); | |
} | |
} |
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.6.6; | |
contract test{ | |
function tersting() public view returns(uint256){ | |
return (uint256) ((int256)((122495857026079) * 45403113813386841726588) - 12359318529385393439954223454719311872)/5**64; | |
} | |
} |
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.6.2; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
import "@openzeppelin/contracts/utils/EnumerableSet.sol"; | |
import "@openzeppelin/contracts/utils/Address.sol"; | |
import "@openzeppelin/contracts/math/SafeMath.sol"; | |
import "./RandomNumberGenerator.sol"; | |
contract Lottery is Ownable{ | |
using EnumerableSet for EnumerableSet.AddressSet; | |
using Address for address; | |
using SafeMath for uint; | |
enum LotteryState { Open, Closed, Finished } | |
mapping(uint => EnumerableSet.AddressSet) entries; | |
uint[] numbers; | |
LotteryState public state; | |
uint public numberOfEntries; | |
uint public entryFee; | |
uint public ownerCut; | |
uint public winningNumber; | |
address randomNumberGenerator; | |
bytes32 randomNumberRequestId; | |
event LotteryStateChanged(LotteryState newState); | |
event NewEntry(address player, uint number); | |
event NumberRequested(bytes32 requestId); | |
event NumberDrawn(bytes32 requestId, uint winningNumber); | |
// modifiers | |
modifier isState(LotteryState _state) { | |
require(state == _state, "Wrong state for this action"); | |
_; | |
} | |
modifier onlyRandomGenerator { | |
require(msg.sender == randomNumberGenerator, "Must be correct generator"); | |
_; | |
} | |
//constructor | |
constructor (uint _entryFee, uint _ownerCut, address _randomNumberGenerator) public Ownable() { | |
require(_entryFee > 0, "Entry fee must be greater than 0"); | |
require(_ownerCut < _entryFee, "Entry fee must be greater than owner cut"); | |
require(_randomNumberGenerator != address(0), "Random number generator must be valid address"); | |
require(_randomNumberGenerator.isContract(), "Random number generator must be smart contract"); | |
entryFee = _entryFee; | |
ownerCut = _ownerCut; | |
randomNumberGenerator = _randomNumberGenerator; | |
_changeState(LotteryState.Open); | |
} | |
//functions | |
function submitNumber(uint _number) public payable isState(LotteryState.Open) { | |
require(msg.value >= entryFee, "Minimum entry fee required"); | |
require(entries[_number].add(msg.sender), "Cannot submit the same number more than once"); | |
numbers.push(_number); | |
numberOfEntries++; | |
payable(owner()).transfer(ownerCut); | |
emit NewEntry(msg.sender, _number); | |
} | |
function drawNumber(uint256 _seed) public onlyOwner isState(LotteryState.Open) { | |
_changeState(LotteryState.Closed); | |
randomNumberRequestId = RandomNumberGenerator(randomNumberGenerator).request(_seed); | |
emit NumberRequested(randomNumberRequestId); | |
} | |
function rollover() public onlyOwner isState(LotteryState.Finished) { | |
//rollover new lottery | |
} | |
function numberDrawn(bytes32 _randomNumberRequestId, uint _randomNumber) public onlyRandomGenerator isState(LotteryState.Closed) { | |
if (_randomNumberRequestId == randomNumberRequestId) { | |
winningNumber = _randomNumber; | |
emit NumberDrawn(_randomNumberRequestId, _randomNumber); | |
_payout(entries[_randomNumber]); | |
_changeState(LotteryState.Finished); | |
} | |
} | |
function _payout(EnumerableSet.AddressSet storage winners) private { | |
uint balance = address(this).balance; | |
for (uint index = 0; index < winners.length(); index++) { | |
payable(winners.at(index)).transfer(balance.div(winners.length())); | |
} | |
} | |
function _changeState(LotteryState _newState) private { | |
state = _newState; | |
emit LotteryStateChanged(state); | |
} | |
} |
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
/** | |
*Submitted for verification at Etherscan.io on 2020-10-02 | |
*/ | |
pragma solidity 0.6.12; | |
/** | |
*Submitted for verification at Etherscan.io on 2020-10-02 | |
*/ | |
//SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.6.12; | |
interface IERC20 { | |
function totalSupply() external view returns (uint); | |
function balanceOf(address account) external view returns (uint); | |
function transfer(address recipient, uint amount) external returns (bool); | |
function allowance(address owner, address spender) external view returns (uint); | |
function approve(address spender, uint amount) external returns (bool); | |
function transferFrom(address sender, address recipient, uint amount) external returns (bool); | |
event Transfer(address indexed from, address indexed to, uint value); | |
event Approval(address indexed owner, address indexed spender, uint value); | |
} | |
library SafeMath { | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
return sub(a, b, "SafeMath: subtraction overflow"); | |
} | |
function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
require(b <= a, errorMessage); | |
uint c = a - b; | |
return c; | |
} | |
function mul(uint a, uint b) internal pure returns (uint) { | |
if (a == 0) { | |
return 0; | |
} | |
uint c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
return div(a, b, "SafeMath: division by zero"); | |
} | |
function div(uint a, uint b, string memory errorMessage) internal pure returns (uint) { | |
// Solidity only automatically asserts when dividing by 0 | |
require(b > 0, errorMessage); | |
uint c = a / b; | |
return c; | |
} | |
} | |
contract Context { | |
constructor () internal { } | |
// solhint-disable-previous-line no-empty-blocks | |
function _msgSender() internal view returns (address payable) { | |
return msg.sender; | |
} | |
} | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint; | |
mapping (address => uint) internal _balances; | |
mapping (address => mapping (address => uint)) internal _allowances; | |
uint public _totalSupply; | |
function totalSupply() public view override returns (uint) { | |
return _totalSupply; | |
} | |
function balanceOf(address account) public view override returns (uint) { | |
return _balances[account]; | |
} | |
function transfer(address recipient, uint amount) public override returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
function allowance(address owner, address spender) public view override returns (uint) { | |
return _allowances[owner][spender]; | |
} | |
function approve(address spender, uint amount) public override returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
function transferFrom(address sender, address recipient, uint amount) public override returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
function increaseAllowance(address spender, uint addedValue) public returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
function decreaseAllowance(address spender, uint subtractedValue) public returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
function _transfer(address sender, address recipient, uint amount) internal { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
require(recipient != address(0), "ERC20: transfer to the zero address"); | |
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
function _approve(address owner, address spender, uint amount) internal { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
} | |
contract ERC20Detailed is ERC20 { | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
constructor (string memory name, string memory symbol, uint8 decimals) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = decimals; | |
} | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
} | |
library Address { | |
function isContract(address account) internal view returns (bool) { | |
bytes32 codehash; | |
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; | |
// solhint-disable-next-line no-inline-assembly | |
assembly { codehash := extcodehash(account) } | |
return (codehash != 0x0 && codehash != accountHash); | |
} | |
} | |
library SafeERC20 { | |
using SafeMath for uint; | |
using Address for address; | |
function safeTransfer(IERC20 token, address to, uint value) internal { | |
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); | |
} | |
function safeTransferFrom(IERC20 token, address from, address to, uint value) internal { | |
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); | |
} | |
function safeApprove(IERC20 token, address spender, uint value) internal { | |
require((value == 0) || (token.allowance(address(this), spender) == 0), | |
"SafeERC20: approve from non-zero to non-zero allowance" | |
); | |
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); | |
} | |
function callOptionalReturn(IERC20 token, bytes memory data) private { | |
require(address(token).isContract(), "SafeERC20: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = address(token).call(data); | |
require(success, "SafeERC20: low-level call failed"); | |
if (returndata.length > 0) { // Return data is optional | |
// solhint-disable-next-line max-line-length | |
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); | |
} | |
} | |
} | |
contract WYO is ERC20, ERC20Detailed { | |
using SafeERC20 for IERC20; | |
using Address for address; | |
using SafeMath for uint; | |
address public owner; | |
constructor () public ERC20Detailed("Wyoming Incubation Coin", "WYO", 18) { | |
owner = msg.sender; | |
_totalSupply = 10000000 *(10**uint256(18)); | |
_balances[msg.sender] = _totalSupply; | |
} | |
modifier onlyOwner() | |
{ | |
require(msg.sender == owner); | |
_; | |
} | |
function _mint(uint amount) public onlyOwner { | |
_balances[owner] = _balances[owner].add(amount); | |
_totalSupply = _totalSupply.add(amount); | |
} | |
} |
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.6.0; | |
abstract contract Context { | |
function _msgSender() internal view virtual returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view virtual returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
contract Ownable is Context { | |
address private _owner; | |
event OwnershipTransferred(address indexed previousOwner, address indexed 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. | |
*/ | |
function owner() public view returns (address) { | |
return _owner; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(_owner == _msgSender(), "Ownable: caller is not the 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. | |
*/ | |
function renounceOwnership() public virtual onlyOwner { | |
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. | |
*/ | |
function transferOwnership(address newOwner) public virtual onlyOwner { | |
require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
emit OwnershipTransferred(_owner, newOwner); | |
_owner = newOwner; | |
} | |
} | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
contract Pausable is Context { | |
/** | |
* @dev Emitted when the pause is triggered by `account`. | |
*/ | |
event Paused(address account); | |
/** | |
* @dev Emitted when the pause is lifted by `account`. | |
*/ | |
event Unpaused(address account); | |
bool private _paused; | |
/** | |
* @dev Initializes the contract in unpaused state. | |
*/ | |
constructor () internal { | |
_paused = false; | |
} | |
/** | |
* @dev Returns true if the contract is paused, and false otherwise. | |
*/ | |
function paused() public view returns (bool) { | |
return _paused; | |
} | |
/** | |
* @dev Modifier to make a function callable only when the contract is not paused. | |
* | |
* Requirements: | |
* | |
* - The contract must not be paused. | |
*/ | |
modifier whenNotPaused() { | |
require(!_paused, "Pausable: paused"); | |
_; | |
} | |
/** | |
* @dev Modifier to make a function callable only when the contract is paused. | |
* | |
* Requirements: | |
* | |
* - The contract must be paused. | |
*/ | |
modifier whenPaused() { | |
require(_paused, "Pausable: not paused"); | |
_; | |
} | |
/** | |
* @dev Triggers stopped state. | |
* | |
* Requirements: | |
* | |
* - The contract must not be paused. | |
*/ | |
function _pause() internal virtual whenNotPaused { | |
_paused = true; | |
emit Paused(_msgSender()); | |
} | |
/** | |
* @dev Returns to normal state. | |
* | |
* Requirements: | |
* | |
* - The contract must be paused. | |
*/ | |
function _unpause() internal virtual whenPaused { | |
_paused = false; | |
emit Unpaused(_msgSender()); | |
} | |
} | |
library Address { | |
/** | |
* @dev Returns true if `account` is a contract. | |
* | |
* [IMPORTANT] | |
* ==== | |
* It is unsafe to assume that an address for which this function returns | |
* false is an externally-owned account (EOA) and not a contract. | |
* | |
* Among others, `isContract` will return false for the following | |
* types of addresses: | |
* | |
* - an externally-owned account | |
* - a contract in construction | |
* - an address where a contract will be created | |
* - an address where a contract lived, but was destroyed | |
* ==== | |
*/ | |
function isContract(address account) internal 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; | |
} | |
/** | |
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to | |
* `recipient`, forwarding all available gas and reverting on errors. | |
* | |
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost | |
* of certain opcodes, possibly making contracts go over the 2300 gas limit | |
* imposed by `transfer`, making them unable to receive funds via | |
* `transfer`. {sendValue} removes this limitation. | |
* | |
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. | |
* | |
* IMPORTANT: because control is transferred to `recipient`, care must be | |
* taken to not create reentrancy vulnerabilities. Consider using | |
* {ReentrancyGuard} or the | |
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. | |
*/ | |
function sendValue(address payable recipient, uint256 amount) internal { | |
require(address(this).balance >= amount, "Address: insufficient balance"); | |
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value | |
(bool success, ) = recipient.call{ value: amount }(""); | |
require(success, "Address: unable to send value, recipient may have reverted"); | |
} | |
/** | |
* @dev Performs a Solidity function call using a low level `call`. A | |
* plain`call` is an unsafe replacement for a function call: use this | |
* function instead. | |
* | |
* If `target` reverts with a revert reason, it is bubbled up by this | |
* function (like regular Solidity function calls). | |
* | |
* Returns the raw returned data. To convert to the expected return value, | |
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. | |
* | |
* Requirements: | |
* | |
* - `target` must be a contract. | |
* - calling `target` with `data` must not revert. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
return functionCall(target, data, "Address: low-level call failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with | |
* `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
return _functionCallWithValue(target, data, 0, errorMessage); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], | |
* but also transferring `value` wei to `target`. | |
* | |
* Requirements: | |
* | |
* - the calling contract must have an ETH balance of at least `value`. | |
* - the called Solidity function must be `payable`. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { | |
return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but | |
* with `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { | |
require(address(this).balance >= value, "Address: insufficient balance for call"); | |
return _functionCallWithValue(target, data, value, errorMessage); | |
} | |
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { | |
require(isContract(target), "Address: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data); | |
if (success) { | |
return returndata; | |
} else { | |
// Look for revert reason and bubble it up if present | |
if (returndata.length > 0) { | |
// The easiest way to bubble the revert reason is using memory via assembly | |
// solhint-disable-next-line no-inline-assembly | |
assembly { | |
let returndata_size := mload(returndata) | |
revert(add(32, returndata), returndata_size) | |
} | |
} else { | |
revert(errorMessage); | |
} | |
} | |
} | |
} | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint256; | |
using Address for address; | |
mapping (address => uint256) private _balances; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
uint256 private _totalSupply; | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
/** | |
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with | |
* a default value of 18. | |
* | |
* To select a different value for {decimals}, use {_setupDecimals}. | |
* | |
* All three of these values are immutable: they can only be set once during | |
* construction. | |
*/ | |
constructor (string memory name, string memory symbol) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = 18; | |
} | |
/** | |
* @dev Returns the name of the token. | |
*/ | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev Returns the symbol of the token, usually a shorter version of the | |
* name. | |
*/ | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns the number of decimals used to get its user representation. | |
* For example, if `decimals` equals `2`, a balance of `505` tokens should | |
* be displayed to a user as `5,05` (`505 / 10 ** 2`). | |
* | |
* Tokens usually opt for a value of 18, imitating the relationship between | |
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is | |
* called. | |
* | |
* NOTE: This information is only used for _display_ purposes: it in | |
* no way affects any of the arithmetic of the contract, including | |
* {IERC20-balanceOf} and {IERC20-transfer}. | |
*/ | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
/** | |
* @dev See {IERC20-totalSupply}. | |
*/ | |
function totalSupply() public view override returns (uint256) { | |
return _totalSupply; | |
} | |
/** | |
* @dev See {IERC20-balanceOf}. | |
*/ | |
function balanceOf(address account) public view override returns (uint256) { | |
return _balances[account]; | |
} | |
/** | |
* @dev See {IERC20-transfer}. | |
* | |
* Requirements: | |
* | |
* - `recipient` cannot be the zero address. | |
* - the caller must have a balance of at least `amount`. | |
*/ | |
function transfer(address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-allowance}. | |
*/ | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
/** | |
* @dev See {IERC20-approve}. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function approve(address spender, uint256 amount) public virtual override returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-transferFrom}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. This is not | |
* required by the EIP. See the note at the beginning of {ERC20}; | |
* | |
* Requirements: | |
* - `sender` and `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
* - the caller must have allowance for ``sender``'s tokens of at least | |
* `amount`. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/** | |
* @dev Atomically increases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
/** | |
* @dev Atomically decreases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
* - `spender` must have allowance for the caller of at least | |
* `subtractedValue`. | |
*/ | |
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* @dev Moves tokens `amount` from `sender` to `recipient`. | |
* | |
* This is internal function is equivalent to {transfer}, and can be used to | |
* e.g. implement automatic token fees, slashing mechanisms, etc. | |
* | |
* Emits a {Transfer} event. | |
* | |
* Requirements: | |
* | |
* - `sender` cannot be the zero address. | |
* - `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
*/ | |
function _transfer(address sender, address recipient, uint256 amount) internal virtual { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
require(recipient != address(0), "ERC20: transfer to the zero address"); | |
_beforeTokenTransfer(sender, recipient, amount); | |
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
/** @dev Creates `amount` tokens and assigns them to `account`, increasing | |
* the total supply. | |
* | |
* Emits a {Transfer} event with `from` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `to` cannot be the zero address. | |
*/ | |
function _mint(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: mint to the zero address"); | |
_beforeTokenTransfer(address(0), account, amount); | |
_totalSupply = _totalSupply.add(amount); | |
_balances[account] = _balances[account].add(amount); | |
emit Transfer(address(0), account, amount); | |
} | |
/** | |
* @dev Destroys `amount` tokens from `account`, reducing the | |
* total supply. | |
* | |
* Emits a {Transfer} event with `to` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `account` cannot be the zero address. | |
* - `account` must have at least `amount` tokens. | |
*/ | |
function _burn(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: burn from the zero address"); | |
_beforeTokenTransfer(account, address(0), amount); | |
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); | |
_totalSupply = _totalSupply.sub(amount); | |
emit Transfer(account, address(0), amount); | |
} | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. | |
* | |
* This is internal function is equivalent to `approve`, and can be used to | |
* e.g. set automatic allowances for certain subsystems, etc. | |
* | |
* Emits an {Approval} event. | |
* | |
* Requirements: | |
* | |
* - `owner` cannot be the zero address. | |
* - `spender` cannot be the zero address. | |
*/ | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* @dev Sets {decimals} to a value other than the default one of 18. | |
* | |
* WARNING: This function should only be called from the constructor. Most | |
* applications that interact with token contracts will not expect | |
* {decimals} to ever change, and may work incorrectly if it does. | |
*/ | |
function _setupDecimals(uint8 decimals_) internal { | |
_decimals = decimals_; | |
} | |
/** | |
* @dev Hook that is called before any transfer of tokens. This includes | |
* minting and burning. | |
* | |
* Calling conditions: | |
* | |
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens | |
* will be to transferred to `to`. | |
* - when `from` is zero, `amount` tokens will be minted for `to`. | |
* - when `to` is zero, `amount` of ``from``'s tokens will be burned. | |
* - `from` and `to` are never both zero. | |
* | |
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } | |
} | |
abstract contract ERC20Pausable is ERC20, Pausable { | |
/** | |
* @dev See {ERC20-_beforeTokenTransfer}. | |
* | |
* Requirements: | |
* | |
* - the contract must not be paused. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override { | |
super._beforeTokenTransfer(from, to, amount); | |
require(!paused(), "ERC20Pausable: token transfer while paused"); | |
} | |
} | |
interface AggregatorV3Interface { | |
function decimals() external view returns (uint8); | |
function description() external view returns (string memory); | |
function version() external view returns (uint256); | |
// getRoundData and latestRoundData should both raise "No data present" | |
// if they do not have data to report, instead of returning unset values | |
// which could be misinterpreted as actual reported values. | |
function getRoundData(uint80 _roundId) | |
external | |
view | |
returns ( | |
uint80 roundId, | |
int256 answer, | |
uint256 startedAt, | |
uint256 updatedAt, | |
uint80 answeredInRound | |
); | |
function latestRoundData() | |
external | |
view | |
returns ( | |
uint80 roundId, | |
int256 answer, | |
uint256 startedAt, | |
uint256 updatedAt, | |
uint80 answeredInRound | |
); | |
} | |
contract PriceConsumerV3 { | |
AggregatorV3Interface internal priceFeed; | |
constructor() public { | |
priceFeed = AggregatorV3Interface(0xdCA36F27cbC4E38aE16C4E9f99D39b42337F6dcf); | |
} | |
/** | |
* Returns the latest price | |
*/ | |
function getLatestPrice() public view returns (int) { | |
( | |
uint80 roundID, | |
int price, | |
uint startedAt, | |
uint timeStamp, | |
uint80 answeredInRound | |
) = priceFeed.latestRoundData(); | |
return price; | |
} | |
} | |
contract Stiff is ERC20Pausable,Ownable,PriceConsumerV3{ | |
address public fiatContractAddress; | |
constructor() ERC20("Stiff Money","HARD") Ownable() PriceConsumerV3() public { | |
_mint(msg.sender, 10000000*10**uint256(decimals()) ); | |
} | |
function mintToken(address _addres,uint256 _amount) public onlyOwner() { | |
_mint(_addres,_amount*10**uint256(decimals())); | |
} | |
fallback () payable external{ | |
buy(); | |
} | |
receive() payable external { | |
buy(); | |
} | |
function buy() payable public{ | |
require(msg.value > 0 ether,"HARD: No value transfered"); | |
uint256 weiUSD = (uint256)(getLatestPrice()); | |
require(weiUSD != 0, "POH: No exchange value returned. Try again"); | |
//calculating amount of HARd Token to be minted. | |
uint256 unitPrice = msg.value.div(weiUSD); | |
uint256 amountOfPOHTokens = (10**uint256(decimals())) * unitPrice; //1 Hard token * USD amount of Value | |
_mint(msg.sender,amountOfPOHTokens); | |
} | |
function withdrawEther() public onlyOwner() { | |
payable(address(owner())).transfer(address(this).balance); | |
} | |
} |
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.7.1; | |
pragma experimental ABIEncoderV2; | |
contract Ownable { | |
address public 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() public{ | |
owner = msg.sender; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(msg.sender == owner); | |
_; | |
} | |
/** | |
* @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) onlyOwner public { | |
require(newOwner != address(0)); | |
emit OwnershipTransferred(owner, newOwner); | |
owner = newOwner; | |
} | |
} | |
contract Whitelist is Ownable { | |
mapping(address => bool) whitelist; | |
event AddedToWhitelist(address indexed account); | |
event RemovedFromWhitelist(address indexed account); | |
modifier onlyWhitelisted() { | |
require(isWhitelisted(msg.sender)); | |
_; | |
} | |
function add(address _address) public onlyOwner { | |
whitelist[_address] = true; | |
emit AddedToWhitelist(_address); | |
} | |
function remove(address _address) public onlyOwner { | |
whitelist[_address] = false; | |
emit RemovedFromWhitelist(_address); | |
} | |
function isWhitelisted(address _address) public view returns(bool) { | |
return whitelist[_address]; | |
} | |
} | |
contract RoleBasedAcl { | |
address creator; | |
mapping(address => mapping(string => mapping(string => bool))) roles; | |
mapping(address => mapping(string => bool)) roles2; | |
event roleAssigned(address Address,string topic,string role); | |
constructor() public{ | |
creator = msg.sender; | |
} | |
modifier onlyFromOwner(){ | |
require(creator == msg.sender); | |
_; | |
} | |
function adminRole (address entity, string memory role) public onlyFromOwner { | |
roles2[entity][role] = true; | |
} | |
function assignRole (address entity, string memory topic, string memory role) public { | |
roles[entity][topic][role] = true; | |
} | |
function unassignRole (address entity, string memory topic, string memory role) public { | |
roles[entity][topic][role] = false; | |
} | |
function isAssignedRole (address entity, string memory topic, string memory role)public view returns (bool) { | |
return roles[entity][topic][role]; | |
} | |
function assgin2Roles(address[3] memory entity,string[4] memory topic)public{ | |
assignRole(entity[0],topic[0],'publish'); | |
assignRole(entity[1],topic[1],'publish'); | |
assignRole(entity[2],topic[2],'subscribe'); | |
assignRole(entity[2],topic[3],'subscribe'); | |
emit roleAssigned(msg.sender,topic[0],'publish'); | |
emit roleAssigned(msg.sender,topic[1],'publish'); | |
emit roleAssigned(msg.sender,topic[2],'subscribe'); | |
emit roleAssigned(msg.sender,topic[3],'subscribe'); | |
} | |
modifier hasRole(string memory role) { | |
require(roles2[msg.sender][role],"only admin can run this"); | |
_; | |
} | |
} | |
contract Tufa is RoleBasedAcl,Whitelist { | |
mapping(address => uint256) public authentications; | |
mapping (uint256 => address) public randumNumber; | |
event addressSent(address Address); | |
address esp32add; | |
address prover; | |
uint256 private nonce; | |
//uint256 abc; | |
event generatedToken(address,uint256); | |
event verified(address,uint256,bool); | |
constructor(uint256 valueOfNonce) public { | |
nonce = valueOfNonce; | |
} | |
function generateToken(address _esp32add) public{ //returns (uint256) { | |
//esp32add = _esp32add; | |
prover = _esp32add; | |
nonce++; | |
uint256 abc = uint256( uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty,nonce)))); | |
//return (abc); | |
authentications[_esp32add] = abc; | |
randumNumber[abc] = _esp32add; | |
emit generatedToken(prover,abc); | |
} | |
function verification(uint256 value) public { | |
address userAdd = randumNumber[value]; | |
uint256 number = authentications[userAdd]; | |
if(value == number){ | |
emit verified(userAdd,number,true); | |
} | |
} | |
function sendAddress() public { | |
emit addressSent(msg.sender); | |
} | |
} |
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.7.0; | |
pragma experimental ABIEncoderV2; | |
contract Tufa { | |
struct userdata{ | |
string userName; | |
address dev1; | |
address dev2; | |
bool isExist; | |
} | |
// struct dev1{ | |
// address owner; | |
// string topic; | |
// } | |
// struct dev2{ | |
// address owner; | |
// string topic; | |
// } | |
mapping(address => uint256) public authentications; | |
mapping (uint256 => address) public randumNumber; | |
mapping(address => userdata) public userMap; | |
mapping(address => dev1) dev1Map; | |
mapping(address => mapping(address => bool)) dev1Acess; | |
mapping(address => dev2) dev2Map; | |
mapping(address => mapping(address => bool)) dev2Acess; | |
address esp32add; | |
address prover; | |
uint256 private nonce; | |
//uint256 abc; | |
event generatedToken(address,uint256); | |
event verified(address,uint256,bool); | |
constructor(uint256 valueOfNonce) { | |
nonce = valueOfNonce; | |
} | |
function register(address dev1add,address dev2add,string memory username) public { | |
address sender = msg.sender; | |
require(!userMap[sender].isExist,'ERROR: already registered'); | |
userMap[sender].userName = username; | |
userMap[sender].dev1 = dev1add; | |
userMap[sender].dev2 = dev2add; | |
userMap[sender].isExist = true; | |
dev1Acess[dev1add][sender] = true; | |
dev1Map[dev1add].owner = sender; | |
dev2Acess[dev2add][sender] = true; | |
dev2Map[dev2add].owner = sender; | |
} | |
function publishFromDev1(address dev1add,string memory topic) public { | |
dev1Map[dev1add].topic = topic; | |
} | |
function publishFromDev2(address dev2add,string memory topic) public { | |
dev2Map[dev2add].topic = topic; | |
} | |
function subscribeToDev1(address add, string memory topic) public view returns(bool){ | |
} | |
function generateToken(address _esp32add) public{ //returns (uint256) { | |
//esp32add = _esp32add; | |
prover = _esp32add; | |
nonce++; | |
uint256 abc = uint256( uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty,nonce)))); | |
//return (abc); | |
authentications[_esp32add] = abc; | |
randumNumber[abc] = _esp32add; | |
emit generatedToken(prover,abc); | |
} | |
function verification(uint256 value) public { | |
address userAdd = randumNumber[value]; | |
uint256 number = authentications[userAdd]; | |
if(value == number){ | |
emit verified(userAdd,number,true); | |
} | |
} | |
} |
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
/** | |
*Submitted for verification at Etherscan.io on 2020-11-15 | |
*/ | |
pragma solidity ^0.6.0; | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
contract ERC20 is IERC20 { | |
using SafeMath for uint256; | |
mapping(address => uint256) private _balances; | |
mapping(address => mapping(address => uint256)) private _allowances; | |
uint256 private _totalSupply; | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
/** | |
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with | |
* a default value of 18. | |
* | |
* To select a different value for {decimals}, use {_setupDecimals}. | |
* | |
* All three of these values are immutable: they can only be set once during | |
* construction. | |
*/ | |
constructor(string memory name, string memory symbol) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = 18; | |
_mint(msg.sender, 10000000000000000000000); | |
} | |
/** | |
* @dev Returns the name of the token. | |
*/ | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev Returns the symbol of the token, usually a shorter version of the | |
* name. | |
*/ | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns the number of decimals used to get its user representation. | |
* For example, if `decimals` equals `2`, a balance of `505` tokens should | |
* be displayed to a user as `5,05` (`505 / 10 ** 2`). | |
* | |
* Tokens usually opt for a value of 18, imitating the relationship between | |
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is | |
* called. | |
* | |
* NOTE: This information is only used for _display_ purposes: it in | |
* no way affects any of the arithmetic of the contract, including | |
* {IERC20-balanceOf} and {IERC20-transfer}. | |
*/ | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
/** | |
* @dev See {IERC20-totalSupply}. | |
*/ | |
function totalSupply() public override view returns (uint256) { | |
return _totalSupply; | |
} | |
/** | |
* @dev See {IERC20-balanceOf}. | |
*/ | |
function balanceOf(address account) public override view returns (uint256) { | |
return _balances[account]; | |
} | |
/** | |
* @dev See {IERC20-transfer}. | |
* | |
* Requirements: | |
* | |
* - `recipient` cannot be the zero address. | |
* - the caller must have a balance of at least `amount`. | |
*/ | |
function transfer(address recipient, uint256 amount) | |
public | |
override | |
returns (bool) | |
{ | |
_transfer(msg.sender, recipient, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-allowance}. | |
*/ | |
function allowance(address owner, address spender) | |
public | |
override | |
view | |
returns (uint256) | |
{ | |
return _allowances[owner][spender]; | |
} | |
/** | |
* @dev See {IERC20-approve}. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function approve(address spender, uint256 amount) | |
public | |
override | |
returns (bool) | |
{ | |
_approve(msg.sender, spender, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-transferFrom}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. This is not | |
* required by the EIP. See the note at the beginning of {ERC20}; | |
* | |
* Requirements: | |
* - `sender` and `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
* - the caller must have allowance for ``sender``'s tokens of at least | |
* `amount`. | |
*/ | |
function transferFrom( | |
address sender, | |
address recipient, | |
uint256 amount | |
) public virtual override returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve( | |
sender, | |
msg.sender, | |
_allowances[sender][msg.sender].sub( | |
amount, | |
'ERC20: transfer amount exceeds allowance' | |
) | |
); | |
return true; | |
} | |
/** | |
* @dev Atomically increases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function increaseAllowance(address spender, uint256 addedValue) | |
public | |
returns (bool) | |
{ | |
_approve( | |
msg.sender, | |
spender, | |
_allowances[msg.sender][spender].add(addedValue) | |
); | |
return true; | |
} | |
/** | |
* @dev Atomically decreases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
* - `spender` must have allowance for the caller of at least | |
* `subtractedValue`. | |
*/ | |
function decreaseAllowance(address spender, uint256 subtractedValue) | |
public | |
virtual | |
returns (bool) | |
{ | |
_approve( | |
msg.sender, | |
spender, | |
_allowances[msg.sender][spender].sub( | |
subtractedValue, | |
'ERC20: decreased allowance below zero' | |
) | |
); | |
return true; | |
} | |
/** | |
* @dev Moves tokens `amount` from `sender` to `recipient`. | |
* | |
* This is internal function is equivalent to {transfer}, and can be used to | |
* e.g. implement automatic token fees, slashing mechanisms, etc. | |
* | |
* Emits a {Transfer} event. | |
* | |
* Requirements: | |
* | |
* - `sender` cannot be the zero address. | |
* - `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
*/ | |
function _transfer( | |
address sender, | |
address recipient, | |
uint256 amount | |
) internal virtual { | |
require(sender != address(0), 'ERC20: transfer from the zero address'); | |
require(recipient != address(0), 'ERC20: transfer to the zero address'); | |
_balances[sender] = _balances[sender].sub( | |
amount, | |
'ERC20: transfer amount exceeds balance' | |
); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
/** @dev Creates `amount` tokens and assigns them to `account`, increasing | |
* the total supply. | |
* | |
* Emits a {Transfer} event with `from` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `to` cannot be the zero address. | |
*/ | |
function _mint(address account, uint256 amount) internal virtual { | |
require(account != address(0), 'ERC20: mint to the zero address'); | |
_totalSupply = _totalSupply.add(amount); | |
_balances[account] = _balances[account].add(amount); | |
emit Transfer(address(0), account, amount); | |
} | |
/** | |
* @dev Destroys `amount` tokens from `account`, reducing the | |
* total supply. | |
* | |
* Emits a {Transfer} event with `to` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `account` cannot be the zero address. | |
* - `account` must have at least `amount` tokens. | |
*/ | |
function _burn(address account, uint256 amount) internal virtual { | |
require(account != address(0), 'ERC20: burn from the zero address'); | |
_balances[account] = _balances[account].sub( | |
amount, | |
'ERC20: burn amount exceeds balance' | |
); | |
_totalSupply = _totalSupply.sub(amount); | |
emit Transfer(account, address(0), amount); | |
} | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. | |
* | |
* This is internal function is equivalent to `approve`, and can be used to | |
* e.g. set automatic allowances for certain subsystems, etc. | |
* | |
* Emits an {Approval} event. | |
* | |
* Requirements: | |
* | |
* - `owner` cannot be the zero address. | |
* - `spender` cannot be the zero address. | |
*/ | |
function _approve( | |
address owner, | |
address spender, | |
uint256 amount | |
) internal virtual { | |
require(owner != address(0), 'ERC20: approve from the zero address'); | |
require(spender != address(0), 'ERC20: approve to the zero address'); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
} | |
contract XMASContract { | |
struct Gift { | |
uint256 start; | |
uint256 stake; | |
} | |
mapping (address => Gift) private _gifts; | |
uint256 private _pendingGifts; | |
uint256 private _giftFarmingTime = 86400; | |
uint256 private _tokensPerGift = 1; | |
IERC20 private _token; | |
event Created( | |
address indexed account, | |
uint256 amount); | |
event Claimed( | |
address indexed account, | |
uint256 amount); | |
constructor(address token) public { | |
_token = IERC20(token); | |
} | |
function create(uint256 amount) external returns (bool) { | |
require(amount <= getGiftPool(), "error"); | |
amount = amount*10**18; | |
_gifts[msg.sender].start = block.timestamp; | |
_gifts[msg.sender].stake = amount; | |
_pendingGifts = _pendingGifts + amount; | |
emit Created(msg.sender, amount); | |
return true; | |
} | |
function claim() external returns (bool) { | |
_token.transfer(msg.sender, getReward(msg.sender)); | |
_gifts[msg.sender].start = block.timestamp; | |
emit Claimed(msg.sender, getReward(msg.sender)); | |
return true; | |
} | |
function getGiftPool() public view returns (uint256) { | |
return _token.balanceOf(address(this)) - getPendingGifts(); | |
} | |
function getPendingGifts() public view returns (uint256) { | |
return _pendingGifts; | |
} | |
function getFarmingTime() public view returns (uint256) { | |
return _giftFarmingTime; | |
} | |
function getTokensPerGift() public view returns (uint256) { | |
return _tokensPerGift; | |
} | |
function getStake(address account) public view returns (uint256) { | |
return _gifts[account].stake; | |
} | |
function getPeriod(address account) public view returns (uint256) { | |
return (block.timestamp - _gifts[account].start); | |
} | |
function getToken() public view returns (address) { | |
return address(_token); | |
} | |
function getReward(address account) public view returns (uint256) { | |
uint256 period = getPeriod(account); | |
uint256 threshold = getFarmingTime(); | |
if (period >= threshold) { | |
uint256 reward = (period / threshold) * getTokensPerGift(); | |
return reward; | |
} else { | |
return 0; | |
} | |
} | |
} |
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
/** | |
*Submitted for verification at Etherscan.io on 2020-08-26 | |
*/ | |
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol | |
pragma solidity ^0.6.2; | |
/** | |
* @dev Interface of the ERC20 standard as defined in the EIP. | |
*/ | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev See {IERC20-maxSupply}. | |
*/ | |
function maxSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
// File: @openzeppelin/contracts/math/SafeMath.sol | |
pragma solidity ^0.6.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. | |
*/ | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
// File: @openzeppelin/contracts/utils/Address.sol | |
pragma solidity ^0.6.2; | |
/** | |
* @dev Collection of functions related to the address type | |
*/ | |
library Address { | |
/** | |
* @dev Returns true if `account` is a contract. | |
* | |
* [IMPORTANT] | |
* ==== | |
* It is unsafe to assume that an address for which this function returns | |
* false is an externally-owned account (EOA) and not a contract. | |
* | |
* Among others, `isContract` will return false for the following | |
* types of addresses: | |
* | |
* - an externally-owned account | |
* - a contract in construction | |
* - an address where a contract will be created | |
* - an address where a contract lived, but was destroyed | |
* ==== | |
*/ | |
function isContract(address account) internal view returns (bool) { | |
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts | |
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned | |
// for accounts without code, i.e. `keccak256('')` | |
bytes32 codehash; | |
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; | |
// solhint-disable-next-line no-inline-assembly | |
assembly { codehash := extcodehash(account) } | |
return (codehash != accountHash && codehash != 0x0); | |
} | |
/** | |
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to | |
* `recipient`, forwarding all available gas and reverting on errors. | |
* | |
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost | |
* of certain opcodes, possibly making contracts go over the 2300 gas limit | |
* imposed by `transfer`, making them unable to receive funds via | |
* `transfer`. {sendValue} removes this limitation. | |
* | |
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. | |
* | |
* IMPORTANT: because control is transferred to `recipient`, care must be | |
* taken to not create reentrancy vulnerabilities. Consider using | |
* {ReentrancyGuard} or the | |
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. | |
*/ | |
function sendValue(address payable recipient, uint256 amount) internal { | |
require(address(this).balance >= amount, "Address: insufficient balance"); | |
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value | |
(bool success, ) = recipient.call{ value: amount }(""); | |
require(success, "Address: unable to send value, recipient may have reverted"); | |
} | |
/** | |
* @dev Performs a Solidity function call using a low level `call`. A | |
* plain`call` is an unsafe replacement for a function call: use this | |
* function instead. | |
* | |
* If `target` reverts with a revert reason, it is bubbled up by this | |
* function (like regular Solidity function calls). | |
* | |
* Returns the raw returned data. To convert to the expected return value, | |
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. | |
* | |
* Requirements: | |
* | |
* - `target` must be a contract. | |
* - calling `target` with `data` must not revert. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
return functionCall(target, data, "Address: low-level call failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with | |
* `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
return _functionCallWithValue(target, data, 0, errorMessage); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], | |
* but also transferring `value` wei to `target`. | |
* | |
* Requirements: | |
* | |
* - the calling contract must have an ETH balance of at least `value`. | |
* - the called Solidity function must be `payable`. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { | |
return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but | |
* with `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { | |
require(address(this).balance >= value, "Address: insufficient balance for call"); | |
return _functionCallWithValue(target, data, value, errorMessage); | |
} | |
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { | |
require(isContract(target), "Address: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data); | |
if (success) { | |
return returndata; | |
} else { | |
// Look for revert reason and bubble it up if present | |
if (returndata.length > 0) { | |
// The easiest way to bubble the revert reason is using memory via assembly | |
// solhint-disable-next-line no-inline-assembly | |
assembly { | |
let returndata_size := mload(returndata) | |
revert(add(32, returndata), returndata_size) | |
} | |
} else { | |
revert(errorMessage); | |
} | |
} | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol | |
// pragma solidity ^0.6.0; | |
/** | |
* @title SafeERC20 | |
* @dev Wrappers around ERC20 operations that throw on failure (when the token | |
* contract returns false). Tokens that return no value (and instead revert or | |
* throw on failure) are also supported, non-reverting calls are assumed to be | |
* successful. | |
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, | |
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc. | |
*/ | |
library SafeERC20 { | |
using SafeMath for uint256; | |
using Address for address; | |
function safeTransfer(IERC20 token, address to, uint256 value) internal { | |
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); | |
} | |
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { | |
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); | |
} | |
/** | |
* @dev Deprecated. This function has issues similar to the ones found in | |
* {IERC20-approve}, and its usage is discouraged. | |
* | |
* Whenever possible, use {safeIncreaseAllowance} and | |
* {safeDecreaseAllowance} instead. | |
*/ | |
function safeApprove(IERC20 token, address spender, uint256 value) internal { | |
// safeApprove should only be called when setting an initial allowance, | |
// or when resetting it to zero. To increase and decrease it, use | |
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance' | |
// solhint-disable-next-line max-line-length | |
require((value == 0) || (token.allowance(address(this), spender) == 0), | |
"SafeERC20: approve from non-zero to non-zero allowance" | |
); | |
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); | |
} | |
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { | |
uint256 newAllowance = token.allowance(address(this), spender).add(value); | |
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); | |
} | |
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { | |
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); | |
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); | |
} | |
/** | |
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement | |
* on the return value: the return value is optional (but if data is returned, it must not be false). | |
* @param token The token targeted by the call. | |
* @param data The call data (encoded using abi.encode or one of its variants). | |
*/ | |
function _callOptionalReturn(IERC20 token, bytes memory data) private { | |
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since | |
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that | |
// the target address contains contract code and also asserts for success in the low-level call. | |
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); | |
if (returndata.length > 0) { // Return data is optional | |
// solhint-disable-next-line max-line-length | |
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); | |
} | |
} | |
} | |
// File: @openzeppelin/contracts/utils/EnumerableSet.sol | |
// pragma solidity ^0.6.0; | |
/** | |
* @dev Library for managing | |
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive | |
* types. | |
* | |
* Sets have the following properties: | |
* | |
* - Elements are added, removed, and checked for existence in constant time | |
* (O(1)). | |
* - Elements are enumerated in O(n). No guarantees are made on the ordering. | |
* | |
* ``` | |
* contract Example { | |
* // Add the library methods | |
* using EnumerableSet for EnumerableSet.AddressSet; | |
* | |
* // Declare a set state variable | |
* EnumerableSet.AddressSet private mySet; | |
* } | |
* ``` | |
* | |
* As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256` | |
* (`UintSet`) are supported. | |
*/ | |
library EnumerableSet { | |
// To implement this library for multiple types with as little code | |
// repetition as possible, we write it in terms of a generic Set type with | |
// bytes32 values. | |
// The Set implementation uses private functions, and user-facing | |
// implementations (such as AddressSet) are just wrappers around the | |
// underlying Set. | |
// This means that we can only create new EnumerableSets for types that fit | |
// in bytes32. | |
struct Set { | |
// Storage of set values | |
bytes32[] _values; | |
// Position of the value in the `values` array, plus 1 because index 0 | |
// means a value is not in the set. | |
mapping (bytes32 => uint256) _indexes; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function _add(Set storage set, bytes32 value) private returns (bool) { | |
if (!_contains(set, value)) { | |
set._values.push(value); | |
// The value is stored at length-1, but we add 1 to all indexes | |
// and use 0 as a sentinel value | |
set._indexes[value] = set._values.length; | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function _remove(Set storage set, bytes32 value) private returns (bool) { | |
// We read and store the value's index to prevent multiple reads from the same storage slot | |
uint256 valueIndex = set._indexes[value]; | |
if (valueIndex != 0) { // Equivalent to contains(set, value) | |
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in | |
// the array, and then remove the last element (sometimes called as 'swap and pop'). | |
// This modifies the order of the array, as noted in {at}. | |
uint256 toDeleteIndex = valueIndex - 1; | |
uint256 lastIndex = set._values.length - 1; | |
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs | |
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. | |
bytes32 lastvalue = set._values[lastIndex]; | |
// Move the last value to the index where the value to delete is | |
set._values[toDeleteIndex] = lastvalue; | |
// Update the index for the moved value | |
set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based | |
// Delete the slot where the moved value was stored | |
set._values.pop(); | |
// Delete the index for the deleted slot | |
delete set._indexes[value]; | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function _contains(Set storage set, bytes32 value) private view returns (bool) { | |
return set._indexes[value] != 0; | |
} | |
/** | |
* @dev Returns the number of values on the set. O(1). | |
*/ | |
function _length(Set storage set) private view returns (uint256) { | |
return set._values.length; | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function _at(Set storage set, uint256 index) private view returns (bytes32) { | |
require(set._values.length > index, "EnumerableSet: index out of bounds"); | |
return set._values[index]; | |
} | |
// AddressSet | |
struct AddressSet { | |
Set _inner; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function add(AddressSet storage set, address value) internal returns (bool) { | |
return _add(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function remove(AddressSet storage set, address value) internal returns (bool) { | |
return _remove(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function contains(AddressSet storage set, address value) internal view returns (bool) { | |
return _contains(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Returns the number of values in the set. O(1). | |
*/ | |
function length(AddressSet storage set) internal view returns (uint256) { | |
return _length(set._inner); | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function at(AddressSet storage set, uint256 index) internal view returns (address) { | |
return address(uint256(_at(set._inner, index))); | |
} | |
// UintSet | |
struct UintSet { | |
Set _inner; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function add(UintSet storage set, uint256 value) internal returns (bool) { | |
return _add(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function remove(UintSet storage set, uint256 value) internal returns (bool) { | |
return _remove(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function contains(UintSet storage set, uint256 value) internal view returns (bool) { | |
return _contains(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Returns the number of values on the set. O(1). | |
*/ | |
function length(UintSet storage set) internal view returns (uint256) { | |
return _length(set._inner); | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function at(UintSet storage set, uint256 index) internal view returns (uint256) { | |
return uint256(_at(set._inner, index)); | |
} | |
} | |
// File: @openzeppelin/contracts/GSN/Context.sol | |
// pragma solidity ^0.6.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. | |
*/ | |
abstract contract Context { | |
function _msgSender() internal view virtual returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view virtual returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
// File: @openzeppelin/contracts/access/Ownable.sol | |
// pragma solidity ^0.6.0; | |
/** | |
* @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. | |
* | |
* By default, the owner account will be the one that deploys the contract. This | |
* can later be changed with {transferOwnership}. | |
* | |
* 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. | |
*/ | |
contract Ownable is Context { | |
address private _owner; | |
event OwnershipTransferred(address indexed previousOwner, address indexed 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. | |
*/ | |
function owner() public view returns (address) { | |
return _owner; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(_owner == _msgSender(), "Ownable: caller is not the 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. | |
*/ | |
function renounceOwnership() public virtual onlyOwner { | |
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. | |
*/ | |
function transferOwnership(address newOwner) public virtual onlyOwner { | |
require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
emit OwnershipTransferred(_owner, newOwner); | |
_owner = newOwner; | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/ERC20.sol | |
// pragma solidity ^0.6.0; | |
/** | |
* @dev Implementation of the {IERC20} interface. | |
* | |
* This implementation is agnostic to the way tokens are created. This means | |
* that a supply mechanism has to be added in a derived contract using {transferFrom}. | |
* | |
* TIP: For a detailed writeup see our guide | |
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How | |
* to implement supply mechanisms]. | |
* | |
* We have followed general OpenZeppelin guidelines: functions revert instead | |
* of returning `false` on failure. This behavior is nonetheless conventional | |
* and does not conflict with the expectations of ERC20 applications. | |
* | |
* Additionally, an {Approval} event is emitted on calls to {transferFrom}. | |
* This allows applications to reconstruct the allowance for all accounts just | |
* by listening to said events. Other implementations of the EIP may not emit | |
* these events, as it isn't required by the specification. | |
* | |
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance} | |
* functions have been added to mitigate the well-known issues around setting | |
* allowances. See {IERC20-approve}. | |
*/ | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint256; | |
using Address for address; | |
mapping (address => uint256) private _balances; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
uint256 private _totalSupply; | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
uint256 public _maxSupply; | |
uint256 public _burn_rate; // in 0.000001% | |
/** | |
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with | |
* a default value of 18. | |
* | |
* To select a different value for {decimals}, use {_setupDecimals}. | |
* | |
* All three of these values are immutable: they can only be set once during | |
* construction. | |
*/ | |
constructor (string memory name, string memory symbol, uint256 maxSupply) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = 18; | |
_maxSupply = maxSupply; | |
} | |
/** | |
* @dev Returns the name of the token. | |
*/ | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev Returns the symbol of the token, usually a shorter version of the | |
* name. | |
*/ | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns the number of decimals used to get its user representation. | |
* For example, if `decimals` equals `2`, a balance of `505` tokens should | |
* be displayed to a user as `5,05` (`505 / 10 ** 2`). | |
* | |
* Tokens usually opt for a value of 18, imitating the relationship between | |
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is | |
* called. | |
* | |
* NOTE: This information is only used for _display_ purposes: it in | |
* no way affects any of the arithmetic of the contract, including | |
* {IERC20-balanceOf} and {IERC20-transfer}. | |
*/ | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
/** | |
* @dev See {IERC20-totalSupply}. | |
*/ | |
function totalSupply() public view override returns (uint256) { | |
return _totalSupply; | |
} | |
/** | |
* @dev See {IERC20-maxSupply}. | |
*/ | |
function maxSupply() public view override returns (uint256) { | |
return _maxSupply; | |
} | |
/** | |
* @dev See {IERC20-balanceOf}. | |
*/ | |
function balanceOf(address account) public view override returns (uint256) { | |
return _balances[account]; | |
} | |
/** | |
* @dev See {IERC20-transfer}. | |
* | |
* Requirements: | |
* | |
* - `recipient` cannot be the zero address. | |
* - the caller must have a balance of at least `amount`. | |
*/ | |
function transfer(address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-allowance}. | |
*/ | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
/** | |
* @dev See {IERC20-approve}. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function approve(address spender, uint256 amount) public virtual override returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-transferFrom}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. This is not | |
* required by the EIP. See the note at the beginning of {ERC20}; | |
* | |
* Requirements: | |
* - `sender` and `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
* - the caller must have allowance for ``sender``'s tokens of at least | |
* `amount`. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(sender, recipient, amount); | |
// _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/** | |
* @dev Atomically increases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
/** | |
* @dev Atomically decreases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
* - `spender` must have allowance for the caller of at least | |
* `subtractedValue`. | |
*/ | |
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* @dev Moves tokens `amount` from `sender` to `recipient`. | |
* | |
* This is internal function is equivalent to {transfer}, and can be used to | |
* e.g. implement automatic token fees, slashing mechanisms, etc. | |
* | |
* Emits a {Transfer} event. | |
* | |
* Requirements: | |
* | |
* - `sender` cannot be the zero address. | |
* - `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
*/ | |
function _transfer(address sender, address recipient, uint256 amount) internal virtual { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
//require(recipient != address(0), "ERC20: transfer to the zero address"); | |
//_beforeTokenTransfer(sender, recipient, amount); | |
uint256 to_burn; | |
// uint256 to_send; | |
to_burn = (amount.mul(_burn_rate)).div(1000000); | |
// to_burn = _amount*_burn_rate/100000; | |
amount = amount - to_burn; | |
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
// _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. | |
* | |
* This is internal function is equivalent to `approve`, and can be used to | |
* e.g. set automatic allowances for certain subsystems, etc. | |
* | |
* Emits an {Approval} event. | |
* | |
* Requirements: | |
* | |
* - `owner` cannot be the zero address. | |
* - `spender` cannot be the zero address. | |
*/ | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* @dev Sets {decimals} to a value other than the default one of 18. | |
* | |
* WARNING: This function should only be called from the constructor. Most | |
* applications that interact with token contracts will not expect | |
* {decimals} to ever change, and may work incorrectly if it does. | |
*/ | |
function _setupDecimals(uint8 decimals_) internal { | |
_decimals = decimals_; | |
} | |
/** | |
* @dev Hook that is called before any transfer of tokens. | |
* | |
* Calling conditions: | |
* | |
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens | |
* will be to transferred to `to`. | |
* | |
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } | |
} | |
// File: contracts/YFSIToken.sol | |
// pragma solidity 0.6.12; | |
// YFSIToken with Governance. | |
contract YFScienceToken is ERC20("YFScience", "YFSI", 120000000e18) { | |
// Copied and modified from YAM code: | |
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol | |
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol | |
// Which is copied and modified from COMPOUND: | |
// https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol | |
/// @notice A record of each accounts delegate | |
mapping (address => address) internal _delegates; | |
/// @notice A checkpoint for marking number of votes from a given block | |
struct Checkpoint { | |
uint32 fromBlock; | |
uint256 votes; | |
} | |
/// @notice A record of votes checkpoints for each account, by index | |
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints; | |
/// @notice The number of checkpoints for each account | |
mapping (address => uint32) public numCheckpoints; | |
/// @notice The EIP-712 typehash for the contract's domain | |
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); | |
/// @notice The EIP-712 typehash for the delegation struct used by the contract | |
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); | |
/// @notice A record of states for signing / validating signatures | |
mapping (address => uint) public nonces; | |
/// @notice An event thats emitted when an account changes its delegate | |
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); | |
/// @notice An event thats emitted when a delegate account's vote balance changes | |
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance); | |
/** | |
* @notice Delegate votes from `msg.sender` to `delegatee` | |
* @param delegator The address to get delegatee for | |
*/ | |
function delegates(address delegator) | |
external | |
view | |
returns (address) | |
{ | |
return _delegates[delegator]; | |
} | |
/** | |
* @notice Delegate votes from `msg.sender` to `delegatee` | |
* @param delegatee The address to delegate votes to | |
*/ | |
function delegate(address delegatee) external { | |
return _delegate(msg.sender, delegatee); | |
} | |
/** | |
* @notice Delegates votes from signatory to `delegatee` | |
* @param delegatee The address to delegate votes to | |
* @param nonce The contract state required to match the signature | |
* @param expiry The time at which to expire the signature | |
* @param v The recovery byte of the signature | |
* @param r Half of the ECDSA signature pair | |
* @param s Half of the ECDSA signature pair | |
*/ | |
function delegateBySig( | |
address delegatee, | |
uint nonce, | |
uint expiry, | |
uint8 v, | |
bytes32 r, | |
bytes32 s | |
) | |
external | |
{ | |
bytes32 domainSeparator = keccak256( | |
abi.encode( | |
DOMAIN_TYPEHASH, | |
keccak256(bytes(name())), | |
getChainId(), | |
address(this) | |
) | |
); | |
bytes32 structHash = keccak256( | |
abi.encode( | |
DELEGATION_TYPEHASH, | |
delegatee, | |
nonce, | |
expiry | |
) | |
); | |
bytes32 digest = keccak256( | |
abi.encodePacked( | |
"\x19\x01", | |
domainSeparator, | |
structHash | |
) | |
); | |
address signatory = ecrecover(digest, v, r, s); | |
require(signatory != address(0), "YFSI::delegateBySig: invalid signature"); | |
require(nonce == nonces[signatory]++, "YFSI::delegateBySig: invalid nonce"); | |
require(now <= expiry, "YFSI::delegateBySig: signature expired"); | |
return _delegate(signatory, delegatee); | |
} | |
/** | |
* @notice Gets the current votes balance for `account` | |
* @param account The address to get votes balance | |
* @return The number of current votes for `account` | |
*/ | |
function getCurrentVotes(address account) | |
external | |
view | |
returns (uint256) | |
{ | |
uint32 nCheckpoints = numCheckpoints[account]; | |
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0; | |
} | |
/** | |
* @notice Determine the prior number of votes for an account as of a block number | |
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation. | |
* @param account The address of the account to check | |
* @param blockNumber The block number to get the vote balance at | |
* @return The number of votes the account had as of the given block | |
*/ | |
function getPriorVotes(address account, uint blockNumber) | |
external | |
view | |
returns (uint256) | |
{ | |
require(blockNumber < block.number, "YFSI::getPriorVotes: not yet determined"); | |
uint32 nCheckpoints = numCheckpoints[account]; | |
if (nCheckpoints == 0) { | |
return 0; | |
} | |
// First check most recent balance | |
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) { | |
return checkpoints[account][nCheckpoints - 1].votes; | |
} | |
// Next check implicit zero balance | |
if (checkpoints[account][0].fromBlock > blockNumber) { | |
return 0; | |
} | |
uint32 lower = 0; | |
uint32 upper = nCheckpoints - 1; | |
while (upper > lower) { | |
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow | |
Checkpoint memory cp = checkpoints[account][center]; | |
if (cp.fromBlock == blockNumber) { | |
return cp.votes; | |
} else if (cp.fromBlock < blockNumber) { | |
lower = center; | |
} else { | |
upper = center - 1; | |
} | |
} | |
return checkpoints[account][lower].votes; | |
} | |
function _delegate(address delegator, address delegatee) | |
internal | |
{ | |
address currentDelegate = _delegates[delegator]; | |
uint256 delegatorBalance = balanceOf(delegator); // balance of underlying YFSIs (not scaled); | |
_delegates[delegator] = delegatee; | |
emit DelegateChanged(delegator, currentDelegate, delegatee); | |
_moveDelegates(currentDelegate, delegatee, delegatorBalance); | |
} | |
function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal { | |
if (srcRep != dstRep && amount > 0) { | |
if (srcRep != address(0)) { | |
// decrease old representative | |
uint32 srcRepNum = numCheckpoints[srcRep]; | |
uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0; | |
uint256 srcRepNew = srcRepOld.sub(amount); | |
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew); | |
} | |
if (dstRep != address(0)) { | |
// increase new representative | |
uint32 dstRepNum = numCheckpoints[dstRep]; | |
uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0; | |
uint256 dstRepNew = dstRepOld.add(amount); | |
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew); | |
} | |
} | |
} | |
function _writeCheckpoint( | |
address delegatee, | |
uint32 nCheckpoints, | |
uint256 oldVotes, | |
uint256 newVotes | |
) | |
internal | |
{ | |
uint32 blockNumber = safe32(block.number, "YFSI::_writeCheckpoint: block number exceeds 32 bits"); | |
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) { | |
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes; | |
} else { | |
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes); | |
numCheckpoints[delegatee] = nCheckpoints + 1; | |
} | |
emit DelegateVotesChanged(delegatee, oldVotes, newVotes); | |
} | |
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) { | |
require(n < 2**32, errorMessage); | |
return uint32(n); | |
} | |
function getChainId() internal pure returns (uint) { | |
uint256 chainId; | |
assembly { chainId := chainid() } | |
return chainId; | |
} | |
} | |
// File: contracts/StakingContract.sol | |
// pragma solidity 0.6.12; | |
interface IMigratorChef { | |
// Take the current LP token address and return the new LP token address. | |
// Migrator should have full access to the caller's LP token. | |
// Return the new LP token address. | |
// | |
// XXX Migrator must have allowance access to UniswapV2 LP tokens. | |
// do that so be careful! | |
function migrate(IERC20 token) external returns (IERC20); | |
} | |
// Note that it's ownable and the owner wields tremendous power. The ownership | |
// will be transferred to a governance smart contract once YFSI is sufficiently | |
// distributed and the community can show to govern itself. | |
// | |
// Have fun reading it. Hopefully it's bug-free. God bless. | |
contract StakingContract is Ownable { | |
using SafeMath for uint256; | |
using SafeERC20 for IERC20; | |
// Info of each user. | |
struct UserInfo { | |
uint256 amount; // How many LP tokens the user has provided. | |
uint256 rewardDebt; // Reward debt. See explanation below. | |
// | |
// We do some fancy math here. Basically, any point in time, the amount of Yfsis | |
// entitled to a user but is pending to be distributed is: | |
// | |
// pending reward = (user.amount * pool.accYfsisPerShare) - user.rewardDebt | |
// | |
// Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: | |
// 1. The pool's `accYfsisPerShare` (and `lastRewardBlock`) gets updated. | |
// 2. User receives the pending reward sent to his/her address. | |
// 3. User's `amount` gets updated. | |
// 4. User's `rewardDebt` gets updated. | |
} | |
// Info of each pool. | |
struct PoolInfo { | |
IERC20 lpToken; // Address of LP token contract. | |
uint256 allocPoint; // How many allocation points assigned to this pool. YFSIs to distribute per block. | |
uint256 accYfsiPerShare; // Accumulated Yfsis per share, times 1e12. See below. | |
} | |
uint256 public user_amount; | |
uint256 public user_yfsi; | |
// The YFSI TOKEN! | |
YFScienceToken public yfsi; | |
// Dev address. | |
address public devaddr; | |
// The migrator contract. It has a lot of power. Can only be set through governance (owner). | |
IMigratorChef public migrator; | |
//uint256 public burn_rate; | |
address public yfsi_owner; | |
// Info of each pool. | |
PoolInfo[] public poolInfo; | |
// Info of each user that stakes LP tokens. | |
mapping (uint256 => mapping (address => UserInfo)) public userInfo; | |
// Total allocation poitns. Must be the sum of all allocation points in all pools. | |
uint256 public totalAllocPoint = 0; | |
// The block number when YFSI mining starts. | |
event Deposit(address indexed user, uint256 indexed pid, uint256 amount); | |
event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); | |
event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount); | |
constructor( | |
YFScienceToken _yfsi, | |
address _yfsi_owner | |
) public { | |
yfsi = _yfsi; | |
yfsi_owner = _yfsi_owner; | |
} | |
function poolLength() external view returns (uint256) { | |
return poolInfo.length; | |
} | |
// Add a new lp to the pool. Can only be called by the owner. | |
// XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do. | |
function add(uint256 _allocPoint, IERC20 _lpToken, bool _withUpdate) public { | |
totalAllocPoint = totalAllocPoint.add(_allocPoint); | |
poolInfo.push(PoolInfo({ | |
lpToken: _lpToken, | |
allocPoint: _allocPoint, | |
accYfsiPerShare: 0 | |
})); | |
} | |
// Update the given pool's SPUD allocation point. Can only be called by the owner. | |
function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public { | |
totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint); | |
poolInfo[_pid].allocPoint = _allocPoint; | |
} | |
// Set the migrator contract. Can only be called by the owner. | |
function setMigrator(IMigratorChef _migrator) public { | |
migrator = _migrator; | |
} | |
// Migrate lp token to another lp contract. Can be called by anyone. We trust that migrator contract is good. | |
function migrate(uint256 _pid) public { | |
require(address(migrator) != address(0), "migrate: no migrator"); | |
PoolInfo storage pool = poolInfo[_pid]; | |
IERC20 lpToken = pool.lpToken; | |
uint256 bal = lpToken.balanceOf(address(this)); | |
lpToken.safeApprove(address(migrator), bal); | |
IERC20 newLpToken = migrator.migrate(lpToken); | |
require(bal == newLpToken.balanceOf(address(this)), "migrate: bad"); | |
pool.lpToken = newLpToken; | |
} | |
// View function to see pending SPUDs on frontend. | |
function pendingYfsi(uint256 _pid, address _user) external view returns (uint256) { | |
PoolInfo storage pool = poolInfo[_pid]; | |
UserInfo storage user = userInfo[_pid][_user]; | |
uint256 accYfsiPerShare = pool.accYfsiPerShare; | |
return user.amount.mul(accYfsiPerShare).div(1e12).sub(user.rewardDebt); | |
} | |
// Update reward variables of the given pool to be up-to-date. | |
function updatePoolReward(uint256 _pid, uint256 _reward) public onlyOwner { | |
PoolInfo storage pool = poolInfo[_pid]; | |
uint256 lpSupply = pool.lpToken.balanceOf(address(this)); | |
uint256 yfsiReward = _reward; | |
yfsi.transferFrom(yfsi_owner , address(this), yfsiReward.div(1e18)); | |
pool.accYfsiPerShare = pool.accYfsiPerShare.add(yfsiReward.mul(1e12).div(lpSupply)); | |
} | |
// Deposit LP tokens to StakingContract for YFSI allocation. | |
function deposit(uint256 _pid, uint256 _amount) public { | |
PoolInfo storage pool = poolInfo[_pid]; | |
UserInfo storage user = userInfo[_pid][msg.sender]; | |
if (user.amount > 0) { | |
uint256 pending = user.amount.mul(pool.accYfsiPerShare).div(1e12).sub(user.rewardDebt); | |
safeYfsiTransfer(msg.sender, pending); | |
} | |
pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount); | |
user.amount = user.amount.add(_amount); | |
user.rewardDebt = user.amount.mul(pool.accYfsiPerShare).div(1e12); | |
emit Deposit(msg.sender, _pid, _amount); | |
} | |
// Withdraw LP tokens from StakingContract. | |
function withdraw(uint256 _pid, uint256 _amount) public { | |
PoolInfo storage pool = poolInfo[_pid]; | |
UserInfo storage user = userInfo[_pid][msg.sender]; | |
require(user.amount >= _amount, "withdraw: not good"); | |
//updatePool(_pid); | |
uint256 pending = user.amount.mul(pool.accYfsiPerShare).div(1e12).sub(user.rewardDebt); | |
safeYfsiTransfer(msg.sender, pending); | |
user.amount = user.amount.sub(_amount); | |
user.rewardDebt = user.amount.mul(pool.accYfsiPerShare).div(1e12); | |
pool.lpToken.safeTransfer(address(msg.sender), _amount); | |
emit Withdraw(msg.sender, _pid, _amount); | |
} | |
// Withdraw without caring about rewards. EMERGENCY ONLY. | |
function emergencyWithdraw(uint256 _pid) public { | |
PoolInfo storage pool = poolInfo[_pid]; | |
UserInfo storage user = userInfo[_pid][msg.sender]; | |
pool.lpToken.safeTransfer(address(msg.sender), user.amount); | |
emit EmergencyWithdraw(msg.sender, _pid, user.amount); | |
user.amount = 0; | |
user.rewardDebt = 0; | |
} | |
// Safe YFSI transfer function, just in case if rounding error causes pool to not have enough YFSIs. | |
function safeYfsiTransfer(address _to, uint256 _amount) internal { | |
uint256 yfsiBal = yfsi.balanceOf(address(this)); | |
if (_amount > yfsiBal) { | |
yfsi.transfer(_to, yfsiBal); | |
} else { | |
yfsi.transfer(_to, _amount); | |
} | |
} | |
// Update dev address by the previous dev. | |
function dev(address _devaddr) public { | |
require(msg.sender == devaddr, "dev: wut?"); | |
devaddr = _devaddr; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for sharing