AXIA Protocol is a Decentralized platform for Cryptocurrency Index Fund management which presents cryptocurrency enthusiasts/investors with opportunities of one-time investments in baskets of cryptocurrencies (Axia Funds) saving them time and energy that would have been spent sifting through thousands of tokens in search of which ones to buy for a portfolio. With Axia Funds, investors can be rest assured that their portfolio will only grow in proļ¬ts over time.
AXIA Protocol consists of 7 Smart Contracts: The Protocol's token contract includes all the standard ERC20 functions as defined in the ERC20 protocol by the Ethereum Foundation.
Additional features included in the contract:
The token contract contains no mint function, so the supply of the token shall never increase. There is a burn function which could decrease the token's total supply.
Ownership/Adminship - Some functions are protected and can only be called by the contract Owner/Administrator.
Owners have the ability to update the rate variables for pools.
Utilization of SafeMath to prevent overflows.
Audit Findings Summary
Overall, no serious security issues were identified.
The contract uses an assert check instead of a require check in the mulDiv() and scaledToken()functions. This is out of line with Solidity best practices, but in this case the usage poses no issue to the integrity of the contract.
The _minStakeAmount(), poolconfigs(), unstakeburnrate() and poolpercentages() functions are technically vulnerable to an arithmetic overflow, but it entirely in the control of the contract owner and thus no security issue is present.
We ran over 400,000 transactions interacting with this suite of contracts on a test blockchain to determine these results. Date: October 22nd, 2020
Vulnerability Category
Notes
Result
Arbitrary Storage Write
N/A
PASS
Arbitrary Jump
N/A
PASS
Delegate Call to Untrusted Contract
N/A
PASS
Dependence on Predictable Variables
N/A
PASS
Deprecated Opcodes
N/A
PASS
Ether Thief
N/A
PASS
Exceptions
N/A
PASS
External Calls
N/A
PASS
Integer Over/Underflow
N/A
PASS
Multiple Sends
N/A
PASS
Suicide
N/A
PASS
State Change External Calls
N/A
PASS
Unchecked Retval
N/A
PASS
User Supplied Assertion
A user can trigger an assertion violation due to SafeMath's interger overflow protections, but their transaction will revert safely.
/**
*Submitted for verification at Etherscan.io on 2020-10-09
*/
/*
* @dev This is the Axia Protocol Staking pool contract (AXIA LONE Pool), a part of the protocol where stakers are rewarded in AXIA tokens
* when they make stakes of Axia tokens.
* stakers reward come from the daily emission from the total supply into circulation,
* this happens daily and upon the reach of a new epoch each made of 180 days,
* halvings are experienced on the emitting amount of tokens.
* on the 11th epoch all the tokens would have been completed emitted into circulation,
* from here on, the stakers will still be earning from daily emissions
* which would now be coming from the accumulated basis points over the epochs.
* upon unstaking, stakers are charged a fee of 1% of their unstaking sum which is
* burnt forever, thereby reducing the total supply. this gives the Axia token its deflationary feature.
*/
pragma solidity 0.6.4;
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);
function supplyeffect(uint _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 {
/**
* @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 ASP{
using SafeMath for uint256;
//======================================EVENTS=========================================//
event StakeEvent(address indexed staker, address indexed pool, uint amount);
event UnstakeEvent(address indexed unstaker, address indexed pool, uint amount);
event RewardEvent(address indexed staker, address indexed pool, uint amount);
event RewardStake(address indexed staker, address indexed pool, uint amount);
//======================================STAKING POOL=========================================//
address public Axiatoken;
bool public stakingEnabled;
uint256 constant private FLOAT_SCALAR = 2**64;
uint256 public MINIMUM_STAKE = 1000000000000000000; // 1000 AXIA Tokens
uint256 public MIN_DIVIDENDS_DUR = 18 hours;
uint256 private UNSTAKE_FEE = 1; //1% burns when you unstake
uint public infocheck;
uint _burnedAmount;
uint actualValue;
struct User {
uint256 balance;
uint256 frozen;
int256 scaledPayout;
uint256 staketime;
}
struct Info {
uint256 totalSupply;
uint256 totalFrozen;
mapping(address => User) users;
uint256 scaledPayoutPerToken; //pool balance
address admin;
}
Info private info;
constructor() public {
info.admin = msg.sender;
stakingEnabled = false;
}
//======================================ADMINSTRATION=========================================//
modifier onlyCreator() {
require(msg.sender == info.admin, "Ownable: caller is not the administrator");
_;
}
modifier onlyAxiaToken() {
require(msg.sender == Axiatoken, "Authorization: only token contract can call");
_;
}
function tokenconfigs(address _axiatoken) public onlyCreator returns (bool success) {
Axiatoken = _axiatoken;
return true;
}
function _minStakeAmount(uint256 _number) onlyCreator public {
MINIMUM_STAKE = _number*1000000000000000000;
}
function stakingStatus(bool _status) public onlyCreator {
require(Axiatoken != address(0), "Pool address is not yet setup");
stakingEnabled = _status;
}
function unstakeburnrate(uint _rate) public onlyCreator returns (bool success) {
UNSTAKE_FEE = _rate;
return true;
}
function MIN_DIVIDENDS_DUR_TIME(uint256 _minDuration) public onlyCreator {
MIN_DIVIDENDS_DUR = _minDuration;
}
//======================================USER WRITE=========================================//
function StakeAxiaTokens(uint256 _tokens) external {
_stake(_tokens);
}
function UnstakeAxiaTokens(uint256 _tokens) external {
_unstake(_tokens);
}
//======================================USER READ=========================================//
function totalFrozen() public view returns (uint256) {
return info.totalFrozen;
}
function frozenOf(address _user) public view returns (uint256) {
return info.users[_user].frozen;
}
function dividendsOf(address _user) public view returns (uint256) {
if(info.users[_user].staketime < MIN_DIVIDENDS_DUR){
return 0;
}else{
return uint256(int256(info.scaledPayoutPerToken * info.users[_user].frozen) - info.users[_user].scaledPayout) / FLOAT_SCALAR;
}
}
function userData(address _user) public view
returns (uint256 totalTokensFrozen, uint256 userFrozen,
uint256 userDividends, uint256 userStaketime, int256 scaledPayout) {
return (totalFrozen(), frozenOf(_user), dividendsOf(_user), info.users[_user].staketime, info.users[_user].scaledPayout);
}
//======================================ACTION CALLS=========================================//
function _stake(uint256 _amount) internal {
require(stakingEnabled, "Staking not yet initialized");
require(IERC20(Axiatoken).balanceOf(msg.sender) >= _amount, "Insufficient Axia token balance");
require(frozenOf(msg.sender) + _amount >= MINIMUM_STAKE, "Your amount is lower than the minimum amount allowed to stake");
require(IERC20(Axiatoken).allowance(msg.sender, address(this)) >= _amount, "Not enough allowance given to contract yet to spend by user");
info.users[msg.sender].staketime = now;
info.totalFrozen += _amount;
info.users[msg.sender].frozen += _amount;
info.users[msg.sender].scaledPayout += int256(_amount * info.scaledPayoutPerToken);
IERC20(Axiatoken).transferFrom(msg.sender, address(this), _amount); // Transfer liquidity tokens from the sender to this contract
emit StakeEvent(msg.sender, address(this), _amount);
}
function _unstake(uint256 _amount) internal {
require(frozenOf(msg.sender) >= _amount, "You currently do not have up to that amount staked");
info.totalFrozen -= _amount;
info.users[msg.sender].frozen -= _amount;
info.users[msg.sender].scaledPayout -= int256(_amount * info.scaledPayoutPerToken);
_burnedAmount = mulDiv(_amount, UNSTAKE_FEE, 100);
actualValue = _amount.sub(_burnedAmount);
require(IERC20(Axiatoken).transfer(msg.sender, actualValue), "Transaction failed");
emit UnstakeEvent(address(this), msg.sender, actualValue);
require(IERC20(Axiatoken).transfer(address(0x0), _burnedAmount), "Transaction failed");
IERC20(Axiatoken).supplyeffect(_burnedAmount);
TakeDividends();
}
function TakeDividends() public returns (uint256) {
uint256 _dividends = dividendsOf(msg.sender);
require(_dividends >= 0, "you do not have any dividend yet");
info.users[msg.sender].scaledPayout += int256(_dividends * FLOAT_SCALAR);
require(IERC20(Axiatoken).transfer(msg.sender, _dividends), "Transaction Failed"); // Transfer dividends to msg.sender
emit RewardEvent(msg.sender, address(this), _dividends);
return _dividends;
}
function scaledToken(uint _amount) external onlyAxiaToken returns(bool){
info.scaledPayoutPerToken += _amount * FLOAT_SCALAR / info.totalFrozen;
infocheck = info.scaledPayoutPerToken;
return true;
}
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;
}
}
/**
*Submitted for verification at Etherscan.io on 2020-10-09
*/
/*
* @dev This is the Axia Protocol Staking pool 2 contract (Defi Fund Pool),
* a part of the protocol where stakers are rewarded in AXIA tokens
* when they make stakes of liquidity tokens from the oracle pool.
* stakers reward come from the daily emission from the total supply into circulation,
* this happens daily and upon the reach of a new epoch each made of 180 days,
* halvings are experienced on the emitting amount of tokens.
* on the 11th epoch all the tokens would have been completed emitted into circulation,
* from here on, the stakers will still be earning from daily emissions
* which would now be coming from the accumulated basis points over the epochs.
* stakers are not charged any fee for unstaking.
*/
pragma solidity 0.6.4;
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 {
/**
* @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 DSP{
using SafeMath for uint256;
//======================================EVENTS=========================================//
event StakeEvent(address indexed staker, address indexed pool, uint amount);
event UnstakeEvent(address indexed unstaker, address indexed pool, uint amount);
event RewardEvent(address indexed staker, address indexed pool, uint amount);
event RewardStake(address indexed staker, address indexed pool, uint amount);
//======================================STAKING POOLS=========================================//
address public Axiatoken;
address public DefiIndexFunds;
address public administrator;
bool public stakingEnabled;
uint256 constant private FLOAT_SCALAR = 2**64;
uint256 public MINIMUM_STAKE = 1000000000000000000; // 1 minimum
uint256 public MIN_DIVIDENDS_DUR = 18 hours;
uint public infocheck;
struct User {
uint256 balance;
uint256 frozen;
int256 scaledPayout;
uint256 staketime;
}
struct Info {
uint256 totalSupply;
uint256 totalFrozen;
mapping(address => User) users;
uint256 scaledPayoutPerToken; //pool balance
address admin;
}
Info private info;
constructor() public {
info.admin = msg.sender;
stakingEnabled = false;
}
//======================================ADMINSTRATION=========================================//
modifier onlyCreator() {
require(msg.sender == info.admin, "Ownable: caller is not the administrator");
_;
}
modifier onlyAxiaToken() {
require(msg.sender == Axiatoken, "Authorization: only token contract can call");
_;
}
function tokenconfigs(address _axiatoken, address _defiindex) public onlyCreator returns (bool success) {
require(_axiatoken != _defiindex, "Insertion of same address is not supported");
require(_axiatoken != address(0) && _defiindex != address(0), "Insertion of address(0) is not supported");
Axiatoken = _axiatoken;
DefiIndexFunds = _defiindex;
return true;
}
function _minStakeAmount(uint256 _number) onlyCreator public {
MINIMUM_STAKE = _number*1000000000000000000;
}
function stakingStatus(bool _status) public onlyCreator {
require(Axiatoken != address(0) && DefiIndexFunds != address(0), "Pool addresses are not yet setup");
stakingEnabled = _status;
}
function MIN_DIVIDENDS_DUR_TIME(uint256 _minDuration) public onlyCreator {
MIN_DIVIDENDS_DUR = _minDuration;
}
//======================================USER WRITE=========================================//
function StakeTokens(uint256 _tokens) external {
_stake(_tokens);
}
function UnstakeTokens(uint256 _tokens) external {
_unstake(_tokens);
}
//======================================USER READ=========================================//
function totalFrozen() public view returns (uint256) {
return info.totalFrozen;
}
function frozenOf(address _user) public view returns (uint256) {
return info.users[_user].frozen;
}
function dividendsOf(address _user) public view returns (uint256) {
if(info.users[_user].staketime < MIN_DIVIDENDS_DUR){
return 0;
}else{
return uint256(int256(info.scaledPayoutPerToken * info.users[_user].frozen) - info.users[_user].scaledPayout) / FLOAT_SCALAR;
}
}
function userData(address _user) public view
returns (uint256 totalTokensFrozen, uint256 userFrozen,
uint256 userDividends, uint256 userStaketime, int256 scaledPayout) {
return (totalFrozen(), frozenOf(_user), dividendsOf(_user), info.users[_user].staketime, info.users[_user].scaledPayout);
}
//======================================ACTION CALLS=========================================//
function _stake(uint256 _amount) internal {
require(stakingEnabled, "Staking not yet initialized");
require(IERC20(DefiIndexFunds).balanceOf(msg.sender) >= _amount, "Insufficient DeFi AFT balance");
require(frozenOf(msg.sender) + _amount >= MINIMUM_STAKE, "Your amount is lower than the minimum amount allowed to stake");
require(IERC20(DefiIndexFunds).allowance(msg.sender, address(this)) >= _amount, "Not enough allowance given to contract yet to spend by user");
info.users[msg.sender].staketime = now;
info.totalFrozen += _amount;
info.users[msg.sender].frozen += _amount;
info.users[msg.sender].scaledPayout += int256(_amount * info.scaledPayoutPerToken);
IERC20(DefiIndexFunds).transferFrom(msg.sender, address(this), _amount); // Transfer liquidity tokens from the sender to this contract
emit StakeEvent(msg.sender, address(this), _amount);
}
function _unstake(uint256 _amount) internal {
require(frozenOf(msg.sender) >= _amount, "You currently do not have up to that amount staked");
info.totalFrozen -= _amount;
info.users[msg.sender].frozen -= _amount;
info.users[msg.sender].scaledPayout -= int256(_amount * info.scaledPayoutPerToken);
require(IERC20(DefiIndexFunds).transfer(msg.sender, _amount), "Transaction failed");
emit UnstakeEvent(address(this), msg.sender, _amount);
TakeDividends();
}
function TakeDividends() public returns (uint256) {
uint256 _dividends = dividendsOf(msg.sender);
require(_dividends >= 0, "you do not have any dividend yet");
info.users[msg.sender].scaledPayout += int256(_dividends * FLOAT_SCALAR);
require(IERC20(Axiatoken).transfer(msg.sender, _dividends), "Transaction Failed"); // Transfer dividends to msg.sender
emit RewardEvent(msg.sender, address(this), _dividends);
return _dividends;
}
function scaledToken(uint _amount) external onlyAxiaToken returns(bool){
info.scaledPayoutPerToken += _amount * FLOAT_SCALAR / info.totalFrozen;
infocheck = info.scaledPayoutPerToken;
return true;
}
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;
}
}
/**
*Submitted for verification at Etherscan.io on 2020-10-09
*/
/*
* @dev This is the Axia Protocol Staking pool 1 contract (Oracle FUND Pool),
* a part of the protocol where stakers are rewarded in AXIA tokens
* when they make stakes of liquidity tokens from the oracle pool.
* stakers reward come from the daily emission from the total supply into circulation,
* this happens daily and upon the reach of a new epoch each made of 180 days,
* halvings are experienced on the emitting amount of tokens.
* on the 11th epoch all the tokens would have been completed emitted into circulation,
* from here on, the stakers will still be earning from daily emissions
* which would now be coming from the accumulated basis points over the epochs.
* stakers are not charged any fee for unstaking.
*/
pragma solidity 0.6.4;
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 {
/**
* @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 OSP{
using SafeMath for uint256;
//======================================EVENTS=========================================//
event StakeEvent(address indexed staker, address indexed pool, uint amount);
event UnstakeEvent(address indexed unstaker, address indexed pool, uint amount);
event RewardEvent(address indexed staker, address indexed pool, uint amount);
event RewardStake(address indexed staker, address indexed pool, uint amount);
//======================================STAKING POOLS=========================================//
address public Axiatoken;
address public OracleIndexFunds;
address public administrator;
bool public stakingEnabled;
uint256 constant private FLOAT_SCALAR = 2**64;
uint256 public MINIMUM_STAKE = 1000000000000000000; // 1 minimum
uint256 public MIN_DIVIDENDS_DUR = 18 hours;
uint public infocheck;
struct User {
uint256 balance;
uint256 frozen;
int256 scaledPayout;
uint256 staketime;
}
struct Info {
uint256 totalSupply;
uint256 totalFrozen;
mapping(address => User) users;
uint256 scaledPayoutPerToken;
address admin;
}
Info private info;
constructor() public {
info.admin = msg.sender;
stakingEnabled = false;
}
//======================================ADMINSTRATION=========================================//
modifier onlyCreator() {
require(msg.sender == info.admin, "Ownable: caller is not the administrator");
_;
}
modifier onlyAxiaToken() {
require(msg.sender == Axiatoken, "Authorization: only token contract can call");
_;
}
function tokenconfigs(address _axiatoken, address _oracleindex) public onlyCreator returns (bool success) {
require(_axiatoken != _oracleindex, "Insertion of same address is not supported");
require(_axiatoken != address(0) && _oracleindex != address(0), "Insertion of address(0) is not supported");
Axiatoken = _axiatoken;
OracleIndexFunds = _oracleindex;
return true;
}
function _minStakeAmount(uint256 _number) onlyCreator public {
MINIMUM_STAKE = _number*1000000000000000000;
}
function stakingStatus(bool _status) public onlyCreator {
require(Axiatoken != address(0) && OracleIndexFunds != address(0), "Pool addresses are not yet setup");
stakingEnabled = _status;
}
function MIN_DIVIDENDS_DUR_TIME(uint256 _minDuration) public onlyCreator {
MIN_DIVIDENDS_DUR = _minDuration;
}
//======================================USER WRITE=========================================//
function StakeTokens(uint256 _tokens) external {
_stake(_tokens);
}
function UnstakeTokens(uint256 _tokens) external {
_unstake(_tokens);
}
//======================================USER READ=========================================//
function totalFrozen() public view returns (uint256) {
return info.totalFrozen;
}
function frozenOf(address _user) public view returns (uint256) {
return info.users[_user].frozen;
}
function dividendsOf(address _user) public view returns (uint256) {
if(info.users[_user].staketime < MIN_DIVIDENDS_DUR){
return 0;
}else{
return uint256(int256(info.scaledPayoutPerToken * info.users[_user].frozen) - info.users[_user].scaledPayout) / FLOAT_SCALAR;
}
}
function userData(address _user) public view
returns (uint256 totalTokensFrozen, uint256 userFrozen,
uint256 userDividends, uint256 userStaketime, int256 scaledPayout) {
return (totalFrozen(), frozenOf(_user), dividendsOf(_user), info.users[_user].staketime, info.users[_user].scaledPayout);
}
//======================================ACTION CALLS=========================================//
function _stake(uint256 _amount) internal {
require(stakingEnabled, "Staking not yet initialized");
require(IERC20(OracleIndexFunds).balanceOf(msg.sender) >= _amount, "Insufficient Oracle AFT token balance");
require(frozenOf(msg.sender) + _amount >= MINIMUM_STAKE, "Your amount is lower than the minimum amount allowed to stake");
require(IERC20(OracleIndexFunds).allowance(msg.sender, address(this)) >= _amount, "Not enough allowance given to contract yet to spend by user");
info.users[msg.sender].staketime = now;
info.totalFrozen += _amount;
info.users[msg.sender].frozen += _amount;
info.users[msg.sender].scaledPayout += int256(_amount * info.scaledPayoutPerToken);
IERC20(OracleIndexFunds).transferFrom(msg.sender, address(this), _amount);
emit StakeEvent(msg.sender, address(this), _amount);
}
function _unstake(uint256 _amount) internal {
require(frozenOf(msg.sender) >= _amount, "You currently do not have up to that amount staked");
info.totalFrozen -= _amount;
info.users[msg.sender].frozen -= _amount;
info.users[msg.sender].scaledPayout -= int256(_amount * info.scaledPayoutPerToken);
require(IERC20(OracleIndexFunds).transfer(msg.sender, _amount), "Transaction failed");
emit UnstakeEvent(address(this), msg.sender, _amount);
TakeDividends();
}
function TakeDividends() public returns (uint256) {
uint256 _dividends = dividendsOf(msg.sender);
require(_dividends >= 0, "you do not have any dividend yet");
info.users[msg.sender].scaledPayout += int256(_dividends * FLOAT_SCALAR);
require(IERC20(Axiatoken).transfer(msg.sender, _dividends), "Transaction Failed"); // Transfer dividends to msg.sender
emit RewardEvent(msg.sender, address(this), _dividends);
return _dividends;
}
function scaledToken(uint _amount) external onlyAxiaToken returns(bool){
info.scaledPayoutPerToken += _amount * FLOAT_SCALAR / info.totalFrozen;
infocheck = info.scaledPayoutPerToken;
return true;
}
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;
}
}
/**
*Submitted for verification at Etherscan.io on 2020-10-09
*/
/*
* @dev This is the Axia Protocol Staking pool 3 contract (SWAP Pool),
* a part of the protocol where stakers are rewarded in AXIA tokens
* when they make stakes of liquidity tokens from the oracle pool.
* stakers reward come from the daily emission from the total supply into circulation,
* this happens daily and upon the reach of a new epoch each made of 180 days,
* halvings are experienced on the emitting amount of tokens.
* on the 11th epoch all the tokens would have been completed emitted into circulation,
* from here on, the stakers will still be earning from daily emissions
* which would now be coming from the accumulated basis points over the epochs.
* stakers are not charged any fee for unstaking.
*/
pragma solidity 0.6.4;
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 {
/**
* @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 USP{
using SafeMath for uint256;
//======================================EVENTS=========================================//
event StakeEvent(address indexed staker, address indexed pool, uint amount);
event UnstakeEvent(address indexed unstaker, address indexed pool, uint amount);
event RewardEvent(address indexed staker, address indexed pool, uint amount);
event RewardStake(address indexed staker, address indexed pool, uint amount);
//======================================STAKING POOLS=========================================//
address public Axiatoken;
address public UniswapV2;
bool public stakingEnabled;
uint256 constant private FLOAT_SCALAR = 2**64;
uint256 public MINIMUM_STAKE = 1000000000000000000; // 1 minimum
uint256 public MIN_DIVIDENDS_DUR = 18 hours;
uint public infocheck;
struct User {
uint256 balance;
uint256 frozen;
int256 scaledPayout;
uint256 staketime;
}
struct Info {
uint256 totalSupply;
uint256 totalFrozen;
mapping(address => User) users;
uint256 scaledPayoutPerToken; //pool balance
address admin;
}
Info private info;
constructor() public {
info.admin = msg.sender;
stakingEnabled = false;
}
//======================================ADMINSTRATION=========================================//
modifier onlyCreator() {
require(msg.sender == info.admin, "Ownable: caller is not the administrator");
_;
}
modifier onlyAxiaToken() {
require(msg.sender == Axiatoken, "Authorization: only token contract can call");
_;
}
function tokenconfigs(address _axiatoken, address _univ2) public onlyCreator returns (bool success) {
require(_axiatoken != _univ2, "Insertion of same address is not supported");
require(_axiatoken != address(0) && _univ2 != address(0), "Insertion of address(0) is not supported");
Axiatoken = _axiatoken;
UniswapV2 = _univ2;
return true;
}
function _minStakeAmount(uint256 _number) onlyCreator public {
MINIMUM_STAKE = _number*1000000000000000000;
}
function stakingStatus(bool _status) public onlyCreator {
require(Axiatoken != address(0) && UniswapV2 != address(0), "Pool addresses are not yet setup");
stakingEnabled = _status;
}
function MIN_DIVIDENDS_DUR_TIME(uint256 _minDuration) public onlyCreator {
MIN_DIVIDENDS_DUR = _minDuration;
}
//======================================USER WRITE=========================================//
function StakeAxiaTokens(uint256 _tokens) external {
_stake(_tokens);
}
function UnstakeAxiaTokens(uint256 _tokens) external {
_unstake(_tokens);
}
//======================================USER READ=========================================//
function totalFrozen() public view returns (uint256) {
return info.totalFrozen;
}
function frozenOf(address _user) public view returns (uint256) {
return info.users[_user].frozen;
}
function dividendsOf(address _user) public view returns (uint256) {
if(info.users[_user].staketime < MIN_DIVIDENDS_DUR){
return 0;
}else{
return uint256(int256(info.scaledPayoutPerToken * info.users[_user].frozen) - info.users[_user].scaledPayout) / FLOAT_SCALAR;
}
}
function userData(address _user) public view
returns (uint256 totalTokensFrozen, uint256 userFrozen,
uint256 userDividends, uint256 userStaketime, int256 scaledPayout) {
return (totalFrozen(), frozenOf(_user), dividendsOf(_user), info.users[_user].staketime, info.users[_user].scaledPayout);
}
//======================================ACTION CALLS=========================================//
function _stake(uint256 _amount) internal {
require(stakingEnabled, "Staking not yet initialized");
require(IERC20(UniswapV2).balanceOf(msg.sender) >= _amount, "Insufficient SWAP AFT balance");
require(frozenOf(msg.sender) + _amount >= MINIMUM_STAKE, "Your amount is lower than the minimum amount allowed to stake");
require(IERC20(UniswapV2).allowance(msg.sender, address(this)) >= _amount, "Not enough allowance given to contract yet to spend by user");
info.users[msg.sender].staketime = now;
info.totalFrozen += _amount;
info.users[msg.sender].frozen += _amount;
info.users[msg.sender].scaledPayout += int256(_amount * info.scaledPayoutPerToken);
IERC20(UniswapV2).transferFrom(msg.sender, address(this), _amount); // Transfer liquidity tokens from the sender to this contract
emit StakeEvent(msg.sender, address(this), _amount);
}
function _unstake(uint256 _amount) internal {
require(frozenOf(msg.sender) >= _amount, "You currently do not have up to that amount staked");
info.totalFrozen -= _amount;
info.users[msg.sender].frozen -= _amount;
info.users[msg.sender].scaledPayout -= int256(_amount * info.scaledPayoutPerToken);
require(IERC20(UniswapV2).transfer(msg.sender, _amount), "Transaction failed");
emit UnstakeEvent(address(this), msg.sender, _amount);
TakeDividends();
}
function TakeDividends() public returns (uint256) {
uint256 _dividends = dividendsOf(msg.sender);
require(_dividends >= 0, "you do not have any dividend yet");
info.users[msg.sender].scaledPayout += int256(_dividends * FLOAT_SCALAR);
require(IERC20(Axiatoken).transfer(msg.sender, _dividends), "Transaction Failed"); // Transfer dividends to msg.sender
emit RewardEvent(msg.sender, address(this), _dividends);
return _dividends;
}
function scaledToken(uint _amount) external onlyAxiaToken returns(bool){
info.scaledPayoutPerToken += _amount * FLOAT_SCALAR / info.totalFrozen;
infocheck = info.scaledPayoutPerToken;
return true;
}
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;
}
}
Function Graph
Inheritence Chart
Functions Overview
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] SafeMath
- [Int] add
- [Int] sub
- [Int] sub
- [Int] mul
- [Int] div
- [Int] div
- [Int] mod
- [Int] mod
+ SWAPCONTRACT
- [Pub] #
- [Pub] tokenConfig #
- modifiers: onlyCreator
- [Pub] swapStatus #
- modifiers: onlyCreator
- [Ext] swap #
- [Ext] swapAll #
- [Pub] GetLeftOverV1 #
- modifiers: onlyCreator
- [Pub] GetLeftOverV2 #
- modifiers: onlyCreator
pragma solidity 0.6.4;
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 {
/**
* @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 SWAPCONTRACT{
using SafeMath for uint256;
address public V1;
address public V2;
bool swapEnabled;
address administrator;
constructor() public {
administrator = msg.sender;
swapEnabled = false;
}
//======================================ADMINSTRATION=========================================//
modifier onlyCreator() {
require(msg.sender == administrator, "Ownable: caller is not the administrator");
_;
}
function tokenConfig(address _v1Address, address _v2Address) public onlyCreator returns(bool){
require(_v1Address != address(0) && _v2Address != address(0), "Invalid address has been set");
V1 = _v1Address;
V2 = _v2Address;
return true;
}
function swapStatus(bool _status) public onlyCreator returns(bool){
require(V1 != address(0) && V2 != address(0), "V1 and V2 addresses are not set up yet");
swapEnabled = _status;
}
function swap(uint256 _amount) external returns(bool){
require(swapEnabled, "Swap not yet initialized");
require(_amount > 0, "Invalid amount to swap");
require(IERC20(V1).balanceOf(msg.sender) >= _amount, "You cannot swap more than what you hold");
require(IERC20(V2).balanceOf(address(this)) >= _amount, "Insufficient amount of tokens to be swapped for");
require(IERC20(V1).allowance(msg.sender, address(this)) >= _amount, "Insufficient allowance given to contract");
require(IERC20(V1).transferFrom(msg.sender, address(this), _amount), "Transaction failed on root");
require(IERC20(V2).transfer(msg.sender, _amount), "Transaction failed from base");
return true;
}
function swapAll() external returns(bool){
require(swapEnabled, "Swap not yet initialized");
uint v1userbalance = IERC20(V1).balanceOf(msg.sender);
uint v2contractbalance = IERC20(V2).balanceOf(address(this));
require(v1userbalance > 0, "You cannot swap on zero balance");
require(v2contractbalance >= v1userbalance, "Insufficient amount of tokens to be swapped for");
require(IERC20(V1).allowance(msg.sender, address(this)) >= v1userbalance, "Insufficient allowance given to contract");
require(IERC20(V1).transferFrom(msg.sender, address(this), v1userbalance), "Transaction failed on root");
require(IERC20(V2).transfer(msg.sender, v1userbalance), "Transaction failed from base");
return true;
}
function GetLeftOverV1() public onlyCreator returns(bool){
require(administrator != address(0));
require(administrator != address(this));
require(V1 != address(0) && V2 != address(0), "V1 address not set up yet");
uint bal = IERC20(V1).balanceOf(address(this));
require(IERC20(V1).transfer(administrator, bal), "Transaction failed");
}
function GetLeftOverV2() public onlyCreator returns(bool){
require(administrator != address(0));
require(administrator != address(this));
require(V1 != address(0) && V2 != address(0), "V1 address not set up yet");
uint bal = IERC20(V2).balanceOf(address(this));
require(IERC20(V2).transfer(administrator, bal), "Transaction failed");
}
}