pragma solidity =0.6.6;
/**
* Math operations with safety checks
*/
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;
}
}
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
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) public onlyOwner {
require(newOwner != address(0));
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
interface UpgradedPriceAble {
function getAmountsOutToken(uint value, uint8 rate) external view returns (uint balance);
function getAmountsOutEth(uint value, uint8 rate) external view returns (uint balance);
}
interface ERC20 {
function allowance(address owner, address spender) external view returns (uint256);
function transferFrom(address from, address to, uint256 value) external;
// function approve(address spender, uint256 value) public;
// function totalSupply() public view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function transfer(address to, uint256 value) external;
// event Transfer(address indexed from, address indexed to, uint256 value);
// event Approval(address indexed owner, address indexed spender, uint256 value);
}
contract UsdgMarket is Ownable{
using SafeMath for uint;
uint oneEth = 1000000000000000000;
uint8 public buyTokenRate = 100;
uint8 public saleTokenRate = 100;
IUniswapV2Router01 public uniswapRouter;
ERC20 public usdg;
address[] pathEth2Usdg;
address public upgradedAddress;
bool public upgraded = false;
event BuyToken(address indexed from,uint inValue, uint outValue);
event SaleToken(address indexed from,uint inValue, uint outValue);
event GovWithdrawEth(address indexed to, uint256 value);
event GovWithdrawToken(address indexed to, uint256 value);
modifier ensure(uint deadline) {
require(deadline >= block.timestamp, 'Market: EXPIRED');
_;
}
constructor(address _usdg, address _usdt, address _uniswap)public {
_setPath(_usdg,_usdt,_uniswap);
}
function _setPath(address _usdg, address _usdt,address _uniswap)private {
uniswapRouter = IUniswapV2Router01(_uniswap);
address _weth = uniswapRouter.WETH();
usdg = ERC20(_usdg);
pathEth2Usdg.push(_weth);
pathEth2Usdg.push(_usdt);
}
function getEthPrice()public view returns (uint balance) {
uint[] memory amounts = uniswapRouter.getAmountsOut( oneEth, pathEth2Usdg);
return amounts[1];
}
function _getAmountsOutToken(uint value, uint8 rate) private view returns (uint balance) {
uint rs = getEthPrice();
rs = rs.mul(value).div(oneEth);
if(rate > 0){
rs = rs.mul(rate).div(100);
}
rs = rs.mul(1000);
return rs;
}
function _getAmountsOutEth(uint value, uint8 rate) private view returns (uint balance) {
uint ePrice = getEthPrice();
uint uPrice = oneEth.div(ePrice);
uint rs = uPrice.mul(value);
if(rate > 0){
rs = rs.mul(rate).div(100);
}
rs = rs.div(1000);
return rs;
}
function getAmountsOutToken(uint _value) public view returns (uint balance) {
uint amount;
if (upgraded) {
amount = UpgradedPriceAble(upgradedAddress).getAmountsOutToken(_value,buyTokenRate);
} else {
amount = _getAmountsOutToken(_value,buyTokenRate);
}
return amount;
}
function getAmountsOutEth(uint _value) public view returns (uint balance) {
uint amount;
if (upgraded) {
amount = UpgradedPriceAble(upgradedAddress).getAmountsOutToken(_value,saleTokenRate);
} else {
amount = _getAmountsOutEth(_value,saleTokenRate);
}
return amount;
}
function buyTokenSafe(uint amountOutMin, uint deadline)payable ensure(deadline) public {
require(msg.value > 0, "!value");
uint amount = getAmountsOutToken(msg.value);
require(amount >= amountOutMin, 'INSUFFICIENT_OUTPUT_AMOUNT');
uint balanced = usdg.balanceOf(address(this));
require(balanced >= amount, "!contract balanced");
usdg.transfer(msg.sender, amount);
BuyToken(msg.sender,msg.value, amount);
}
function saleTokenSafe(uint256 _value,uint amountOutMin, uint deadline) ensure(deadline) public {
require(_value > 0, "!value");
uint amount = getAmountsOutEth(_value);
require(amount >= amountOutMin, 'INSUFFICIENT_OUTPUT_AMOUNT');
msg.sender.transfer(amount);
uint allowed = usdg.allowance(msg.sender,address(this));
uint balanced = usdg.balanceOf(msg.sender);
require(allowed >= _value, "!allowed");
require(balanced >= _value, "!balanced");
usdg.transferFrom( msg.sender,address(this), _value);
SaleToken(msg.sender,_value, amount);
}
function buyToken()payable public {
require(msg.value > 0, "!value");
uint amount = getAmountsOutToken(msg.value);
uint balanced = usdg.balanceOf(address(this));
require(balanced >= amount, "!contract balanced");
usdg.transfer(msg.sender, amount);
BuyToken(msg.sender,msg.value, amount);
}
function saleToken(uint256 _value) public {
require(_value > 0, "!value");
uint amount = getAmountsOutEth(_value);
msg.sender.transfer(amount);
uint allowed = usdg.allowance(msg.sender,address(this));
uint balanced = usdg.balanceOf(msg.sender);
require(allowed >= _value, "!allowed");
require(balanced >= _value, "!balanced");
usdg.transferFrom( msg.sender,address(this), _value);
SaleToken(msg.sender,_value, amount);
}
function govWithdrawToken(uint256 _amount)onlyOwner public {
require(_amount > 0, "!zero input");
usdg.transfer( msg.sender, _amount);
emit GovWithdrawToken(msg.sender, _amount);
}
function govWithdrawEth(uint256 _amount)onlyOwner public {
require(_amount > 0, "!zero input");
msg.sender.transfer(_amount);
emit GovWithdrawEth(msg.sender, _amount);
}
function changeRates(uint8 _buyTokenRate, uint8 _saleTokenRate)onlyOwner public {
require(201 > buyTokenRate, "_buyTokenRate big than 200");
require(201 > _saleTokenRate, "_saleTokenRate big than 200");
buyTokenRate = _buyTokenRate;
saleTokenRate = _saleTokenRate;
}
fallback() external payable {}
}
{
"compilationTarget": {
"UsdgMarket.sol": "UsdgMarket"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_usdg","type":"address"},{"internalType":"address","name":"_usdt","type":"address"},{"internalType":"address","name":"_uniswap","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"inValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"outValue","type":"uint256"}],"name":"BuyToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"GovWithdrawEth","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"GovWithdrawToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"inValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"outValue","type":"uint256"}],"name":"SaleToken","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"buyToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"buyTokenRate","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"buyTokenSafe","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_buyTokenRate","type":"uint8"},{"internalType":"uint8","name":"_saleTokenRate","type":"uint8"}],"name":"changeRates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"getAmountsOutEth","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"getAmountsOutToken","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEthPrice","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"govWithdrawEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"govWithdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"saleToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"saleTokenRate","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"saleTokenSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapRouter","outputs":[{"internalType":"contract IUniswapV2Router01","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"upgraded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"upgradedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdg","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"}]