编译器
0.6.12+commit.27d51765
文件 1 的 7:GmtSwap.sol
pragma solidity 0.6.12;
import "../libraries/math/SafeMath.sol";
import "../libraries/token/IERC20.sol";
import "../libraries/utils/ReentrancyGuard.sol";
import "../interfaces/IXVIX.sol";
import "../interfaces/IBurnVault.sol";
import "../interfaces/IGmtIou.sol";
contract GmtSwap is ReentrancyGuard {
using SafeMath for uint256;
uint256 constant PRECISION = 1000000;
bool public isInitialized;
bool public isSwapActive = true;
address public xvix;
address public uni;
address public xlge;
address public gmtIou;
address public weth;
address public dai;
address public wethDaiUni;
address public wethXvixUni;
address public allocator;
address public burnVault;
uint256 public gmtPrice;
uint256 public xlgePrice;
uint256 public minXvixPrice;
uint256 public unlockTime;
address public gov;
constructor() public {
gov = msg.sender;
}
modifier onlyGov() {
require(msg.sender == gov, "GmtSwap: forbidden");
_;
}
function initialize(
address[] memory _addresses,
uint256 _gmtPrice,
uint256 _xlgePrice,
uint256 _minXvixPrice,
uint256 _unlockTime
) public onlyGov {
require(!isInitialized, "GmtSwap: already initialized");
isInitialized = true;
xvix = _addresses[0];
uni = _addresses[1];
xlge = _addresses[2];
gmtIou = _addresses[3];
weth = _addresses[4];
dai = _addresses[5];
wethDaiUni = _addresses[6];
wethXvixUni = _addresses[7];
allocator = _addresses[8];
burnVault = _addresses[9];
gmtPrice = _gmtPrice;
xlgePrice = _xlgePrice;
minXvixPrice = _minXvixPrice;
unlockTime = _unlockTime;
}
function setGov(address _gov) public onlyGov {
gov = _gov;
}
function extendUnlockTime(uint256 _unlockTime) public onlyGov {
require(_unlockTime > unlockTime, "GmtSwap: invalid unlockTime");
unlockTime = _unlockTime;
}
function withdraw(address _token, uint256 _tokenAmount, address _receiver) public onlyGov {
require(block.timestamp > unlockTime, "GmtSwap: unlockTime not yet passed");
IERC20(_token).transfer(_receiver, _tokenAmount);
}
function swap(
address _token,
uint256 _tokenAmount,
uint256 _allocation,
uint8 _v,
bytes32 _r,
bytes32 _s
) public nonReentrant {
require(isSwapActive, "GmtSwap: swap is no longer active");
require(_tokenAmount > 0, "GmtSwap: invalid tokenAmount");
require(_allocation > 0, "GmtSwap: invalid gmtAllocation");
_verifyAllocation(msg.sender, _allocation, _v, _r, _s);
(uint256 transferAmount, uint256 mintAmount) = getSwapAmounts(
msg.sender, _token, _tokenAmount, _allocation);
require(transferAmount > 0, "GmtSwap: invalid transferAmount");
require(mintAmount > 0, "GmtSwap: invalid mintAmount");
IXVIX(xvix).rebase();
IERC20(_token).transferFrom(msg.sender, address(this), transferAmount);
if (_token == xvix) {
IERC20(_token).approve(burnVault, transferAmount);
IBurnVault(burnVault).deposit(transferAmount);
}
IGmtIou(gmtIou).mint(msg.sender, mintAmount);
}
function endSwap() public onlyGov {
isSwapActive = false;
}
function getSwapAmounts(
address _account,
address _token,
uint256 _tokenAmount,
uint256 _allocation
) public view returns (uint256, uint256) {
require(_token == xvix || _token == uni || _token == xlge, "GmtSwap: unsupported token");
uint256 tokenPrice = getTokenPrice(_token);
uint256 transferAmount = _tokenAmount;
uint256 mintAmount = _tokenAmount.mul(tokenPrice).div(gmtPrice);
uint256 gmtIouBalance = IERC20(gmtIou).balanceOf(_account);
uint256 maxMintAmount = _allocation.sub(gmtIouBalance);
if (mintAmount > maxMintAmount) {
mintAmount = maxMintAmount;
transferAmount = mintAmount.mul(gmtPrice).mul(10).div(tokenPrice).add(9).div(10);
}
return (transferAmount, mintAmount);
}
function getTokenPrice(address _token) public view returns (uint256) {
if (_token == xlge) {
return xlgePrice;
}
if (_token == xvix) {
return getXvixPrice();
}
if (_token == uni) {
return getUniPrice();
}
revert("GmtSwap: unsupported token");
}
function getEthPrice() public view returns (uint256) {
uint256 wethBalance = IERC20(weth).balanceOf(wethDaiUni);
uint256 daiBalance = IERC20(dai).balanceOf(wethDaiUni);
return daiBalance.mul(PRECISION).div(wethBalance);
}
function getXvixPrice() public view returns (uint256) {
uint256 ethPrice = getEthPrice();
uint256 wethBalance = IERC20(weth).balanceOf(wethXvixUni);
uint256 xvixBalance = IERC20(xvix).balanceOf(wethXvixUni);
uint256 price = wethBalance.mul(ethPrice).div(xvixBalance);
if (price < minXvixPrice) {
return minXvixPrice;
}
return price;
}
function getUniPrice() public view returns (uint256) {
uint256 ethPrice = getEthPrice();
uint256 wethBalance = IERC20(weth).balanceOf(wethXvixUni);
uint256 supply = IERC20(wethXvixUni).totalSupply();
return wethBalance.mul(ethPrice).mul(2).div(supply);
}
function _verifyAllocation(
address _account,
uint256 _allocation,
uint8 _v,
bytes32 _r,
bytes32 _s
) private view {
bytes32 message = keccak256(abi.encodePacked(
"GmtSwap:GmtAllocation",
_account,
_allocation
));
bytes32 messageHash = keccak256(abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
message
));
require(
allocator == ecrecover(messageHash, _v, _r, _s),
"GmtSwap: invalid signature"
);
}
}
文件 2 的 7:IBurnVault.sol
pragma solidity 0.6.12;
interface IBurnVault {
function deposit(uint256 amount) external;
}
文件 3 的 7:IERC20.sol
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);
}
文件 4 的 7:IGmtIou.sol
pragma solidity 0.6.12;
interface IGmtIou {
function mint(address account, uint256 amount) external returns (bool);
}
文件 5 的 7:IXVIX.sol
pragma solidity 0.6.12;
interface IXVIX {
function setGov(address gov) external;
function normalDivisor() external view returns (uint256);
function maxSupply() external view returns (uint256);
function mint(address account, uint256 amount) external returns (bool);
function burn(address account, uint256 amount) external returns (bool);
function toast(uint256 amount) external returns (bool);
function rebase() external returns (bool);
}
文件 6 的 7:ReentrancyGuard.sol
pragma solidity 0.6.12;
contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 7 的 7:SafeMath.sol
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;
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;
}
}
{
"compilationTarget": {
"contracts/gmt/GmtSwap.sol": "GmtSwap"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"allocator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dai","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_unlockTime","type":"uint256"}],"name":"extendUnlockTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getEthPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"},{"internalType":"uint256","name":"_allocation","type":"uint256"}],"name":"getSwapAmounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getTokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUniPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getXvixPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gmtIou","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gmtPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gov","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"},{"internalType":"uint256","name":"_gmtPrice","type":"uint256"},{"internalType":"uint256","name":"_xlgePrice","type":"uint256"},{"internalType":"uint256","name":"_minXvixPrice","type":"uint256"},{"internalType":"uint256","name":"_unlockTime","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSwapActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minXvixPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_gov","type":"address"}],"name":"setGov","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"},{"internalType":"uint256","name":"_allocation","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uni","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlockTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wethDaiUni","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wethXvixUni","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"xlge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xlgePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xvix","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]