pragma solidity 0.5.17;
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 ERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address, uint) external returns (bool);
function allowance(address owner, address spender) external view returns (uint);
function approve(address, uint) external returns (bool);
function transferFrom(address, address, uint) external returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}
interface POWER {
function scaledPower(uint amount) external returns(bool);
function totalPopping() external view returns (uint256);
}
interface OPERATORS {
function scaledOperators(uint amount) external returns(bool);
function totalPopping() external view returns (uint256);
}
//======================================POPCORN CONTRACT=========================================//
contract PopcornToken is ERC20 {
using SafeMath for uint256;
//======================================POPCORN EVENTS=========================================//
event BurnEvent(address indexed pool, address indexed burnaddress, uint amount);
event AddCornEvent(address indexed _from, address indexed pool, uint value);
// ERC-20 Parameters
string public name;
string public symbol;
uint public decimals;
uint public totalSupply;
//======================================POPPING POOLS=========================================//
address public pool1;
address public pool2;
uint256 public power;
uint256 public operators;
uint256 operatorstotalpopping;
uint256 powertotalpopping;
// ERC-20 Mappings
mapping(address => uint) public balanceOf;
mapping(address => mapping(address => uint)) public allowance;
// Public Parameters
uint corns;
uint bValue;
uint actualValue;
uint burnAmount;
address administrator;
// Public Mappings
mapping(address=>bool) public Whitelisted;
//=====================================CREATION=========================================//
// Constructor
constructor() public {
name = "Popcorn Token";
symbol = "CORN";
decimals = 18;
corns = 1*10**decimals;
totalSupply = 2000000*corns;
administrator = msg.sender;
balanceOf[administrator] = totalSupply;
emit Transfer(administrator, address(this), totalSupply);
Whitelisted[administrator] = true;
}
//========================================CONFIGURATIONS=========================================//
function machineries(address _power, address _operators) public onlyAdministrator returns (bool success) {
pool1 = _power;
pool2 = _operators;
return true;
}
modifier onlyAdministrator() {
require(msg.sender == administrator, "Ownable: caller is not the owner");
_;
}
modifier onlyOperators() {
require(msg.sender == pool2, "Authorization: Only the operators pool can call on this");
_;
}
function whitelist(address _address) public onlyAdministrator returns (bool success) {
Whitelisted[_address] = true;
return true;
}
function unwhitelist(address _address) public onlyAdministrator returns (bool success) {
Whitelisted[_address] = false;
return true;
}
function Burn(uint _amount) public returns (bool success) {
require(balanceOf[msg.sender] >= _amount, "You do not have the amount of tokens you wanna burn in your wallet");
balanceOf[msg.sender] -= _amount;
totalSupply -= _amount;
emit BurnEvent(pool2, address(0x0), _amount);
return true;
}
//========================================ERC20=========================================//
// ERC20 Transfer function
function transfer(address to, uint value) public returns (bool success) {
_transfer(msg.sender, to, value);
return true;
}
// ERC20 Approve function
function approve(address spender, uint value) public returns (bool success) {
allowance[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
// ERC20 TransferFrom function
function transferFrom(address from, address to, uint value) public returns (bool success) {
require(value <= allowance[from][msg.sender], 'Must not send more than allowance');
allowance[from][msg.sender] -= value;
_transfer(from, to, value);
return true;
}
function _transfer(address _from, address _to, uint _value) private {
require(balanceOf[_from] >= _value, 'Must not send more than balance');
require(balanceOf[_to] + _value >= balanceOf[_to], 'Balance overflow');
balanceOf[_from] -= _value;
if(Whitelisted[msg.sender]){
actualValue = _value;
}else{
bValue = mulDiv(_value, 10, 100);
actualValue = _value.sub(bValue);
power = mulDiv(bValue, 50, 100);
powertotalpopping = powerTotalPopping();
if(powertotalpopping > 0){
POWER(pool1).scaledPower(power);
balanceOf[pool1] += power;
emit AddCornEvent(_from, pool1, power);
emit Transfer(_from, pool1, power);
}else{
totalSupply -= power;
emit BurnEvent(_from, address(0x0), power);
}
operators = mulDiv(bValue, 30, 100);
operatorstotalpopping = OperatorsTotalPopping();
if(operatorstotalpopping > 0){
OPERATORS(pool2).scaledOperators(operators);
balanceOf[pool2] += operators;
emit AddCornEvent(_from, pool2, operators);
emit Transfer(_from, pool2, operators);
}else{
totalSupply -= operators;
emit BurnEvent(_from, address(0x0), operators);
}
burnAmount = mulDiv(bValue, 20, 100);
totalSupply -= burnAmount;
emit BurnEvent(_from, address(0x0), burnAmount);
}
balanceOf[_to] += actualValue;
emit Transfer(_from, _to, _value);
}
function powerTotalPopping() public view returns(uint){
return POWER(pool1).totalPopping();
}
function OperatorsTotalPopping() public view returns(uint){
return OPERATORS(pool2).totalPopping();
}
function mulDiv (uint x, uint y, uint z) public pure returns (uint) {
(uint l, uint h) = fullMul (x, y);
assert (h < z);
uint mm = mulmod (x, y, z);
if (mm > l) h -= 1;
l -= mm;
uint pow2 = z & -z;
z /= pow2;
l /= pow2;
l += h * ((-pow2) / pow2 + 1);
uint r = 1;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
return l * r;
}
function fullMul (uint x, uint y) private pure returns (uint l, uint h) {
uint mm = mulmod (x, y, uint (-1));
l = x * y;
h = mm - l;
if (mm < l) h -= 1;
}
}
{
"compilationTarget": {
"PopcornToken.sol": "PopcornToken"
},
"evmVersion": "istanbul",
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"AddCornEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"burnaddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BurnEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Burn","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"OperatorsTotalPopping","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"Whitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_power","type":"address"},{"internalType":"address","name":"_operators","type":"address"}],"name":"machineries","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"},{"internalType":"uint256","name":"z","type":"uint256"}],"name":"mulDiv","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"operators","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pool1","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pool2","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"power","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"powerTotalPopping","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"unwhitelist","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"whitelist","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]