编译器
0.8.13+commit.abaa5c0e
文件 1 的 22:CollectibleFees.sol
pragma solidity ^0.8.0;
import "IERC20.sol";
import "Ownable.sol";
import "Geminon.sol";
contract CollectibleFees is Ownable, Geminon {
address private _feesCollector;
uint256 internal _balanceFees;
function setCollector(address feesCollector) external onlyOwner {
_feesCollector = feesCollector;
}
function collectFees() external returns(uint256) {
require(_feesCollector != address(0));
require(msg.sender == _feesCollector);
require(_balanceFees > 0);
uint256 feesCollected = _balanceFees;
_balanceFees = 0;
require(IERC20(GEX).transfer(_feesCollector, feesCollected));
return feesCollected;
}
}
文件 2 的 22:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 22:Geminon.sol
pragma solidity ^0.8.0;
contract Geminon {
address public GEX;
address public oracleGeminon;
uint256 internal _balanceGEX;
}
文件 4 的 22:GeminonInfrastructure.sol
pragma solidity ^0.8.0;
import "Ownable.sol";
import "SCMinterMigration.sol";
import "IGeminonOracle.sol";
import "TimeLocks.sol";
contract GeminonInfrastructure is Ownable, TimeLocks, SCMinterMigration {
address public arbitrageur;
function setArbitrageur(address arbitrageur_) external onlyOwner {
arbitrageur = arbitrageur_;
}
function applyOracleChange() external onlyOwner {
require(!isMigrationRequested);
require(changeRequests[oracleGeminon].changeRequested);
require(block.timestamp - changeRequests[oracleGeminon].timestampRequest > 30 days);
require(changeRequests[oracleGeminon].newAddressRequested != address(0));
changeRequests[oracleGeminon].changeRequested = false;
oracleGeminon = changeRequests[oracleGeminon].newAddressRequested;
oracleAge = uint64(block.timestamp);
}
function cancelChangeRequests() external onlyOwner {
if (changeRequests[address(0)].changeRequested)
changeRequests[address(0)].changeRequested = false;
if (changeRequests[oracleGeminon].changeRequested)
changeRequests[oracleGeminon].changeRequested = false;
if (isMigrationRequested) {
isMigrationRequested = false;
IGeminonOracle(oracleGeminon).cancelMigration();
}
}
}
文件 5 的 22:ICollectible.sol
pragma solidity ^0.8.0;
interface ICollectible {
function collectFees() external returns(uint256);
}
文件 6 的 22:ICollectibleFees.sol
pragma solidity ^0.8.0;
interface ICollectibleFees {
function setCollector(address feesCollector) external;
function collectFees() external returns(uint256);
}
文件 7 的 22:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, 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 from,
address to,
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);
}
文件 8 的 22:IERC20ElasticSupply.sol
pragma solidity ^0.8.0;
import "IERC20.sol";
interface IERC20ElasticSupply is IERC20 {
function addMinter(address newMinter) external;
function removeMinter(address minter) external;
function mint(address to, uint256 amount) external;
function burn(address from, uint256 amount) external;
function maxAmountMintable() external view returns(uint256);
}
文件 9 的 22:IERC20Indexed.sol
pragma solidity ^0.8.0;
import "IERC20ElasticSupply.sol";
interface IERC20Indexed is IERC20ElasticSupply {
function setIndexBeacon(address beacon) external;
function requestMaxVariationChange(uint16 newValue) external;
function applyMaxVariationChange() external;
function updateTarget() external;
function getOrUpdatePegValue() external returns(uint256);
function getPegValue() external view returns(uint256);
}
文件 10 的 22:IGeminon.sol
pragma solidity ^0.8.0;
interface IGeminon {
function GEX() external view returns(address);
function oracleGeminon() external view returns(address);
}
文件 11 的 22:IGeminonInfrastructure.sol
pragma solidity ^0.8.0;
interface IGeminonInfrastructure {
function arbitrageur() external view returns(address);
function setArbitrageur(address arbitrageur_) external;
function applyOracleChange() external;
function cancelChangeRequests() external;
}
文件 12 的 22:IGeminonOracle.sol
pragma solidity ^0.8.0;
interface IGeminonOracle {
function isAnyPoolMigrating() external view returns(bool);
function isAnyPoolRemoving() external view returns(bool);
function scMinter() external view returns(address);
function bridge() external view returns(address);
function treasuryLender() external view returns(address);
function feesCollector() external view returns(address);
function pools(uint) external view returns(address);
function ageSCMinter() external view returns(uint64);
function ageBridge() external view returns(uint64);
function ageTreasuryLender() external view returns(uint64);
function ageFeesCollector() external view returns(uint64);
function isMigratingMinter() external view returns(bool);
function newMinter() external view returns(address);
function isPool(address) external view returns(bool);
function isMigratingPool(address) external view returns(bool);
function isRemovingPool(address) external view returns(bool);
function poolAge(address) external view returns(uint64);
function setSCMinter(address scMinter_) external;
function setBridge(address bridge_) external;
function setTreasuryLender(address lender) external;
function setCollector(address feesCollector_) external;
function addPool(address newPool) external;
function removePool(address pool) external;
function requestMigratePool(address newPool) external;
function setMigrationDone() external;
function cancelMigration() external;
function requestRemovePool() external;
function setRemoveDone() external;
function cancelRemove() external;
function requestMigrateMinter(address newMinter) external;
function setMinterMigrationDone() external;
function cancelMinterMigration() external;
function getTotalCollatValue() external view returns(uint256);
function getPoolCollatWeight(address pool) external view returns(uint256);
function getSafePrice() external view returns(uint256);
function getLastPrice() external view returns(uint256);
function getMeanVolume() external view returns(uint256);
function getLastVolume() external view returns(uint256);
function getTotalMintedGEX() external view returns(uint256);
function getExternalMintedGEX() external view returns(uint256);
function getLockedAmountGEX() external view returns(uint256);
function getHighestGEXPool() external view returns(address);
}
文件 13 的 22:IGenesisLiquidityPool.sol
pragma solidity ^0.8.0;
import "ICollectible.sol";
interface IGenesisLiquidityPool is ICollectible {
function initMintedAmount() external view returns(uint256);
function poolWeight() external view returns(uint16);
function mintedGEX() external view returns(int256);
function balanceCollateral() external view returns(uint256);
function balanceGEX() external view returns(uint256);
function blockTimestampLast() external view returns(uint64);
function lastCollatPrice() external view returns(uint256);
function meanPrice() external view returns(uint256);
function lastPrice() external view returns(uint256);
function meanVolume() external view returns(uint256);
function lastVolume() external view returns(uint256);
function isMigrationRequested() external view returns(bool);
function isRemoveRequested() external view returns(bool);
function receiveMigration(uint256 amountGEX, uint256 amountCollateral, uint256 initMintedAmount) external;
function bailoutMinter() external returns(uint256);
function lendCollateral(uint256 amount) external returns(uint256);
function repayCollateral(uint256 amount) external returns(uint256);
function mintSwap(uint256 inCollatAmount, uint256 minOutGEXAmount) external;
function redeemSwap(uint256 inGEXAmount, uint256 minOutCollatAmount) external;
function collateralPrice() external view returns(uint256);
function collateralQuote() external view returns(uint256);
function getCollateralValue() external view returns(uint256);
function GEXPrice() external view returns(uint256);
function GEXQuote() external view returns(uint256);
function amountFeeMint(uint256 amountGEX) external view returns(uint256);
function amountFeeRedeem(uint256 amountGEX) external view returns(uint256);
function getMintInfo(uint256 inCollatAmount) external view returns(
uint256 collateralPriceUSD,
uint256 gexPriceUSD,
uint256 collatQuote,
uint256 gexQuote,
uint256 fee,
uint256 feeAmount,
uint256 outGEXAmount,
uint256 finalGEXPriceUSD,
uint256 priceImpact
);
function getRedeemInfo(uint256 inGEXAmount) external view returns(
uint256 collateralPriceUSD,
uint256 gexPriceUSD,
uint256 collatQuote,
uint256 gexQuote,
uint256 fee,
uint256 feeAmount,
uint256 outCollatAmount,
uint256 finalGEXPriceUSD,
uint256 priceImpact
);
function amountOutGEX(uint256 inCollatAmount) external view returns(uint256);
function amountOutCollateral(uint256 inGEXAmount) external view returns(uint256);
function amountMint(uint256 outGEXAmount) external view returns(uint256);
function amountBurn(uint256 inGEXAmount) external view returns(uint256);
function variableFee(uint256 amountGEX, uint256 baseFee) external view returns(uint256);
}
文件 14 的 22:ISCMinter.sol
pragma solidity ^0.8.0;
import "IGeminon.sol";
import "ICollectibleFees.sol";
import "IGeminonInfrastructure.sol";
import "ISCMinterMigration.sol";
interface ISCMinter is
IGeminon,
ICollectibleFees,
ISCMinterMigration,
IGeminonInfrastructure
{
function USDI() external view returns(address);
function baseMintFee() external view returns(uint32);
function baseRedeemFee() external view returns(uint32);
function stablecoins(uint) external view returns(address);
function validTokens(address) external view returns(bool);
function mintedTokens(address) external view returns(bool);
function baseSwapFees(address) external view returns(uint32);
function addStablecoin(address token, uint32 swapFee) external;
function removeStablecoin(address token) external;
function setMintFee(uint32 value) external;
function setRedeemFee(uint32 value) external;
function setSwapFee(address stable, uint32 value) external;
function mintStablecoin(address stablecoin, uint256 inAmountGEX) external returns(uint256);
function redeemStablecoin(address stablecoin, uint256 inAmountStablecoin) external returns(uint256);
function stableSwap(address stableIn, address stableOut, uint256 amountIn) external returns(uint256);
function pauseMint() external;
function unpauseMint() external;
function addReservesGEX(uint256 amount) external;
function addReserves(uint256 amount, address stablecoin) external;
function burnReserves(uint256 amount, address stablecoin) external;
function requestBailoutFromPool() external returns(uint256);
function getBalanceGEX() external view returns(uint256);
function getTVC() external view returns(uint256);
function amountFeeGEX(uint256 amountGEX, uint256 baseFee) external view returns(uint256 fee);
function amountFeeMint(address stable, uint256 amountStable, uint256 usdPrice) external view returns(uint256);
function amountFeeRedeem(address stable, uint256 amountStable, uint256 usdPrice) external view returns(uint256);
function amountFeeSwap(
address stableIn,
address stableOut,
uint256 usdPriceIn,
uint256 usdPriceOut,
uint256 amountOut
) external view returns(uint256);
function feeStablecoinMint(address stable, uint256 amountStable) external view returns(uint256);
function feeStablecoinRedeem(address stable, uint256 amountStable) external view returns(uint256);
function amountUSDI(address stablecoin, uint256 amount) external view returns(uint256);
function getMintInfo(uint256 inGEXAmount, address stablecoin) external view returns(
uint256 gexPriceUSD,
uint256 stablecoinPriceUSD,
uint256 fee,
uint256 feeAmount,
uint256 outStablecoinAmount
);
function getRedeemInfo(uint256 inStablecoinAmount, address stablecoin) external view returns(
uint256 stablecoinPriceUSD,
uint256 gexPriceUSD,
uint256 fee,
uint256 feeAmount,
uint256 outGEXAmount
);
function getStableSwapInfo(uint256 inAmount, address stableIn, address stableOut) external view returns(
uint256 inStablecoinPriceUSD,
uint256 outStablecoinPriceUSD,
uint256 quoteS2S1,
uint256 fee,
uint256 feeAmount,
uint256 outStablecoinAmount
);
function amountMint(address stablecoin, uint256 amountGEX) external view returns(uint256);
function amountRedeem(address stablecoin, uint256 amountStablecoin) external view returns(uint256);
function getSafeMintRatio(address stablecoin) external view returns(uint256);
function getSafeRedeemRatio(address stablecoin) external view returns(uint256);
function feeGEX(uint256 amountGEX, uint256 baseFee) external view returns(uint256 fee);
function feeSwap(
address stableIn,
address stableOut,
uint256 usdPriceIn,
uint256 usdPriceOut,
uint256 amountOut
) external view returns(uint256);
}
文件 15 的 22:ISCMinterMigration.sol
pragma solidity ^0.8.0;
interface ISCMinterMigration {
function oracleAge() external view returns(uint64);
function isMigrationRequested() external view returns(bool);
function timestampMigrationRequest() external view returns(uint64);
function migrationMinter() external view returns(address);
function requestMigration(address newMinter) external;
function migrateMinter() external;
function receiveMigration(uint256 amountGEX) external;
}
文件 16 的 22:Ownable.sol
pragma solidity ^0.8.0;
import "Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 17 的 22:SCMinter.sol
pragma solidity ^0.8.0;
import "Ownable.sol";
import "IERC20.sol";
import "StableSwapGuard.sol";
import "GeminonInfrastructure.sol";
import "VariableFees.sol";
import "IGeminonOracle.sol";
import "IGenesisLiquidityPool.sol";
import "IERC20Indexed.sol";
import "TradePausable.sol";
contract SCMinter is Ownable, TradePausable, GeminonInfrastructure, StableSwapGuard, VariableFees {
address public immutable USDI;
uint32 public baseMintFee;
uint32 public baseRedeemFee;
address[] public stablecoins;
mapping(address => bool) public validTokens;
mapping(address => bool) public mintedTokens;
mapping(address => uint32) public baseSwapFees;
modifier onlyValidTokens(address token) {
require(validTokens[token], 'Invalid token');
_;
}
modifier onlyMintedTokens(address token) {
require(mintedTokens[token], 'Token not minted');
_;
}
constructor(address gex, address usdi, address oracle) {
GEX = gex;
USDI = usdi;
oracleGeminon = oracle;
oracleAge = uint64(block.timestamp);
baseMintFee = 1000;
baseRedeemFee = 2000;
stablecoins.push(usdi);
validTokens[usdi] = true;
mintedTokens[usdi] = true;
baseSwapFees[usdi] = 3000;
}
function addStablecoin(address token, uint32 swapFee) external onlyOwner {
require(token != address(0));
stablecoins.push(token);
validTokens[token] = true;
mintedTokens[token] = true;
setSwapFee(token, swapFee);
}
function removeStablecoin(address token) external onlyOwner onlyValidTokens(token) {
require(token != USDI);
validTokens[token] = false;
}
function setMintFee(uint32 value) external onlyOwner {
require(value <= 5000);
baseMintFee = value;
}
function setRedeemFee(uint32 value) external onlyOwner {
require(value <= 6000);
baseRedeemFee = value;
}
function setSwapFee(address stable, uint32 value) public onlyOwner onlyValidTokens(stable) {
require(value <= 12000);
require(value >= baseMintFee + baseRedeemFee);
baseSwapFees[stable] = value;
}
function mintStablecoin(address stablecoin, uint256 amountInGEX)
external
whenMintNotPaused
onlyValidTokens(stablecoin)
returns(uint256)
{
uint256 amountOutStablecoin;
uint256 usdPrice = IERC20Indexed(stablecoin).getOrUpdatePegValue();
if (stablecoin == USDI || usdPrice == 1e18) {
uint256 amountFeeGEX_ = amountFeeGEX(amountInGEX, baseMintFee);
amountOutStablecoin = amountMint(stablecoin, amountInGEX - amountFeeGEX_);
} else {
amountOutStablecoin = amountMint(stablecoin, amountInGEX);
_updatePriceRecord(stablecoin, usdPrice, amountOutStablecoin, true);
amountOutStablecoin -= amountFeeMint(stablecoin, amountOutStablecoin, usdPrice);
}
if (amountOutStablecoin > IERC20Indexed(stablecoin).balanceOf(address(this)) / 10)
_addReserves(amountOutStablecoin, stablecoin);
_balanceFees += (amountInGEX * baseMintFee) / 1e6;
IERC20(GEX).transferFrom(msg.sender, address(this), amountInGEX);
IERC20(stablecoin).transfer(msg.sender, amountOutStablecoin);
return amountOutStablecoin;
}
function redeemStablecoin(address stablecoin, uint256 amountInStablecoin)
external
onlyMintedTokens(stablecoin)
returns(uint256)
{
uint256 amountFeeGEX_;
uint256 usdPrice = IERC20Indexed(stablecoin).getOrUpdatePegValue();
uint256 amountOutGEX = amountRedeem(stablecoin, amountInStablecoin);
if (stablecoin == USDI || usdPrice == 1e18) {
amountFeeGEX_ = amountFeeGEX(amountOutGEX, baseRedeemFee);
} else {
_updatePriceRecord(stablecoin, usdPrice, amountInStablecoin, false);
uint256 amountFeeStablecoin = amountFeeRedeem(stablecoin, amountInStablecoin, usdPrice);
amountFeeGEX_ = amountRedeem(stablecoin, amountFeeStablecoin);
}
uint256 balanceGEX = IERC20(GEX).balanceOf(address(this)) - _balanceFees;
if(amountOutGEX > balanceGEX)
_requestBailoutFromPool();
require(amountOutGEX <= balanceGEX, "Amount too high");
_balanceFees += (amountOutGEX * baseRedeemFee) / 1e6;
amountOutGEX -= amountFeeGEX_;
IERC20(stablecoin).transferFrom(msg.sender, address(this), amountInStablecoin);
IERC20(GEX).transfer(msg.sender, amountOutGEX);
return amountOutGEX;
}
function stableSwap(address stableIn, address stableOut, uint256 amountIn)
external
whenMintNotPaused
onlyMintedTokens(stableIn)
onlyValidTokens(stableOut)
returns(uint256)
{
uint256 usdPriceIn = IERC20Indexed(stableIn).getOrUpdatePegValue();
uint256 usdPriceOut = IERC20Indexed(stableOut).getOrUpdatePegValue();
uint256 amountOutStable = (amountIn * usdPriceIn) / usdPriceOut;
if (stableIn != USDI && usdPriceIn != 1e18)
_updatePriceRecord(stableIn, usdPriceIn, amountIn, false);
if (stableOut != USDI && usdPriceOut != 1e18)
_updatePriceRecord(stableOut, usdPriceOut, amountOutStable, true);
amountOutStable -= amountFeeSwap(
stableIn,
stableOut,
usdPriceIn,
usdPriceOut,
amountOutStable
);
if (amountOutStable > IERC20Indexed(stableOut).balanceOf(address(this)) / 10)
_addReserves(amountOutStable, stableOut);
IERC20(stableIn).transferFrom(msg.sender, address(this), amountIn);
IERC20(stableOut).transfer(msg.sender, amountOutStable);
return amountOutStable;
}
function pauseMint() external onlyOwner whenMintNotPaused {
_pauseMint();
}
function unpauseMint() external onlyOwner whenMintPaused {
require(!isMigrationRequested);
_unpauseMint();
}
function addReservesGEX(uint256 amount) external onlyOwner {
IERC20Indexed(GEX).mint(address(this), amount);
}
function addReserves(uint256 amount, address stablecoin) external onlyOwner onlyValidTokens(stablecoin) {
_addReserves(amount, stablecoin);
}
function burnReserves(uint256 amount, address stablecoin) external onlyOwner onlyMintedTokens(stablecoin) {
IERC20Indexed(stablecoin).burn(address(this), amount);
}
function requestBailoutFromPool() external onlyOwner returns(uint256) {
return _requestBailoutFromPool();
}
function getBalanceGEX() external view returns(uint256) {
return IERC20(GEX).balanceOf(address(this)) - _balanceFees;
}
function getTVC() external view returns(uint256) {
uint256 value = 0;
for (uint16 i=0; i<stablecoins.length; i++) {
address sc = stablecoins[i];
uint256 circulating = IERC20(sc).totalSupply() - IERC20(sc).balanceOf(address(this));
value += (circulating * IERC20Indexed(sc).getPegValue()) / 1e18;
}
return value;
}
function amountFeeGEX(uint256 amountGEX, uint256 baseFee) public view returns(uint256 fee) {
return (amountGEX * feeGEX(amountGEX, baseFee)) / 1e6;
}
function amountFeeMint(address stable, uint256 amountStable, uint256 usdPrice) public view returns(uint256) {
return (amountStable * _feeStablecoin(stable, amountStable, usdPrice, baseMintFee, true)) / 1e6;
}
function amountFeeRedeem(address stable, uint256 amountStable, uint256 usdPrice) public view returns(uint256) {
return (amountStable * _feeStablecoin(stable, amountStable, usdPrice, baseRedeemFee, false)) / 1e6;
}
function amountFeeSwap(
address stableIn,
address stableOut,
uint256 usdPriceIn,
uint256 usdPriceOut,
uint256 amountOut
) public view returns(uint256) {
return (amountOut * feeSwap(stableIn, stableOut, usdPriceIn, usdPriceOut, amountOut)) / 1e6;
}
function feeStablecoinMint(address stable, uint256 amountStable) public view returns(uint256) {
uint256 amountEqUSDI = amountUSDI(stable, amountStable);
uint256 usdPrice = IERC20Indexed(stable).getPegValue();
return _feeStablecoin(stable, amountEqUSDI, usdPrice, baseMintFee, true);
}
function feeStablecoinRedeem(address stable, uint256 amountStable) public view returns(uint256) {
uint256 amountEqUSDI = amountUSDI(stable, amountStable);
uint256 usdPrice = IERC20Indexed(stable).getPegValue();
return _feeStablecoin(stable, amountEqUSDI, usdPrice, baseRedeemFee, false);
}
function amountUSDI(address stablecoin, uint256 amount) public view returns(uint256) {
return (amount * IERC20Indexed(stablecoin).getPegValue()) / IERC20Indexed(USDI).getPegValue();
}
function getMintInfo(uint256 inGEXAmount, address stablecoin) public view returns(
uint256 gexPriceUSD,
uint256 stablecoinPriceUSD,
uint256 fee,
uint256 feeAmount,
uint256 outStablecoinAmount
) {
gexPriceUSD = IGeminonOracle(oracleGeminon).getSafePrice();
stablecoinPriceUSD = IERC20Indexed(stablecoin).getPegValue();
fee = feeGEX(inGEXAmount, baseMintFee);
feeAmount = (inGEXAmount * fee) / 1e6;
outStablecoinAmount = amountMint(stablecoin, inGEXAmount - feeAmount);
}
function getRedeemInfo(uint256 inStablecoinAmount, address stablecoin) public view returns(
uint256 stablecoinPriceUSD,
uint256 gexPriceUSD,
uint256 fee,
uint256 feeAmount,
uint256 outGEXAmount
) {
stablecoinPriceUSD = IERC20Indexed(stablecoin).getPegValue();
gexPriceUSD = IGeminonOracle(oracleGeminon).getSafePrice();
fee = feeStablecoinRedeem(stablecoin, inStablecoinAmount);
feeAmount = (inStablecoinAmount * fee) / 1e6;
outGEXAmount = amountRedeem(stablecoin, inStablecoinAmount - feeAmount);
}
function getStableSwapInfo(uint256 inAmount, address stableIn, address stableOut) public view returns(
uint256 inStablecoinPriceUSD,
uint256 outStablecoinPriceUSD,
uint256 quoteS2S1,
uint256 fee,
uint256 feeAmount,
uint256 outStablecoinAmount
) {
inStablecoinPriceUSD = IERC20Indexed(stableIn).getPegValue();
outStablecoinPriceUSD = IERC20Indexed(stableOut).getPegValue();
quoteS2S1 = (outStablecoinPriceUSD * 1e18) / inStablecoinPriceUSD;
outStablecoinAmount = (inAmount * inStablecoinPriceUSD) / outStablecoinPriceUSD;
fee = feeSwap(stableIn, stableOut, inStablecoinPriceUSD, outStablecoinPriceUSD, outStablecoinAmount);
feeAmount = (outStablecoinAmount * fee) / 1e6;
outStablecoinAmount -= feeAmount;
}
function amountMint(address stablecoin, uint256 amountGEX) public view returns(uint256) {
return (amountGEX * getSafeMintRatio(stablecoin)) / 1e18;
}
function amountRedeem(address stablecoin, uint256 amountStablecoin) public view returns(uint256) {
return (amountStablecoin * getSafeRedeemRatio(stablecoin)) / 1e18;
}
function getSafeMintRatio(address stablecoin) public view returns(uint256) {
uint256 priceGEX = IGeminonOracle(oracleGeminon).getSafePrice();
uint256 priceIndex = IERC20Indexed(stablecoin).getPegValue();
return (priceGEX * 1e18) / priceIndex;
}
function getSafeRedeemRatio(address stablecoin) public view returns(uint256) {
uint256 priceGEX = IGeminonOracle(oracleGeminon).getSafePrice();
uint256 priceIndex = IERC20Indexed(stablecoin).getPegValue();
return (priceIndex * 1e18) / priceGEX;
}
function feeGEX(uint256 amountGEX, uint256 baseFee) public view returns(uint256 fee) {
if (msg.sender == arbitrageur && arbitrageur != address(0)) return 0;
uint256 usdiAmount = (amountGEX * getSafeMintRatio(USDI)) / 1e18;
return _variableFee(usdiAmount, baseFee);
}
function feeSwap(
address stableIn,
address stableOut,
uint256 usdPriceIn,
uint256 usdPriceOut,
uint256 amountOut
) public view returns(uint256) {
uint256 amountEqUSDI = amountUSDI(stableOut, amountOut);
uint256 feeStableIn = _feeStablecoin(stableIn, amountEqUSDI, usdPriceIn, baseSwapFees[stableIn], false);
uint256 feeStableOut = _feeStablecoin(stableOut, amountEqUSDI, usdPriceOut, baseSwapFees[stableOut], true);
return feeStableIn > feeStableOut ? feeStableIn : feeStableOut;
}
function _addReserves(uint256 amount, address stablecoin) private {
IERC20Indexed(stablecoin).mint(address(this), amount);
}
function _requestBailoutFromPool() private returns(uint256) {
address pool = _biggestPool();
uint256 bailoutAmount = IGenesisLiquidityPool(pool).bailoutMinter();
IERC20(GEX).transferFrom(pool, address(this), bailoutAmount);
return bailoutAmount;
}
function _feeStablecoin(
address stable,
uint256 amountEqUSDI,
uint256 usdPrice,
uint256 baseFee,
bool isOpLong
) private view returns(uint256) {
if (msg.sender == arbitrageur && arbitrageur != address(0)) return 0;
if (stable != USDI && usdPrice != 1e18) {
uint256 safetyFee = _safetyFeeStablecoin(stable, usdPrice, isOpLong);
baseFee = safetyFee > baseFee ? safetyFee : baseFee;
}
return _variableFee(amountEqUSDI, baseFee);
}
function _biggestPool() private view returns(address) {
return IGeminonOracle(oracleGeminon).getHighestGEXPool();
}
}
文件 18 的 22:SCMinterMigration.sol
pragma solidity ^0.8.0;
import "Ownable.sol";
import "IERC20.sol";
import "CollectibleFees.sol";
import "ISCMinter.sol";
import "IGeminonOracle.sol";
import "TimeLocks.sol";
import "TradePausable.sol";
contract SCMinterMigration is Ownable, TradePausable, TimeLocks, CollectibleFees {
uint64 public oracleAge;
bool public isMigrationRequested;
uint64 public timestampMigrationRequest;
address public migrationMinter;
function requestMigration(address newMinter) external onlyOwner {
require(changeRequests[address(this)].changeRequested);
require(block.timestamp - changeRequests[address(this)].timestampRequest > 7 days);
require(changeRequests[address(this)].newAddressRequested == newMinter);
require(oracleGeminon != address(0));
changeRequests[address(this)].changeRequested = false;
changeRequests[address(this)].newAddressRequested = address(this);
changeRequests[address(this)].timestampRequest = type(uint64).max;
isMigrationRequested = true;
migrationMinter = newMinter;
timestampMigrationRequest = uint64(block.timestamp);
IGeminonOracle(oracleGeminon).requestMigrateMinter(newMinter);
_pauseMint();
}
function migrateMinter() external onlyOwner whenMintPaused {
require(isMigrationRequested);
require(oracleGeminon != address(0));
require(IGeminonOracle(oracleGeminon).isMigratingMinter());
require(block.timestamp - timestampMigrationRequest > 15 days);
uint256 amountGEX = IERC20(GEX).balanceOf(address(this)) - _balanceFees;
isMigrationRequested = false;
IERC20(GEX).approve(migrationMinter, amountGEX);
ISCMinter(migrationMinter).receiveMigration(amountGEX);
IGeminonOracle(oracleGeminon).setMinterMigrationDone();
}
function receiveMigration(uint256 amountGEX) external {
require(oracleGeminon != address(0));
require(IGeminonOracle(oracleGeminon).scMinter() == msg.sender);
require(IGeminonOracle(oracleGeminon).isMigratingMinter());
require(IERC20(GEX).transferFrom(msg.sender, address(this), amountGEX));
}
}
文件 19 的 22:StableSwapGuard.sol
pragma solidity ^0.8.0;
contract StableSwapGuard {
struct priceRecord {
uint64 lastTimestamp;
uint32 weightedPrice;
uint256 volume;
}
mapping(address => priceRecord) public priceRecordsLongs;
mapping(address => priceRecord) public priceRecordsShorts;
function _updatePriceRecord(address stable, uint256 usdPrice, uint256 amount, bool isOpLong) internal {
if (isOpLong) {
priceRecord memory record = priceRecordsLongs[stable];
priceRecordsLongs[stable] = _modifyRecord(record, usdPrice, amount);
} else {
priceRecord memory record = priceRecordsShorts[stable];
priceRecordsShorts[stable] = _modifyRecord(record, usdPrice, amount);
}
}
function _safetyFeeStablecoins(
address stableIn,
address stableOut,
uint256 usdPriceIn,
uint256 usdPriceOut
) internal view returns(uint256) {
uint256 fee1 = _safetyFeeStablecoin(stableIn, usdPriceIn, false);
uint256 fee2 = _safetyFeeStablecoin(stableOut, usdPriceOut, true);
return fee1 > fee2 ? fee1 : fee2;
}
function _safetyFeeStablecoin(address stable, uint256 usdPrice, bool isOpLong) internal view returns(uint256) {
return _volatility(stable, usdPrice, isOpLong) / 1e12;
}
function _modifyRecord(
priceRecord memory record,
uint256 usdPrice,
uint256 amount
) private view returns(priceRecord memory) {
uint64 timestamp;
uint32 weightedPrice;
uint256 volume;
if (block.timestamp - record.lastTimestamp > 300) {
weightedPrice = uint32(usdPrice/1e12);
volume = amount;
} else {
uint256 w = (amount * 1e6) / (amount + record.volume);
weightedPrice = uint32((w*usdPrice/1e12 + (1e6-w)*record.weightedPrice) / 1e6);
volume = record.volume + amount;
}
timestamp = uint64(block.timestamp);
return priceRecord(timestamp, weightedPrice, volume);
}
function _volatility(address stable, uint256 usdPrice, bool isOpLong) private view returns(uint256) {
uint32 weightedPrice;
if (isOpLong)
weightedPrice = priceRecordsLongs[stable].weightedPrice;
else
weightedPrice = priceRecordsShorts[stable].weightedPrice;
return _absRet(usdPrice, uint256(weightedPrice)*1e12);
}
function _absRet(uint256 price, uint256 basePrice) private pure returns(uint256) {
if (basePrice == 0)
return 0;
if (price >= basePrice)
return ((price - basePrice) * 1e18) / basePrice;
else
return ((basePrice - price) * 1e18) / basePrice;
}
}
文件 20 的 22:TimeLocks.sol
pragma solidity ^0.8.0;
import "Ownable.sol";
contract TimeLocks is Ownable {
struct ContractChangeRequest {
bool changeRequested;
uint64 timestampRequest;
address newAddressRequested;
}
mapping(address => ContractChangeRequest) public changeRequests;
function requestAddressChange(address actualContract, address newContract)
external
onlyOwner
{
require(newContract != address(0));
ContractChangeRequest memory changeRequest =
ContractChangeRequest({
changeRequested: true,
timestampRequest: uint64(block.timestamp),
newAddressRequested: newContract
});
changeRequests[actualContract] = changeRequest;
}
function requestAddAddress(address newContract) external onlyOwner {
require(newContract != address(0));
ContractChangeRequest memory changeRequest =
ContractChangeRequest({
changeRequested: true,
timestampRequest: uint64(block.timestamp),
newAddressRequested: newContract
});
changeRequests[address(0)] = changeRequest;
}
function requestRemoveAddress(address oldContract) external onlyOwner {
require(oldContract != address(0));
ContractChangeRequest memory changeRequest =
ContractChangeRequest({
changeRequested: true,
timestampRequest: uint64(block.timestamp),
newAddressRequested: address(0)
});
changeRequests[oldContract] = changeRequest;
}
}
文件 21 的 22:TradePausable.sol
pragma solidity ^0.8.0;
abstract contract TradePausable {
bool private _mintPaused;
bool private _redeemPaused;
event MintPaused(address account);
event RedeemPaused(address account);
event MintUnpaused(address account);
event RedeemUnpaused(address account);
modifier whenMintNotPaused() {
_requireMintNotPaused();
_;
}
modifier whenMintPaused() {
_requireMintPaused();
_;
}
modifier whenRedeemNotPaused() {
_requireRedeemNotPaused();
_;
}
modifier whenRedeemPaused() {
_requireRedeemPaused();
_;
}
constructor() {
_mintPaused= false;
_redeemPaused= false;
}
function isMintPaused() public view returns(bool) {
return _mintPaused;
}
function isRedeemPaused() public view returns(bool) {
return _redeemPaused;
}
function _requireMintNotPaused() internal view virtual {
require(!_mintPaused, "Mint paused");
}
function _requireMintPaused() internal view virtual {
require(_mintPaused);
}
function _requireRedeemNotPaused() internal view virtual {
require(!_redeemPaused);
}
function _requireRedeemPaused() internal view virtual {
require(_redeemPaused);
}
function _pauseMint() internal virtual {
_mintPaused = true;
emit MintPaused(msg.sender);
}
function _unpauseMint() internal virtual {
_mintPaused = false;
emit MintUnpaused(msg.sender);
}
function _pauseRedeem() internal virtual {
_redeemPaused = true;
emit RedeemPaused(msg.sender);
}
function _unpauseRedeem() internal virtual {
_redeemPaused = false;
emit RedeemUnpaused(msg.sender);
}
}
文件 22 的 22:VariableFees.sol
pragma solidity ^0.8.0;
contract VariableFees {
function _variableFee(uint256 usdAmount, uint256 baseFee) internal pure returns(uint256 fee) {
if (usdAmount < 1000*1e18)
fee = baseFee;
else if (usdAmount < 10000*1e18)
fee = baseFee + 500 * (usdAmount - 1000*1e18) / 9000 / 1e18;
else if (usdAmount < 100000*1e18)
fee = baseFee + 500 + 500 * (usdAmount - 10000*1e18) / 90000 / 1e18;
else if (usdAmount < 1000000*1e18)
fee = baseFee + 1000 + 1000 * (usdAmount - 100000*1e18) / 900000 / 1e18;
else
fee = baseFee + 2000;
}
}
{
"compilationTarget": {
"SCMinter.sol": "SCMinter"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"gex","type":"address"},{"internalType":"address","name":"usdi","type":"address"},{"internalType":"address","name":"oracle","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"MintPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"MintUnpaused","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":false,"internalType":"address","name":"account","type":"address"}],"name":"RedeemPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"RedeemUnpaused","type":"event"},{"inputs":[],"name":"GEX","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDI","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"stablecoin","type":"address"}],"name":"addReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addReservesGEX","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint32","name":"swapFee","type":"uint32"}],"name":"addStablecoin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountGEX","type":"uint256"},{"internalType":"uint256","name":"baseFee","type":"uint256"}],"name":"amountFeeGEX","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stable","type":"address"},{"internalType":"uint256","name":"amountStable","type":"uint256"},{"internalType":"uint256","name":"usdPrice","type":"uint256"}],"name":"amountFeeMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stable","type":"address"},{"internalType":"uint256","name":"amountStable","type":"uint256"},{"internalType":"uint256","name":"usdPrice","type":"uint256"}],"name":"amountFeeRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stableIn","type":"address"},{"internalType":"address","name":"stableOut","type":"address"},{"internalType":"uint256","name":"usdPriceIn","type":"uint256"},{"internalType":"uint256","name":"usdPriceOut","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"amountFeeSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stablecoin","type":"address"},{"internalType":"uint256","name":"amountGEX","type":"uint256"}],"name":"amountMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stablecoin","type":"address"},{"internalType":"uint256","name":"amountStablecoin","type":"uint256"}],"name":"amountRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stablecoin","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"amountUSDI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"applyOracleChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"arbitrageur","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseMintFee","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseRedeemFee","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"baseSwapFees","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"stablecoin","type":"address"}],"name":"burnReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelChangeRequests","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"changeRequests","outputs":[{"internalType":"bool","name":"changeRequested","type":"bool"},{"internalType":"uint64","name":"timestampRequest","type":"uint64"},{"internalType":"address","name":"newAddressRequested","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collectFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountGEX","type":"uint256"},{"internalType":"uint256","name":"baseFee","type":"uint256"}],"name":"feeGEX","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stable","type":"address"},{"internalType":"uint256","name":"amountStable","type":"uint256"}],"name":"feeStablecoinMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stable","type":"address"},{"internalType":"uint256","name":"amountStable","type":"uint256"}],"name":"feeStablecoinRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stableIn","type":"address"},{"internalType":"address","name":"stableOut","type":"address"},{"internalType":"uint256","name":"usdPriceIn","type":"uint256"},{"internalType":"uint256","name":"usdPriceOut","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"feeSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBalanceGEX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"inGEXAmount","type":"uint256"},{"internalType":"address","name":"stablecoin","type":"address"}],"name":"getMintInfo","outputs":[{"internalType":"uint256","name":"gexPriceUSD","type":"uint256"},{"internalType":"uint256","name":"stablecoinPriceUSD","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"outStablecoinAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"inStablecoinAmount","type":"uint256"},{"internalType":"address","name":"stablecoin","type":"address"}],"name":"getRedeemInfo","outputs":[{"internalType":"uint256","name":"stablecoinPriceUSD","type":"uint256"},{"internalType":"uint256","name":"gexPriceUSD","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"outGEXAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stablecoin","type":"address"}],"name":"getSafeMintRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stablecoin","type":"address"}],"name":"getSafeRedeemRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"inAmount","type":"uint256"},{"internalType":"address","name":"stableIn","type":"address"},{"internalType":"address","name":"stableOut","type":"address"}],"name":"getStableSwapInfo","outputs":[{"internalType":"uint256","name":"inStablecoinPriceUSD","type":"uint256"},{"internalType":"uint256","name":"outStablecoinPriceUSD","type":"uint256"},{"internalType":"uint256","name":"quoteS2S1","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"outStablecoinAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTVC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMigrationRequested","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMintPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRedeemPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migrateMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"migrationMinter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stablecoin","type":"address"},{"internalType":"uint256","name":"amountInGEX","type":"uint256"}],"name":"mintStablecoin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintedTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleAge","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleGeminon","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"priceRecordsLongs","outputs":[{"internalType":"uint64","name":"lastTimestamp","type":"uint64"},{"internalType":"uint32","name":"weightedPrice","type":"uint32"},{"internalType":"uint256","name":"volume","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"priceRecordsShorts","outputs":[{"internalType":"uint64","name":"lastTimestamp","type":"uint64"},{"internalType":"uint32","name":"weightedPrice","type":"uint32"},{"internalType":"uint256","name":"volume","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountGEX","type":"uint256"}],"name":"receiveMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"stablecoin","type":"address"},{"internalType":"uint256","name":"amountInStablecoin","type":"uint256"}],"name":"redeemStablecoin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"removeStablecoin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newContract","type":"address"}],"name":"requestAddAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"actualContract","type":"address"},{"internalType":"address","name":"newContract","type":"address"}],"name":"requestAddressChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestBailoutFromPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newMinter","type":"address"}],"name":"requestMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"oldContract","type":"address"}],"name":"requestRemoveAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"arbitrageur_","type":"address"}],"name":"setArbitrageur","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feesCollector","type":"address"}],"name":"setCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"value","type":"uint32"}],"name":"setMintFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"value","type":"uint32"}],"name":"setRedeemFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"stable","type":"address"},{"internalType":"uint32","name":"value","type":"uint32"}],"name":"setSwapFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"stableIn","type":"address"},{"internalType":"address","name":"stableOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"stableSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stablecoins","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timestampMigrationRequest","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"validTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]