Contract 0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b8

Contract Overview

Balance:
0 MATIC
Txn Hash
Method
Block
From
To
Value [Txn Fee]
0x26fcf601766331d37fcd202edddd5d9d150aaafc425cffddefb1e5ae30cab722Create Pool186980862021-09-09 6:16:29639 days 19 hrs ago0xfd9656df3e4dca84c260137aecba416050aea145 IN  0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b80 MATIC0.0172627143
0xb77afe0df2c6295e561d92cefd83101b0c6c79a8ad2d1ea65bf6433dec223318Create Pool186980852021-09-09 6:16:27639 days 19 hrs ago0xfd9656df3e4dca84c260137aecba416050aea145 IN  0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b80 MATIC0.0172628223
0xf600c8bc7fca3bf9dc75f81e01cd94da84fea47460235279c1208ce744222880Create Pool186980842021-09-09 6:16:25639 days 19 hrs ago0xfd9656df3e4dca84c260137aecba416050aea145 IN  0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b80 MATIC0.0173141223
0xdc36b260c62362f41f1fc88a7ece3736e931a537bb7fe406aa69d85a4dadb6850x60806040186980812021-09-09 6:16:19639 days 19 hrs ago0xfd9656df3e4dca84c260137aecba416050aea145 IN  Create: LosslessV2Factory0 MATIC0.0160830933
[ Download CSV Export 
Latest 12 internal transactions
Parent Txn Hash Block From To Value
0x26fcf601766331d37fcd202edddd5d9d150aaafc425cffddefb1e5ae30cab722186980862021-09-09 6:16:29639 days 19 hrs ago 0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b8  Contract Creation0 MATIC
0x26fcf601766331d37fcd202edddd5d9d150aaafc425cffddefb1e5ae30cab722186980862021-09-09 6:16:29639 days 19 hrs ago 0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b8  Contract Creation0 MATIC
0x26fcf601766331d37fcd202edddd5d9d150aaafc425cffddefb1e5ae30cab722186980862021-09-09 6:16:29639 days 19 hrs ago 0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b8  Contract Creation0 MATIC
0x26fcf601766331d37fcd202edddd5d9d150aaafc425cffddefb1e5ae30cab722186980862021-09-09 6:16:29639 days 19 hrs ago 0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b8  Contract Creation0 MATIC
0xb77afe0df2c6295e561d92cefd83101b0c6c79a8ad2d1ea65bf6433dec223318186980852021-09-09 6:16:27639 days 19 hrs ago 0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b8  Contract Creation0 MATIC
0xb77afe0df2c6295e561d92cefd83101b0c6c79a8ad2d1ea65bf6433dec223318186980852021-09-09 6:16:27639 days 19 hrs ago 0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b8  Contract Creation0 MATIC
0xb77afe0df2c6295e561d92cefd83101b0c6c79a8ad2d1ea65bf6433dec223318186980852021-09-09 6:16:27639 days 19 hrs ago 0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b8  Contract Creation0 MATIC
0xb77afe0df2c6295e561d92cefd83101b0c6c79a8ad2d1ea65bf6433dec223318186980852021-09-09 6:16:27639 days 19 hrs ago 0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b8  Contract Creation0 MATIC
0xf600c8bc7fca3bf9dc75f81e01cd94da84fea47460235279c1208ce744222880186980842021-09-09 6:16:25639 days 19 hrs ago 0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b8  Contract Creation0 MATIC
0xf600c8bc7fca3bf9dc75f81e01cd94da84fea47460235279c1208ce744222880186980842021-09-09 6:16:25639 days 19 hrs ago 0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b8  Contract Creation0 MATIC
0xf600c8bc7fca3bf9dc75f81e01cd94da84fea47460235279c1208ce744222880186980842021-09-09 6:16:25639 days 19 hrs ago 0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b8  Contract Creation0 MATIC
0xf600c8bc7fca3bf9dc75f81e01cd94da84fea47460235279c1208ce744222880186980842021-09-09 6:16:25639 days 19 hrs ago 0x0b272a52e64542c7b2bfe001ffe6ead1ae24c4b8  Contract Creation0 MATIC
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
LosslessV2Factory

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 20 : LosslessV2Factory.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;

import "./LosslessV2Token.sol";
import "./LosslessV2Pool.sol";
import "../interfaces/ILosslessV2Factory.sol";
import "./ERC20.sol";

contract LosslessV2Factory is ILosslessV2Factory {
	address public override feeTo;
	address public override DAO;
	address public override pendingDAO;
	uint256 public override feePercent; //  usage: fee = totalInterest.mul(feePercent).div(PRECISION)

	// all pool related
	address[] public override allPools;
	// BTC - USDT: USDT, DAI, USDC
	//     bidToken ----> principalToken -> poolAddress
	//         |                   |          |
	mapping(address => mapping(address => address)) public override getPool;
	mapping(address => bool) public override isPoolActive;

	mapping(address => address) public override getPoolShortToken;
	mapping(address => address) public override getPoolLongToken;
	mapping(address => address) public override getPoolSponsorToken;

	modifier onlyDAO() {
		require(msg.sender == DAO, "LosslessV2Factory: FORBIDDEN");
		_;
	}

	constructor(address _DAO) public {
		require(_DAO != address(0), "LosslessV2Factory: set DAO the zero address");
		DAO = _DAO; // default is DAO
	}

	function allPoolsLength() external view override returns (uint256) {
		return allPools.length;
	}

	function createPool(
		address bidToken,
		address principalToken,
		address addressProvider,
		address aggregator,
		uint256 biddingDuration,
		uint256 gamingDuration,
		string memory tokenName,
		string memory tokenSymbol
	) external override onlyDAO {
		// pool setting check
		require(bidToken != principalToken, "LosslessV2Factory: IDENTICAL_ADDRESSES");
		require((bidToken != address(0)) && (principalToken != address(0)), "LosslessV2Factory: ZERO_ADDRESS");
		require(addressProvider != address(0), "LosslessV2Factory: ADDRESS PROVIDER ZERO_ADDRESS");
		require(aggregator != address(0), "LosslessV2Factory: AGGREGATOR ZERO_ADDRESS");
		require(getPool[bidToken][principalToken] == address(0), "LosslessV2Factory: POOL_EXISTS");
		require(biddingDuration > 0, "LosslessV2Factory: BIDDING DURATION INVALID_AMOUNT");
		require(gamingDuration > 0, "LosslessV2Factory: GAMING DURATION INVALID_AMOUNT");
		// token name and symbol check
		require(bytes(tokenName).length != 0, "LosslessV2Factory: TOKEN NAME INPUT IS INVALID");
		require(bytes(tokenSymbol).length != 0, "LosslessV2Factory: TOKEN SYMBOL INPUT IS INVALID");

		bytes32 salt = keccak256(abi.encodePacked(allPools.length, bidToken, principalToken, addressProvider, aggregator));
		LosslessV2Pool newPool = new LosslessV2Pool{ salt: salt }(bidToken, principalToken, addressProvider, aggregator, biddingDuration, gamingDuration);
		(address shortToken, address longToken, address sponsorToken) = _initializeTokens(
			tokenName,
			tokenSymbol,
			ERC20(principalToken).decimals(),
			address(newPool)
		);
		newPool.initialize(shortToken, longToken, sponsorToken);
		// save pool address to pool related
		getPool[bidToken][principalToken] = address(newPool);
		allPools.push(address(newPool));
		isPoolActive[address(newPool)] = true;
		// save pool tokens related
		getPoolShortToken[address(newPool)] = shortToken;
		getPoolLongToken[address(newPool)] = longToken;
		getPoolSponsorToken[address(newPool)] = sponsorToken;

		emit PoolCreated(bidToken, principalToken, address(newPool), allPools.length);
	}

	///@dev only DAO can call this function
	function terminatePool(address pool) external onlyDAO returns (bool) {
		require(isPoolActive[pool] == true, "LosslessV2Factory: POOL MUST BE ACTIVE");

		// call pool termination function to
		LosslessV2Pool(pool).poolTermination();
		// update pool related
		isPoolActive[pool] = false;

		emit PoolTerminated(pool);
		return true;
	}

	function _initializeTokens(
		string memory _tokenName,
		string memory _tokenSymbol,
		uint8 _decimals,
		address _pool
	)
		private
		returns (
			address shortToken,
			address longToken,
			address sponsorToken
		)
	{
		require(_pool != address(0), "LosslessV2Factory: ADDRESS PROVIDER ZERO_ADDRESS");

		// create a list of tokens for the new pool
		shortToken = _createToken(string(abi.encodePacked("st", _tokenName)), string(abi.encodePacked("st", _tokenSymbol)), _decimals, _pool);
		longToken = _createToken(string(abi.encodePacked("lg", _tokenName)), string(abi.encodePacked("lg", _tokenSymbol)), _decimals, _pool);
		sponsorToken = _createToken(string(abi.encodePacked("sp", _tokenName)), string(abi.encodePacked("sp", _tokenSymbol)), _decimals, _pool);
	}

	function _createToken(
		string memory _name,
		string memory _symbol,
		uint8 _decimals,
		address _pool
	) private returns (address) {
		bytes32 salt = keccak256(abi.encodePacked(_name, _symbol, _decimals, _pool));
		LosslessV2Token newToken = new LosslessV2Token{ salt: salt }(_name, _symbol, _decimals, _pool);

		return address(newToken);
	}

	// below functions all limited to DAO

	/**
	 * @dev	 The default DAO can assign the receiver of the trading fee
	 * @param _feeTo	the receiver of the trading fee
	 **/
	function setFeeTo(address _feeTo) external override onlyDAO {
		require(_feeTo != address(0), "LosslessV2Factory: set feeTo to the zero address");
		feeTo = _feeTo;
		emit FeeToChanged(feeTo);
	}

	/**
	 * @dev	 only DAO can set the feePercent (usage: fee = totalInterest.mul(feePercent).div(PRECISION))
	 * @param _feePercent	percentage of total interest as trading fee: 1% - 100, 10% - 1000, 100% - 10000
	 **/
	function setFeePercent(uint256 _feePercent) external override onlyDAO {
		require(_feePercent < 10**4, "LosslessV2Factory: feePercent must be less than PRECISION");
		feePercent = _feePercent;
		emit FeePercentChanged(feePercent);
	}

	/**
	 * @dev The default DAO and DAO can assign pendingDAO to others by calling `setDAO`
	 * @param _pendingDAO	new DAO address
	 **/
	function setPendingDAO(address _pendingDAO) external override onlyDAO {
		require(_pendingDAO != address(0), "LosslessV2Factory: set _pendingDAO to the zero address");
		pendingDAO = _pendingDAO;
		emit proposeDAOChange(pendingDAO);
	}

	/**
	 * @dev double confirm on whether to accept the pending changes or not
	 **/
	function setDAO() external override onlyDAO {
		require(pendingDAO != address(0), "LosslessV2Factory: set _DAO to the zero address");
		DAO = pendingDAO;
		pendingDAO = address(0);
		emit DAOChanged(DAO);
	}
}

File 2 of 20 : LosslessV2Token.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;

import "./ERC20.sol";
import "../interfaces/ILosslessV2Pool.sol";

contract LosslessV2Token is ERC20 {
	address public adminPool;

	// limit only pool can mint token
	modifier onlyAdminPool() {
		require(msg.sender == adminPool, "LosslessV2Token: FORBIDDEN");
		_;
	}

	constructor(
		string memory _name,
		string memory _symbol,
		uint8 _decimals,
		address _adminPool
	) public ERC20(_name, _symbol, _decimals) {
		require(address(0) != _adminPool, "LosslessV2Token: set pool to the zero address");
		adminPool = _adminPool;
	}

	function mint(address _to, uint256 _amount) external onlyAdminPool returns (bool) {
		_mint(_to, _amount);
		return true;
	}

	function burn(address _from, uint256 _amount) external onlyAdminPool returns (bool) {
		_burn(_from, _amount);
		return true;
	}
}

File 3 of 20 : LosslessV2Pool.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;

import "../interfaces/ILosslessV2Pool.sol";
import "../interfaces/ILosslessV2Factory.sol";
import "../interfaces/ILosslessV2Token.sol";

import "../interfaces/IPriceOracleGetter.sol";
import "../interfaces/ILendingPoolAddressesProvider.sol";
import "../interfaces/ILendingPool.sol";
import "../interfaces/IProtocolDataProvider.sol";
import "../interfaces/IStakedToken.sol";

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";

import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
import "@chainlink/contracts/src/v0.6/interfaces/KeeperCompatibleInterface.sol";

contract LosslessV2Pool is ILosslessV2Pool, KeeperCompatibleInterface{
	using SafeMath for uint256;

	// basic info for initializing a pool
	address public override factory;
	address public override bidToken;
	address public override principalToken;
	address public override aToken;
	address public override addressProvider;

	AggregatorV3Interface private priceFeed;

	// used for calculating share price, define the precision is 0.0001
	uint256 public constant PRECISION = 10**4;

	///@dev the actual share value is valuePerShortToken /  PRECISION (constant = 10000)
	uint256 public valuePerShortToken = PRECISION; // the value of a single share - short
	uint256 public valuePerLongToken = PRECISION; // the value of a single share - long
	uint256 public constant valuePerSponsorToken = PRECISION; // the value of sponsor share should be fixed to PRECISION

	uint256 private totalInterest;

	GameStatus public status;
	PoolTokensInfo public poolTokensInfo;
	mapping(address => uint256) public override inPoolTimestamp;

	ILosslessV2Token private _shortToken;
	ILosslessV2Token private _longToken;
	ILosslessV2Token private _sponsorToken;

	// lock modifier
	bool private accepting = true;
	modifier lock() {
		require(accepting == true, "LosslessV2Pool: LOCKED");
		accepting = false;
		_;
		accepting = true;
	}

	modifier onlyFactory() {
		require(msg.sender == factory, "LosslessV2Factory: FACTORY ONLY");
		_;
	}

	modifier onlyAfter(uint256 _time) {
		require(block.timestamp > _time, "LosslessV2Pool: INVALID TIMESTAMP AFTER");
		_;
	}

	constructor(
		address _bidToken,
		address _principalToken,
		address _addressProvider,
		address _aggregator,
		uint256 _biddingDuration,
		uint256 _gamingDuration
	) public {
		factory = msg.sender;
		bidToken = _bidToken;
		principalToken = _principalToken;

		addressProvider = _addressProvider;
		aToken = _getATokenAddress(principalToken);

		priceFeed = AggregatorV3Interface(_aggregator);

		// modify status variable
		status.gameRound = 1;
		status.durationOfBidding = _biddingDuration;
		status.durationOfGame = _gamingDuration;
		status.lastUpdateTimestamp = block.timestamp;
		// status.initialPrice - unchange for now
		// status.endPrice - unchange for now
		// status.isShortLastRoundWinner - default to false
		status.isFirstRound = true;
		status.isFirstUser = true;
		status.currState = PoolStatus.FirstGame;
	}

	/**
	 * @dev initialize pool
	 **/
	function initialize(
		address shortToken_,
		address longToken_,
		address sponsorToken_
	) external override onlyFactory {
		poolTokensInfo.shortToken = shortToken_;
		poolTokensInfo.longToken = longToken_;
		poolTokensInfo.sponsorToken = sponsorToken_;

		_shortToken = ILosslessV2Token(shortToken_);
		_longToken = ILosslessV2Token(longToken_);
		_sponsorToken = ILosslessV2Token(sponsorToken_);
	}

	/**
	 * @dev only be called once, after initalize
	 **/
	function startFirstRound() external override {
		require(status.isFirstRound == true, "LosslessV2Pool: NOT FIRST ROUND!");
		require(status.currState == PoolStatus.FirstGame, "LosslessV2Pool: WRONG STATUS");
		// modify status variable
		// status.gameRound = 1;
		status.lastUpdateTimestamp = block.timestamp;
		// status.initialPrice - unchange for now
		// status.endPrice - unchange for now
		// status.isShortLastRoundWinner - unchange for now
		status.isFirstRound = false;
		// status.isFirstUser = true;
		status.currState = PoolStatus.Accepting;
	}

	/**
	 * @dev start the gaming, lock pool and transfer asset to defi lending
	 **/
	function startGame() public override lock onlyAfter(status.lastUpdateTimestamp.add(status.durationOfBidding)) {
		require(status.currState == PoolStatus.Accepting, "LosslessV2Pool: WRONG STATUS");
		require(_shortToken.totalSupply() != 0 && _longToken.totalSupply() != 0, "LosslessV2Pool: NO FUND IN POOL");
		// modify status variable
		// status.gameRound = 1;
		status.lastUpdateTimestamp = block.timestamp;
		// fisrt user can set the inital price
		if (status.isFirstUser == true) {
			status.initialPrice = _getPrice();
			status.isFirstUser = false;
		}
		// status.endPrice - unchange for now
		// status.isShortLastRoundWinner - unchange for now
		// status.isFirstRound = false;
		// status.isFirstUser = true;
		status.currState = PoolStatus.Locked;

		// transfer to aave
		_supplyToAAVE(principalToken, IERC20(principalToken).balanceOf(address(this)));
	}

	/**
	 * @dev end the gaming, redeem assets from aave and get end price
	 **/
	function endGame() public override lock onlyAfter(status.lastUpdateTimestamp.add(status.durationOfGame)) {
		require(status.currState == PoolStatus.Locked, "LosslessV2Pool: WRONG STATUS");

		// modify status variable
		status.gameRound = status.gameRound.add(1);
		status.lastUpdateTimestamp = block.timestamp;
		// status.initialPrice - unchange for now
		// status.endPrice - unchange for now
		// status.isShortLastRoundWinner - unchange for now
		// status.isFirstRound = false;
		status.isFirstUser = true;
		status.currState = PoolStatus.Accepting;

		// redeem from AAVE
		_redeemFromAAVE(principalToken, 0); // redeem all
		// get end price
		status.endPrice = _getPrice();

		// if end price higher than inital price -> long users win !
		if (status.endPrice >= status.initialPrice) {
			status.isShortLastRoundWinner = false;
		} else {
			status.isShortLastRoundWinner = true;
		}

		// update interest and principal amount
		uint256 totalShortPrincipal = _shortToken.totalSupply().mul(valuePerShortToken).div(PRECISION);
		uint256 totalLongPrincipal = _longToken.totalSupply().mul(valuePerLongToken).div(PRECISION);
		uint256 totalSponsorPrincipal = _sponsorToken.totalSupply().mul(valuePerSponsorToken).div(PRECISION);
		uint256 totalPrincipal = totalShortPrincipal.add(totalLongPrincipal.add(totalSponsorPrincipal));
		if (IERC20(principalToken).balanceOf(address(this)) < totalPrincipal) {
			totalInterest = 0; // in case kovan testnet give us aToken slightly less than deposit amount
		} else {
			totalInterest = IERC20(principalToken).balanceOf(address(this)).sub(totalPrincipal);
		}

		// update share value
		_updateTokenValue(totalShortPrincipal, totalLongPrincipal);

		emit AnnounceWinner(status.isShortLastRoundWinner, status.initialPrice, status.endPrice);
	}

	/**
	 * @dev chainlink keeper checkUpkeep function to constantly check whether we need function call
	 **/
	function checkUpkeep(bytes calldata checkData) external override returns (bool upkeepNeeded, bytes memory performData) {
		PoolStatus currState = status.currState;
		uint256 lastUpdateTimestamp = status.lastUpdateTimestamp;
		uint256 durationOfGame = status.durationOfGame;
		uint256 durationOfBidding = status.durationOfBidding;

		if (currState == PoolStatus.Accepting && block.timestamp > lastUpdateTimestamp.add(durationOfBidding)) {
			upkeepNeeded = true;
		} else if (currState == PoolStatus.Locked && block.timestamp > lastUpdateTimestamp.add(durationOfGame)) {
			upkeepNeeded = true;
		} else {
			upkeepNeeded = false;
		}
		performData = checkData;
	}

	/**
	 * @dev once checkUpKeep been trigered, keeper will call performUpKeep
	 **/
	function performUpkeep(bytes calldata performData) external override {
		PoolStatus currState = status.currState;
		uint256 lastUpdateTimestamp = status.lastUpdateTimestamp;
		uint256 durationOfGame = status.durationOfGame;
		uint256 durationOfBidding = status.durationOfBidding;

		if (currState == PoolStatus.Accepting && block.timestamp > lastUpdateTimestamp.add(durationOfBidding)) {
			startGame();
		}
		if (currState == PoolStatus.Locked && block.timestamp > lastUpdateTimestamp.add(durationOfGame)) {
			endGame();
		}
		performData;
	}

	/**
	 * @dev termination function, use this to terminate the game
	 **/
	function poolTermination() external override onlyFactory {
		// only when pool status is at Accepting
		require(status.currState == PoolStatus.Accepting, "LosslessV2Pool: WRONG STATUS");

		// modify status variable
		// status.gameRound = status.gameRound.add(1);
		// status.durationOfGame = 6 days;
		// status.durationOfBidding = 1 days;
		// status.lastUpdateTimestamp = block.timestamp;
		// status.initialPrice - unchange for now
		// status.endPrice - unchange for now
		// status.isShortLastRoundWinner - unchange for now
		// status.isFirstRound = false;
		// status.isFirstUser = true;
		status.currState = PoolStatus.Terminated;
	}

	/**
	 * @dev users can add principal as long as the status is accpeting
	 * @param shortPrincipalAmount how many principal in short pool does user want to deposit
	 * @param longPrincipalAmount how many principal in long pool does user want to deposit
	 **/
	function deposit(uint256 shortPrincipalAmount, uint256 longPrincipalAmount) external override lock {
		require(status.currState == PoolStatus.Accepting, "LosslessV2Pool: WRONG STATUS");
		require(shortPrincipalAmount > 0 || longPrincipalAmount > 0, "LosslessV2Pool: INVALID AMOUNT");

		// fisrt user can set the inital price
		if (status.isFirstUser == true) {
			status.initialPrice = _getPrice();
			status.isFirstUser = false;
		}
		// // if user's balance is zero record user's join timestamp for reward
		if (_shortToken.balanceOf(msg.sender) == 0 && _longToken.balanceOf(msg.sender) == 0) {
			inPoolTimestamp[msg.sender] = block.timestamp;
		}
		// transfer principal to pool contract
		SafeERC20.safeTransferFrom(IERC20(principalToken), msg.sender, address(this), shortPrincipalAmount.add(longPrincipalAmount));
		_mintTokens(true, msg.sender, shortPrincipalAmount, longPrincipalAmount);

		emit Deposit(shortPrincipalAmount, longPrincipalAmount);
	}

	/**
	 * @dev user can call it to redeem pool tokens to principal tokens
	 * @param shortTokenAmount 	how many short token in short pool does user want to redeem
	 * @param longTokenAmount 	how many long token in long pool does user want to redeem
	 **/
	function withdraw(
		bool isAToken,
		uint256 shortTokenAmount,
		uint256 longTokenAmount
	) external override lock {
		// withdraw should have no limitation in pool status
		require(shortTokenAmount > 0 || longTokenAmount > 0, "LosslessV2Pool: INVALID AMOUNT");

		// check user token balance
		uint256 userShortTokenBalance = _shortToken.balanceOf(msg.sender);
		uint256 userLongTokenBalance = _longToken.balanceOf(msg.sender);
		require(userShortTokenBalance >= shortTokenAmount && userLongTokenBalance >= longTokenAmount, "LosslessV2Pool: INSUFFICIENT BALANCE");

		// calculate withdraw principal amount
		uint256 shortPrincipalAmount = shortTokenAmount.mul(valuePerShortToken).div(PRECISION);
		uint256 longPrincipalAmount = longTokenAmount.mul(valuePerLongToken).div(PRECISION);

		// user withdraw will cause timestamp update -> reduce their goverance reward
		inPoolTimestamp[msg.sender] = block.timestamp;

		// burn user withdraw token
		_burnTokens(false, msg.sender, shortTokenAmount, longTokenAmount);

		/*  pool status | isAToken | Operation
				lock	     T       transfer aToken
				lock 		 F		 redeem then transfer principal Token
			  unlock  		 T 		 supply to aave then transfer aToken
			  unlock         F       transfer principal token
		 */
		if (isAToken == false) {
			if (status.currState == PoolStatus.Locked) {
				_redeemFromAAVE(principalToken, shortPrincipalAmount.add(longPrincipalAmount));
			}
			SafeERC20.safeTransfer(IERC20(principalToken), msg.sender, shortPrincipalAmount.add(longPrincipalAmount));
		} else {
			if (status.currState == PoolStatus.Accepting) {
				_supplyToAAVE(principalToken, shortPrincipalAmount.add(longPrincipalAmount));
			}
			SafeERC20.safeTransfer(IERC20(aToken), msg.sender, shortPrincipalAmount.add(longPrincipalAmount));
		}

		emit Withdraw(isAToken, shortTokenAmount, longTokenAmount);
	}

	/**
	 * @dev user can call this to shift share from long -> short, short -> long without withdrawing assets
	 * @param fromLongToShort is user choosing to shift from long to short
	 * @param swapTokenAmount the amount of token that user wishes to swap
	 **/
	function swap(bool fromLongToShort, uint256 swapTokenAmount) external override lock {
		require(status.currState == PoolStatus.Accepting, "LosslessV2Pool: WRONG STATUS");
		uint256 shortTokenBalance = _shortToken.balanceOf(msg.sender);
		uint256 longTokenBalance = _longToken.balanceOf(msg.sender);
		uint256 tokenBalanceOfTargetPosition = fromLongToShort ? longTokenBalance : shortTokenBalance;
		// check user balance
		require(swapTokenAmount > 0 && swapTokenAmount <= tokenBalanceOfTargetPosition, "LosslessV2Pool: INSUFFICIENT BALANCE");

		// reallocate user's share balance
		if (fromLongToShort == true) {
			// user wants to shift from long to short, so burn long share and increase short share
			_burnTokens(false, msg.sender, 0, swapTokenAmount);
			_mintTokens(false, msg.sender, swapTokenAmount.mul(valuePerLongToken).div(valuePerShortToken), 0);
		} else {
			// user wants to shift from short to long, so burn short share and increase long share
			_burnTokens(false, msg.sender, swapTokenAmount, 0);
			_mintTokens(false, msg.sender, 0, swapTokenAmount.mul(valuePerShortToken).div(valuePerLongToken));
		}
	}

	/**
	 * @dev sponsr can deposit and withdraw principals to the game
	 * @param principalAmount amount of principal token
	 **/
	function sponsorDeposit(uint256 principalAmount) external override lock {
		require(status.currState != PoolStatus.Terminated, "LosslessV2Pool: POOL TERMINATED");
		require(principalAmount > 0, "LosslessV2Pool: INVALID AMOUNT");
		require(IERC20(principalToken).balanceOf(msg.sender) >= principalAmount, "LosslessV2Pool: INSUFFICIENT BALANCE");

		// transfer asset first
		SafeERC20.safeTransferFrom(IERC20(principalToken), msg.sender, address(this), principalAmount);

		// check current game state
		if (status.currState == PoolStatus.Locked) {
			// if during the lock time
			// interact with AAVE to get the principal back
			_supplyToAAVE(principalToken, principalAmount);
		}

		// mint sponsor token
		_sponsorToken.mint(msg.sender, principalAmount);

		emit SponsorDeposit(principalAmount);
	}

	/**
	 * @dev sponsr can deposit and withdraw principals to the game
	 * @param sponsorTokenAmount amount of zero token
	 **/
	function sponsorWithdraw(uint256 sponsorTokenAmount) external override lock {
		require(sponsorTokenAmount > 0, "LosslessV2Pool: INVALID AMOUNT");
		// burn user sponsor token
		_sponsorToken.burn(msg.sender, sponsorTokenAmount);

		// check current game state
		if (status.currState == PoolStatus.Locked) {
			// if during the lock time
			// interact with AAVE to get the principal back
			_redeemFromAAVE(principalToken, sponsorTokenAmount);
		}

		// transfer principal token
		SafeERC20.safeTransfer(IERC20(principalToken), msg.sender, sponsorTokenAmount);

		emit SponsorWithdraw(sponsorTokenAmount);
	}

	/**
	 * @dev calculate each token's value
	 * @param _totalShortPrincipal 	the total amount of short principal
	 * @param _totalLongPrincipal	the total amount of long principal
	 **/
	function _updateTokenValue(uint256 _totalShortPrincipal, uint256 _totalLongPrincipal) private {
		address feeTo = ILosslessV2Factory(factory).feeTo();
		uint256 feePercent = ILosslessV2Factory(factory).feePercent();
		uint256 fee = totalInterest.mul(feePercent).div(PRECISION);

		// if fee is on and feeTo been set
		if (feePercent != 0 && feeTo != address(0)) {
			totalInterest = totalInterest.sub(fee);
			SafeERC20.safeTransfer(IERC20(principalToken), feeTo, fee);
		}

		// update short/long token value
		if (status.isShortLastRoundWinner == true) {
			// short win
			_totalShortPrincipal = _totalShortPrincipal.add(totalInterest);
			valuePerShortToken = _totalShortPrincipal.mul(PRECISION).div(_shortToken.totalSupply());
		} else if (status.isShortLastRoundWinner == false) {
			// long win
			_totalLongPrincipal = _totalLongPrincipal.add(totalInterest);
			valuePerLongToken = _totalLongPrincipal.mul(PRECISION).div(_longToken.totalSupply());
		}

		emit UpdateTokenValue(valuePerShortToken, valuePerLongToken);
	}

	/**
	 * @dev supply to aave protocol
	 * @param _asset 	the address of the principal token
	 * @param _amount	the amount of the principal token wish to supply to AAVE
	 **/
	function _supplyToAAVE(address _asset, uint256 _amount) private {
		address lendingPoolAddress = ILendingPoolAddressesProvider(addressProvider).getLendingPool();
		ILendingPool lendingPool = ILendingPool(lendingPoolAddress);
		SafeERC20.safeApprove(IERC20(_asset), address(lendingPool), _amount);
		lendingPool.deposit(_asset, _amount, address(this), 0);
	}

	/**
	 * @dev redeem from aave protocol
	 * @param _asset 	the address of the principal token
	 * @param _amount	the amount of the principal token wish to withdraw from AAVE
	 **/
	function _redeemFromAAVE(address _asset, uint256 _amount) private {
		// lendingPool
		address lendingPoolAddress = ILendingPoolAddressesProvider(addressProvider).getLendingPool();
		ILendingPool lendingPool = ILendingPool(lendingPoolAddress);
		// protocol data provider
		aToken = _getATokenAddress(_asset);
		if (_amount == 0) {
			_amount = IERC20(aToken).balanceOf(address(this));
		}
		lendingPool.withdraw(_asset, _amount, address(this));
	}

	/**
	 * @dev get atoken address
	 * @param _asset 	the address of the principal token
	 **/
	function _getATokenAddress(address _asset) private view returns (address _aToken) {
		// protocol data provider
		uint8 number = 1;
		bytes32 id = bytes32(bytes1(number));
		address dataProviderAddress = ILendingPoolAddressesProvider(addressProvider).getAddress(id);
		IProtocolDataProvider protocolDataProvider = IProtocolDataProvider(dataProviderAddress);
		(_aToken, , ) = protocolDataProvider.getReserveTokensAddresses(_asset);
	}

	/**
	 * @dev mint token function to mint long and short token
	 * @param _isPrincipal 	true: principal, false:long/short token amount
	 * @param _to			the destination account token got burned
	 * @param _shortAmount 	the amount of the token to short
	 * @param _longAmount 	the amount of the token to long
	 **/
	function _mintTokens(
		bool _isPrincipal,
		address _to,
		uint256 _shortAmount,
		uint256 _longAmount
	) private {
		if (_isPrincipal == true) {
			// convert principal token amount to long/short token amount
			_shortAmount = _shortAmount.mul(PRECISION).div(valuePerShortToken);
			_longAmount = _longAmount.mul(PRECISION).div(valuePerLongToken);
		}
		if (_shortAmount != 0) {
			_shortToken.mint(_to, _shortAmount);
		}
		if (_longAmount != 0) {
			_longToken.mint(_to, _longAmount);
		}
	}

	/**
	 * @dev burn token function to burn long and short token
	 * @param _isPrincipal 	true: principal, false:long/short token amount
	 * @param _from			the destination account token got burned
	 * @param _shortAmount 	the amount of the token to short
	 * @param _longAmount 	the amount of the token to long
	 **/
	function _burnTokens(
		bool _isPrincipal,
		address _from,
		uint256 _shortAmount,
		uint256 _longAmount
	) private {
		if (_isPrincipal == true) {
			// convert principal token amount to long/short token amount
			_shortAmount = _shortAmount.mul(PRECISION).div(valuePerShortToken);
			_longAmount = _longAmount.mul(PRECISION).div(valuePerLongToken);
		}
		if (_shortAmount != 0) {
			_shortToken.burn(_from, _shortAmount);
		}
		if (_longAmount != 0) {
			_longToken.burn(_from, _longAmount);
		}
	}

	/**
	 * @dev communicate with oracle to get current trusted price
	 * @return price ratio of bidToken * PRECISION / principalToken -> the result comes with precision
	 **/
	function _getPrice() private view returns (int256) {
		(uint80 roundID, int256 price, uint256 startedAt, uint256 timeStamp, uint80 answeredInRound) = priceFeed.latestRoundData();
		return price;
	}

	/**
	 * @dev return user's long token equivalent principal token amount
	 **/
	function userLongPrincipalBalance(address userAddress) external view override returns (uint256 userLongAmount) {
		userLongAmount = _longToken.balanceOf(userAddress).mul(valuePerLongToken).div(PRECISION);
	}

	/**
	 * @dev return user's short token equivalent principal token amount
	 **/
	function userShortPrincipalBalance(address userAddress) external view override returns (uint256 userShortAmount) {
		userShortAmount = _shortToken.balanceOf(userAddress).mul(valuePerShortToken).div(PRECISION);
	}

	/**
	 * @dev claim AAVE token rewards
	 * @param stakedAAVEAddress_ stakedAAVE contract address
	 * @param amount_  The amount of AAVE to be claimed. Use type(uint).max to claim all outstanding rewards for the user.
	 */
	function claimAAVE(address stakedAAVEAddress_, uint256 amount_ ) external override {
		require(stakedAAVEAddress_ != address(0), "LosslessV2Pool: stakedAAVEAddress_ ZERO ADDRESS");
		address feeTo = ILosslessV2Factory(factory).feeTo();
		require(feeTo != address(0), "LosslessV2Pool: feeTo ZERO ADDRESS");

		IStakedToken stakedAAVE = IStakedToken(stakedAAVEAddress_);
		stakedAAVE.claimRewards(feeTo, amount_);
	}
}

File 4 of 20 : ILosslessV2Factory.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;

interface ILosslessV2Factory {
	// event related
	event PoolCreated(address indexed bidToken, address indexed principalToken, address pool, uint256 allPoolLength);
	event PoolTerminated(address pool);
	event FeeToChanged(address feeTo);
	event FeePercentChanged(uint256 feePercent);
	event proposeDAOChange(address pendingDAO);
	event DAOChanged(address DAO);

	function allPools(uint256) external view returns (address pool);

	function allPoolsLength() external view returns (uint256);

	function getPool(address bidToken, address principalToken) external view returns (address pool);

	function isPoolActive(address) external view returns (bool);

	function getPoolShortToken(address) external view returns (address);

	function getPoolLongToken(address) external view returns (address);

	function getPoolSponsorToken(address) external view returns (address);

	function createPool(
		address bidToken,
		address principalToken,
		address addressProvider,
		address aggregator,
		uint256 biddingDuration,
		uint256 gamingDuration,
		string memory tokenName,
		string memory tokenSymbol
	) external;

	// all fee related getter functions
	function feeTo() external view returns (address);

	function DAO() external view returns (address);

	function pendingDAO() external view returns (address);

	function feePercent() external view returns (uint256);

	// only admin functions
	// The default DAO is admin but admin can assign this role to others by calling `setDAO`
	function setFeeTo(address) external;

	function setFeePercent(uint256 _feePercent) external;

	function setPendingDAO(address _pendingDAO) external;

	function setDAO() external;
}

File 5 of 20 : ERC20.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;

import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20 {
	using SafeMath for uint256;

	mapping(address => uint256) private _balances;

	mapping(address => mapping(address => uint256)) private _allowances;

	uint256 private _totalSupply;

	string private _name;
	string private _symbol;
	uint8 private _decimals;

	/**
	 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
	 * a default value of 18.
	 *
	 * To select a different value for {decimals}, use {_setupDecimals}.
	 *
	 * All three of these values are immutable: they can only be set once during
	 * construction.
	 */
	constructor(
		string memory name_,
		string memory symbol_,
		uint8 decimals_
	) public {
		_name = name_;
		_symbol = symbol_;
		_decimals = decimals_;
	}

	/**
	 * @dev Returns the name of the token.
	 */
	function name() public view virtual returns (string memory) {
		return _name;
	}

	/**
	 * @dev Returns the symbol of the token, usually a shorter version of the
	 * name.
	 */
	function symbol() public view virtual returns (string memory) {
		return _symbol;
	}

	/**
	 * @dev Returns the number of decimals used to get its user representation.
	 * For example, if `decimals` equals `2`, a balance of `505` tokens should
	 * be displayed to a user as `5,05` (`505 / 10 ** 2`).
	 *
	 * Tokens usually opt for a value of 18, imitating the relationship between
	 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
	 * called.
	 *
	 * NOTE: This information is only used for _display_ purposes: it in
	 * no way affects any of the arithmetic of the contract, including
	 * {IERC20-balanceOf} and {IERC20-transfer}.
	 */
	function decimals() public view virtual returns (uint8) {
		return _decimals;
	}

	/**
	 * @dev See {IERC20-totalSupply}.
	 */
	function totalSupply() public view virtual override returns (uint256) {
		return _totalSupply;
	}

	/**
	 * @dev See {IERC20-balanceOf}.
	 */
	function balanceOf(address account) public view virtual override returns (uint256) {
		return _balances[account];
	}

	/**
	 * @dev See {IERC20-transfer}.
	 *
	 * Requirements:
	 *
	 * - `recipient` cannot be the zero address.
	 * - the caller must have a balance of at least `amount`.
	 */
	function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
		_transfer(_msgSender(), recipient, amount);
		return true;
	}

	/**
	 * @dev See {IERC20-allowance}.
	 */
	function allowance(address owner, address spender) public view virtual override returns (uint256) {
		return _allowances[owner][spender];
	}

	/**
	 * @dev See {IERC20-approve}.
	 *
	 * Requirements:
	 *
	 * - `spender` cannot be the zero address.
	 */
	function approve(address spender, uint256 amount) public virtual override returns (bool) {
		_approve(_msgSender(), spender, amount);
		return true;
	}

	/**
	 * @dev See {IERC20-transferFrom}.
	 *
	 * Emits an {Approval} event indicating the updated allowance. This is not
	 * required by the EIP. See the note at the beginning of {ERC20}.
	 *
	 * Requirements:
	 *
	 * - `sender` and `recipient` cannot be the zero address.
	 * - `sender` must have a balance of at least `amount`.
	 * - the caller must have allowance for ``sender``'s tokens of at least
	 * `amount`.
	 */
	function transferFrom(
		address sender,
		address recipient,
		uint256 amount
	) public virtual override returns (bool) {
		_transfer(sender, recipient, amount);
		_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
		return true;
	}

	/**
	 * @dev Atomically increases the allowance granted to `spender` by the caller.
	 *
	 * This is an alternative to {approve} that can be used as a mitigation for
	 * problems described in {IERC20-approve}.
	 *
	 * Emits an {Approval} event indicating the updated allowance.
	 *
	 * Requirements:
	 *
	 * - `spender` cannot be the zero address.
	 */
	function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
		_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
		return true;
	}

	/**
	 * @dev Atomically decreases the allowance granted to `spender` by the caller.
	 *
	 * This is an alternative to {approve} that can be used as a mitigation for
	 * problems described in {IERC20-approve}.
	 *
	 * Emits an {Approval} event indicating the updated allowance.
	 *
	 * Requirements:
	 *
	 * - `spender` cannot be the zero address.
	 * - `spender` must have allowance for the caller of at least
	 * `subtractedValue`.
	 */
	function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
		_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
		return true;
	}

	/**
	 * @dev Moves tokens `amount` from `sender` to `recipient`.
	 *
	 * This is internal function is equivalent to {transfer}, and can be used to
	 * e.g. implement automatic token fees, slashing mechanisms, etc.
	 *
	 * Emits a {Transfer} event.
	 *
	 * Requirements:
	 *
	 * - `sender` cannot be the zero address.
	 * - `recipient` cannot be the zero address.
	 * - `sender` must have a balance of at least `amount`.
	 */
	function _transfer(
		address sender,
		address recipient,
		uint256 amount
	) internal virtual {
		require(sender != address(0), "ERC20: transfer from the zero address");
		require(recipient != address(0), "ERC20: transfer to the zero address");

		_beforeTokenTransfer(sender, recipient, amount);

		_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
		_balances[recipient] = _balances[recipient].add(amount);
		emit Transfer(sender, recipient, amount);
	}

	/** @dev Creates `amount` tokens and assigns them to `account`, increasing
	 * the total supply.
	 *
	 * Emits a {Transfer} event with `from` set to the zero address.
	 *
	 * Requirements:
	 *
	 * - `to` cannot be the zero address.
	 */
	function _mint(address account, uint256 amount) internal virtual {
		require(account != address(0), "ERC20: mint to the zero address");

		_beforeTokenTransfer(address(0), account, amount);

		_totalSupply = _totalSupply.add(amount);
		_balances[account] = _balances[account].add(amount);
		emit Transfer(address(0), account, amount);
	}

	/**
	 * @dev Destroys `amount` tokens from `account`, reducing the
	 * total supply.
	 *
	 * Emits a {Transfer} event with `to` set to the zero address.
	 *
	 * Requirements:
	 *
	 * - `account` cannot be the zero address.
	 * - `account` must have at least `amount` tokens.
	 */
	function _burn(address account, uint256 amount) internal virtual {
		require(account != address(0), "ERC20: burn from the zero address");

		_beforeTokenTransfer(account, address(0), amount);

		_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
		_totalSupply = _totalSupply.sub(amount);
		emit Transfer(account, address(0), amount);
	}

	/**
	 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
	 *
	 * This internal function is equivalent to `approve`, and can be used to
	 * e.g. set automatic allowances for certain subsystems, etc.
	 *
	 * Emits an {Approval} event.
	 *
	 * Requirements:
	 *
	 * - `owner` cannot be the zero address.
	 * - `spender` cannot be the zero address.
	 */
	function _approve(
		address owner,
		address spender,
		uint256 amount
	) internal virtual {
		require(owner != address(0), "ERC20: approve from the zero address");
		require(spender != address(0), "ERC20: approve to the zero address");

		_allowances[owner][spender] = amount;
		emit Approval(owner, spender, amount);
	}

	/**
	 * @dev Sets {decimals} to a value other than the default one of 18.
	 *
	 * WARNING: This function should only be called from the constructor. Most
	 * applications that interact with token contracts will not expect
	 * {decimals} to ever change, and may work incorrectly if it does.
	 */
	function _setupDecimals(uint8 decimals_) internal virtual {
		_decimals = decimals_;
	}

	/**
	 * @dev Hook that is called before any transfer of tokens. This includes
	 * minting and burning.
	 *
	 * Calling conditions:
	 *
	 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
	 * will be to transferred to `to`.
	 * - when `from` is zero, `amount` tokens will be minted for `to`.
	 * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
	 * - `from` and `to` are never both zero.
	 *
	 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
	 */
	function _beforeTokenTransfer(
		address from,
		address to,
		uint256 amount
	) internal virtual {}
}

File 6 of 20 : ILosslessV2Pool.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;

interface ILosslessV2Pool {
	// defined and controls all game logic related variables
	struct GameStatus {
		bool isShortLastRoundWinner; // record whether last round winner
		bool isFirstUser; // check if the user is the first one to enter the game or not
		bool isFirstRound; // is this game the first round of the entire pool?
		uint256 gameRound; // count for showing current game round
		uint256 durationOfGame; // which should be 6 days in default
		uint256 durationOfBidding; // which should be 1 days in default
		uint256 lastUpdateTimestamp; // the timestamp when last game logic function been called
		int256 initialPrice; // game initial price
		int256 endPrice; // game end price
		PoolStatus currState; // current pool status
	}

	// token info for current pool
	struct PoolTokensInfo {
		address longToken;
		address shortToken;
		address sponsorToken;
	}

	// # ENUM FOR POOL STATUS
	/*  
      PoolStatus Explaination
      *****
        Locked ------ game period. interacting with compound
        Accepting --- users can adding or reducing the bet
        FirstGame --- only been used for the first round
		Terminated -- only when special cases admin decided to close the pool

      Notation
      ******
        /name/ - status name
        [name] - function call name

      Workflow
      *******  

                                    
                     /Accepting/            /Locked/         /Accepting/				/Terminated/
                          |                     |                | 							 |
    [startFirstRound] ---------> [startGame] -------> [endGame] ---> [poolTermination] --------------->
                                      ^                    | |
                                      |                    | record time
                                       --------------------
                                                 |
                                            /Accepting/
    */
	enum PoolStatus {
		FirstGame,
		Locked,
		Accepting,
		Terminated
	}

	// ## DEFINE USER OPERATION EVENTS
	event Deposit(uint256 shortPrincipalAmount, uint256 longPrincipalAmount);
	event Withdraw(bool isAToken, uint256 shortTokenAmount, uint256 longTokenAmount);
	event SponsorDeposit(uint256 principalAmount);
	event SponsorWithdraw(uint256 sponsorTokenAmount);
	// ## DEFINE GAME OPERATION EVENTS
	event UpdateTokenValue(uint256 valuePerShortToken, uint256 valuePerLongToken);
	event AnnounceWinner(bool isShortLastRoundWinner, int256 initialPrice, int256 endPrice);

	// ## PUBLIC VARIABLES
	function factory() external view returns (address);

	function bidToken() external view returns (address);

	function principalToken() external view returns (address);

	function aToken() external view returns (address);

	function addressProvider() external view returns (address);

	// ### GAME SETTING VARIABLES
	function inPoolTimestamp(address userAddress) external view returns (uint256);

	// ## STATE-CHANGING FUNCTION
	/* 
		initialize: 		initialize the game
		startFirstRound: 	start the frist round logic
		startGame: 			start game -> pool lock supply principal to AAVE, get start game price
		endGame: 			end game -> pool unlock redeem fund to AAVE, get end game price
		poolTermination:	terminate the pool, no more game, but user can still withdraw fund
    */
	function initialize(
		address shortToken_,
		address longToken_,
		address sponsorToken_
	) external;

	function startFirstRound() external; // only be called to start the first Round

	function startGame() external; // called after bidding duration

	function endGame() external; // called after game duraion

	///@dev admin only
	function poolTermination() external; // called after selectWinner only by admin

	// user actions in below, join game, add, reduce or withDraw all fund
	/* 
		deposit: 			adding funds can be either just long or short or both
		withdraw: 			reduce funds can be either just long or short or both
		swap: 				change amount of tokens from long -> short / short -> long
		sponsorDeposit:		deposit principal to the pool as interest sponsor
		sponsorWithdraw:	withdraw sponsor donation from the pool
    */
	function deposit(uint256 shortPrincipalAmount, uint256 longPrincipalAmount) external;

	function withdraw(
		bool isAToken,
		uint256 shortTokenAmount,
		uint256 longTokenAmount
	) external;

	function swap(bool fromLongToShort, uint256 swapTokenAmount) external;

	function sponsorDeposit(uint256 principalAmount) external;

	function sponsorWithdraw(uint256 sponsorTokenAmount) external;
	
	function claimAAVE(address stakedAAVEAddress_, uint256 amount_ ) external;

	// view functions to return user balance
	function userLongPrincipalBalance(address userAddress) external view returns (uint256);

	function userShortPrincipalBalance(address userAddress) external view returns (uint256);
}

File 7 of 20 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

File 8 of 20 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 9 of 20 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @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) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @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) {
        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, reverting 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) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting 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) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * 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);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * 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);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * 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;
    }
}

File 10 of 20 : ILosslessV2Token.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface ILosslessV2Token is IERC20 {
	function mint(address to, uint256 amount) external returns (bool);

	function burn(address from, uint256 amount) external returns (bool);
}

File 11 of 20 : IPriceOracleGetter.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;

interface IPriceOracleGetter {
	function getAssetPrice(address _asset) external view returns (uint256);

	function getAssetsPrices(address[] calldata _assets) external view returns (uint256[] memory);

	function getSourceOfAsset(address _asset) external view returns (address);

	function getFallbackOracle() external view returns (address);
}

File 12 of 20 : ILendingPoolAddressesProvider.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;

/**
 * @title LendingPoolAddressesProvider contract
 * @dev Main registry of addresses part of or connected to the protocol, including permissioned roles
 * - Acting also as factory of proxies and admin of those, so with right to change its implementations
 * - Owned by the Aave Governance
 * @author Aave
 **/
interface ILendingPoolAddressesProvider {
	event MarketIdSet(string newMarketId);
	event LendingPoolUpdated(address indexed newAddress);
	event ConfigurationAdminUpdated(address indexed newAddress);
	event EmergencyAdminUpdated(address indexed newAddress);
	event LendingPoolConfiguratorUpdated(address indexed newAddress);
	event LendingPoolCollateralManagerUpdated(address indexed newAddress);
	event PriceOracleUpdated(address indexed newAddress);
	event LendingRateOracleUpdated(address indexed newAddress);
	event ProxyCreated(bytes32 id, address indexed newAddress);
	event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy);

	function getMarketId() external view returns (string memory);

	function setMarketId(string calldata marketId) external;

	function setAddress(bytes32 id, address newAddress) external;

	function setAddressAsProxy(bytes32 id, address impl) external;

	function getAddress(bytes32 id) external view returns (address);

	function getLendingPool() external view returns (address);

	function setLendingPoolImpl(address pool) external;

	function getLendingPoolConfigurator() external view returns (address);

	function setLendingPoolConfiguratorImpl(address configurator) external;

	function getLendingPoolCollateralManager() external view returns (address);

	function setLendingPoolCollateralManager(address manager) external;

	function getPoolAdmin() external view returns (address);

	function setPoolAdmin(address admin) external;

	function getEmergencyAdmin() external view returns (address);

	function setEmergencyAdmin(address admin) external;

	function getPriceOracle() external view returns (address);

	function setPriceOracle(address priceOracle) external;

	function getLendingRateOracle() external view returns (address);

	function setLendingRateOracle(address lendingRateOracle) external;
}

File 13 of 20 : ILendingPool.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import { ILendingPoolAddressesProvider } from "./ILendingPoolAddressesProvider.sol";
import { DataTypes } from "../core/libraries/DataTypes.sol";

interface ILendingPool {
	/**
	 * @dev Emitted on deposit()
	 * @param reserve The address of the underlying asset of the reserve
	 * @param user The address initiating the deposit
	 * @param onBehalfOf The beneficiary of the deposit, receiving the aTokens
	 * @param amount The amount deposited
	 * @param referral The referral code used
	 **/
	event Deposit(address indexed reserve, address user, address indexed onBehalfOf, uint256 amount, uint16 indexed referral);

	/**
	 * @dev Emitted on withdraw()
	 * @param reserve The address of the underlyng asset being withdrawn
	 * @param user The address initiating the withdrawal, owner of aTokens
	 * @param to Address that will receive the underlying
	 * @param amount The amount to be withdrawn
	 **/
	event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);

	/**
	 * @dev Emitted on borrow() and flashLoan() when debt needs to be opened
	 * @param reserve The address of the underlying asset being borrowed
	 * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just
	 * initiator of the transaction on flashLoan()
	 * @param onBehalfOf The address that will be getting the debt
	 * @param amount The amount borrowed out
	 * @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable
	 * @param borrowRate The numeric rate at which the user has borrowed
	 * @param referral The referral code used
	 **/
	event Borrow(
		address indexed reserve,
		address user,
		address indexed onBehalfOf,
		uint256 amount,
		uint256 borrowRateMode,
		uint256 borrowRate,
		uint16 indexed referral
	);

	/**
	 * @dev Emitted on repay()
	 * @param reserve The address of the underlying asset of the reserve
	 * @param user The beneficiary of the repayment, getting his debt reduced
	 * @param repayer The address of the user initiating the repay(), providing the funds
	 * @param amount The amount repaid
	 **/
	event Repay(address indexed reserve, address indexed user, address indexed repayer, uint256 amount);

	/**
	 * @dev Emitted on swapBorrowRateMode()
	 * @param reserve The address of the underlying asset of the reserve
	 * @param user The address of the user swapping his rate mode
	 * @param rateMode The rate mode that the user wants to swap to
	 **/
	event Swap(address indexed reserve, address indexed user, uint256 rateMode);

	/**
	 * @dev Emitted on setUserUseReserveAsCollateral()
	 * @param reserve The address of the underlying asset of the reserve
	 * @param user The address of the user enabling the usage as collateral
	 **/
	event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);

	/**
	 * @dev Emitted on setUserUseReserveAsCollateral()
	 * @param reserve The address of the underlying asset of the reserve
	 * @param user The address of the user enabling the usage as collateral
	 **/
	event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);

	/**
	 * @dev Emitted on rebalanceStableBorrowRate()
	 * @param reserve The address of the underlying asset of the reserve
	 * @param user The address of the user for which the rebalance has been executed
	 **/
	event RebalanceStableBorrowRate(address indexed reserve, address indexed user);

	/**
	 * @dev Emitted on flashLoan()
	 * @param target The address of the flash loan receiver contract
	 * @param initiator The address initiating the flash loan
	 * @param asset The address of the asset being flash borrowed
	 * @param amount The amount flash borrowed
	 * @param premium The fee flash borrowed
	 * @param referralCode The referral code used
	 **/
	event FlashLoan(address indexed target, address indexed initiator, address indexed asset, uint256 amount, uint256 premium, uint16 referralCode);

	/**
	 * @dev Emitted when the pause is triggered.
	 */
	event Paused();

	/**
	 * @dev Emitted when the pause is lifted.
	 */
	event Unpaused();

	/**
	 * @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via
	 * LendingPoolCollateral manager using a DELEGATECALL
	 * This allows to have the events in the generated ABI for LendingPool.
	 * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
	 * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
	 * @param user The address of the borrower getting liquidated
	 * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
	 * @param liquidatedCollateralAmount The amount of collateral received by the liiquidator
	 * @param liquidator The address of the liquidator
	 * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
	 * to receive the underlying collateral asset directly
	 **/
	event LiquidationCall(
		address indexed collateralAsset,
		address indexed debtAsset,
		address indexed user,
		uint256 debtToCover,
		uint256 liquidatedCollateralAmount,
		address liquidator,
		bool receiveAToken
	);

	/**
	 * @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared
	 * in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal,
	 * the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it
	 * gets added to the LendingPool ABI
	 * @param reserve The address of the underlying asset of the reserve
	 * @param liquidityRate The new liquidity rate
	 * @param stableBorrowRate The new stable borrow rate
	 * @param variableBorrowRate The new variable borrow rate
	 * @param liquidityIndex The new liquidity index
	 * @param variableBorrowIndex The new variable borrow index
	 **/
	event ReserveDataUpdated(
		address indexed reserve,
		uint256 liquidityRate,
		uint256 stableBorrowRate,
		uint256 variableBorrowRate,
		uint256 liquidityIndex,
		uint256 variableBorrowIndex
	);

	/**
	 * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
	 * - E.g. User deposits 100 USDC and gets in return 100 aUSDC
	 * @param asset The address of the underlying asset to deposit
	 * @param amount The amount to be deposited
	 * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
	 *   wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
	 *   is a different wallet
	 * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
	 *   0 if the action is executed directly by the user, without any middle-man
	 **/
	function deposit(
		address asset,
		uint256 amount,
		address onBehalfOf,
		uint16 referralCode
	) external;

	/**
	 * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
	 * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
	 * @param asset The address of the underlying asset to withdraw
	 * @param amount The underlying amount to be withdrawn
	 *   - Send the value type(uint256).max in order to withdraw the whole aToken balance
	 * @param to Address that will receive the underlying, same as msg.sender if the user
	 *   wants to receive it on his own wallet, or a different address if the beneficiary is a
	 *   different wallet
	 * @return The final amount withdrawn
	 **/
	function withdraw(
		address asset,
		uint256 amount,
		address to
	) external returns (uint256);

	/**
	 * @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
	 * already deposited enough collateral, or he was given enough allowance by a credit delegator on the
	 * corresponding debt token (StableDebtToken or VariableDebtToken)
	 * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
	 *   and 100 stable/variable debt tokens, depending on the `interestRateMode`
	 * @param asset The address of the underlying asset to borrow
	 * @param amount The amount to be borrowed
	 * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
	 * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
	 *   0 if the action is executed directly by the user, without any middle-man
	 * @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself
	 * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
	 * if he has been given credit delegation allowance
	 **/
	function borrow(
		address asset,
		uint256 amount,
		uint256 interestRateMode,
		uint16 referralCode,
		address onBehalfOf
	) external;

	/**
	 * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
	 * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address
	 * @param asset The address of the borrowed underlying asset previously borrowed
	 * @param amount The amount to repay
	 * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
	 * @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
	 * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the
	 * user calling the function if he wants to reduce/remove his own debt, or the address of any other
	 * other borrower whose debt should be removed
	 * @return The final amount repaid
	 **/
	function repay(
		address asset,
		uint256 amount,
		uint256 rateMode,
		address onBehalfOf
	) external returns (uint256);

	/**
	 * @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa
	 * @param asset The address of the underlying asset borrowed
	 * @param rateMode The rate mode that the user wants to swap to
	 **/
	function swapBorrowRateMode(address asset, uint256 rateMode) external;

	/**
	 * @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.
	 * - Users can be rebalanced if the following conditions are satisfied:
	 *     1. Usage ratio is above 95%
	 *     2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been
	 *        borrowed at a stable rate and depositors are not earning enough
	 * @param asset The address of the underlying asset borrowed
	 * @param user The address of the user to be rebalanced
	 **/
	function rebalanceStableBorrowRate(address asset, address user) external;

	/**
	 * @dev Allows depositors to enable/disable a specific deposited asset as collateral
	 * @param asset The address of the underlying asset deposited
	 * @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise
	 **/
	function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;

	/**
	 * @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
	 * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
	 *   a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
	 * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
	 * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
	 * @param user The address of the borrower getting liquidated
	 * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
	 * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
	 * to receive the underlying collateral asset directly
	 **/
	function liquidationCall(
		address collateralAsset,
		address debtAsset,
		address user,
		uint256 debtToCover,
		bool receiveAToken
	) external;

	/**
	 * @dev Allows smartcontracts to access the liquidity of the pool within one transaction,
	 * as long as the amount taken plus a fee is returned.
	 * IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration.
	 * For further details please visit https://developers.aave.com
	 * @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface
	 * @param assets The addresses of the assets being flash-borrowed
	 * @param amounts The amounts amounts being flash-borrowed
	 * @param modes Types of the debt to open if the flash loan is not returned:
	 *   0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
	 *   1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
	 *   2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
	 * @param onBehalfOf The address  that will receive the debt in the case of using on `modes` 1 or 2
	 * @param params Variadic packed params to pass to the receiver as extra information
	 * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
	 *   0 if the action is executed directly by the user, without any middle-man
	 **/
	function flashLoan(
		address receiverAddress,
		address[] calldata assets,
		uint256[] calldata amounts,
		uint256[] calldata modes,
		address onBehalfOf,
		bytes calldata params,
		uint16 referralCode
	) external;

	/**
	 * @dev Returns the user account data across all the reserves
	 * @param user The address of the user
	 * @return totalCollateralETH the total collateral in ETH of the user
	 * @return totalDebtETH the total debt in ETH of the user
	 * @return availableBorrowsETH the borrowing power left of the user
	 * @return currentLiquidationThreshold the liquidation threshold of the user
	 * @return ltv the loan to value of the user
	 * @return healthFactor the current health factor of the user
	 **/
	function getUserAccountData(address user)
		external
		view
		returns (
			uint256 totalCollateralETH,
			uint256 totalDebtETH,
			uint256 availableBorrowsETH,
			uint256 currentLiquidationThreshold,
			uint256 ltv,
			uint256 healthFactor
		);

	function initReserve(
		address reserve,
		address aTokenAddress,
		address stableDebtAddress,
		address variableDebtAddress,
		address interestRateStrategyAddress
	) external;

	function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress) external;

	function setConfiguration(address reserve, uint256 configuration) external;

	/**
	 * @dev Returns the configuration of the reserve
	 * @param asset The address of the underlying asset of the reserve
	 * @return The configuration of the reserve
	 **/
	function getConfiguration(address asset) external view returns (DataTypes.ReserveConfigurationMap memory);

	/**
	 * @dev Returns the configuration of the user across all the reserves
	 * @param user The user address
	 * @return The configuration of the user
	 **/
	function getUserConfiguration(address user) external view returns (DataTypes.UserConfigurationMap memory);

	/**
	 * @dev Returns the normalized income normalized income of the reserve
	 * @param asset The address of the underlying asset of the reserve
	 * @return The reserve's normalized income
	 */
	function getReserveNormalizedIncome(address asset) external view returns (uint256);

	/**
	 * @dev Returns the normalized variable debt per unit of asset
	 * @param asset The address of the underlying asset of the reserve
	 * @return The reserve normalized variable debt
	 */
	function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);

	/**
	 * @dev Returns the state and configuration of the reserve
	 * @param asset The address of the underlying asset of the reserve
	 * @return The state of the reserve
	 **/
	function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);

	function finalizeTransfer(
		address asset,
		address from,
		address to,
		uint256 amount,
		uint256 balanceFromAfter,
		uint256 balanceToBefore
	) external;

	function getReservesList() external view returns (address[] memory);

	function getAddressesProvider() external view returns (ILendingPoolAddressesProvider);

	function setPause(bool val) external;

	function paused() external view returns (bool);
}

File 14 of 20 : IProtocolDataProvider.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import { ILendingPoolAddressesProvider } from "./ILendingPoolAddressesProvider.sol";

interface IProtocolDataProvider {
	struct TokenData {
		string symbol;
		address tokenAddress;
	}

	function ADDRESSES_PROVIDER() external view returns (ILendingPoolAddressesProvider);

	function getAllReservesTokens() external view returns (TokenData[] memory);

	function getAllATokens() external view returns (TokenData[] memory);

	function getReserveConfigurationData(address asset)
		external
		view
		returns (
			uint256 decimals,
			uint256 ltv,
			uint256 liquidationThreshold,
			uint256 liquidationBonus,
			uint256 reserveFactor,
			bool usageAsCollateralEnabled,
			bool borrowingEnabled,
			bool stableBorrowRateEnabled,
			bool isActive,
			bool isFrozen
		);

	function getReserveData(address asset)
		external
		view
		returns (
			uint256 availableLiquidity,
			uint256 totalStableDebt,
			uint256 totalVariableDebt,
			uint256 liquidityRate,
			uint256 variableBorrowRate,
			uint256 stableBorrowRate,
			uint256 averageStableBorrowRate,
			uint256 liquidityIndex,
			uint256 variableBorrowIndex,
			uint40 lastUpdateTimestamp
		);

	function getUserReserveData(address asset, address user)
		external
		view
		returns (
			uint256 currentATokenBalance,
			uint256 currentStableDebt,
			uint256 currentVariableDebt,
			uint256 principalStableDebt,
			uint256 scaledVariableDebt,
			uint256 stableBorrowRate,
			uint256 liquidityRate,
			uint40 stableRateLastUpdated,
			bool usageAsCollateralEnabled
		);

	function getReserveTokensAddresses(address asset)
		external
		view
		returns (
			address aTokenAddress,
			address stableDebtTokenAddress,
			address variableDebtTokenAddress
		);
}

File 15 of 20 : IStakedToken.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;

interface IStakedToken {
  
  function stake(address to, uint256 amount) external;

  function redeem(address to, uint256 amount) external;

  function cooldown() external;

  function claimRewards(address to, uint256 amount) external;
}

File 16 of 20 : SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 17 of 20 : AggregatorV3Interface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

interface AggregatorV3Interface {

  function decimals()
    external
    view
    returns (
      uint8
    );

  function description()
    external
    view
    returns (
      string memory
    );

  function version()
    external
    view
    returns (
      uint256
    );

  // getRoundData and latestRoundData should both raise "No data present"
  // if they do not have data to report, instead of returning unset values
  // which could be misinterpreted as actual reported values.
  function getRoundData(
    uint80 _roundId
  )
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

}

File 18 of 20 : KeeperCompatibleInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

interface KeeperCompatibleInterface {

  /**
   * @notice checks if the contract requires work to be done.
   * @param checkData data passed to the contract when checking for upkeep.
   * @return upkeepNeeded boolean to indicate whether the keeper should call
   * performUpkeep or not.
   * @return performData bytes that the keeper should call performUpkeep with,
   * if upkeep is needed.
   */
  function checkUpkeep(
    bytes calldata checkData
  )
    external
    returns (
      bool upkeepNeeded,
      bytes memory performData
    );

  /**
   * @notice Performs work on the contract. Executed by the keepers, via the registry.
   * @param performData is the data which was passed back from the checkData
   * simulation.
   */
  function performUpkeep(
    bytes calldata performData
  ) external;
}

File 19 of 20 : DataTypes.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;

library DataTypes {
	// refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.
	struct ReserveData {
		//stores the reserve configuration
		ReserveConfigurationMap configuration;
		//the liquidity index. Expressed in ray
		uint128 liquidityIndex;
		//variable borrow index. Expressed in ray
		uint128 variableBorrowIndex;
		//the current supply rate. Expressed in ray
		uint128 currentLiquidityRate;
		//the current variable borrow rate. Expressed in ray
		uint128 currentVariableBorrowRate;
		//the current stable borrow rate. Expressed in ray
		uint128 currentStableBorrowRate;
		uint40 lastUpdateTimestamp;
		//tokens addresses
		address aTokenAddress;
		address stableDebtTokenAddress;
		address variableDebtTokenAddress;
		//address of the interest rate strategy
		address interestRateStrategyAddress;
		//the id of the reserve. Represents the position in the list of the active reserves
		uint8 id;
	}

	struct ReserveConfigurationMap {
		//bit 0-15: LTV
		//bit 16-31: Liq. threshold
		//bit 32-47: Liq. bonus
		//bit 48-55: Decimals
		//bit 56: Reserve is active
		//bit 57: reserve is frozen
		//bit 58: borrowing is enabled
		//bit 59: stable rate borrowing enabled
		//bit 60-63: reserved
		//bit 64-79: reserve factor
		uint256 data;
	}

	struct UserConfigurationMap {
		uint256 data;
	}

	enum InterestRateMode {
		NONE,
		STABLE,
		VARIABLE
	}
}

File 20 of 20 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_DAO","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"DAO","type":"address"}],"name":"DAOChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"feePercent","type":"uint256"}],"name":"FeePercentChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeTo","type":"address"}],"name":"FeeToChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bidToken","type":"address"},{"indexed":true,"internalType":"address","name":"principalToken","type":"address"},{"indexed":false,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"allPoolLength","type":"uint256"}],"name":"PoolCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pool","type":"address"}],"name":"PoolTerminated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pendingDAO","type":"address"}],"name":"proposeDAOChange","type":"event"},{"inputs":[],"name":"DAO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allPools","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allPoolsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bidToken","type":"address"},{"internalType":"address","name":"principalToken","type":"address"},{"internalType":"address","name":"addressProvider","type":"address"},{"internalType":"address","name":"aggregator","type":"address"},{"internalType":"uint256","name":"biddingDuration","type":"uint256"},{"internalType":"uint256","name":"gamingDuration","type":"uint256"},{"internalType":"string","name":"tokenName","type":"string"},{"internalType":"string","name":"tokenSymbol","type":"string"}],"name":"createPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"getPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getPoolLongToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getPoolShortToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getPoolSponsorToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isPoolActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingDAO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"setDAO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_feePercent","type":"uint256"}],"name":"setFeePercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeTo","type":"address"}],"name":"setFeeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pendingDAO","type":"address"}],"name":"setPendingDAO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"terminatePool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b5060405161606e38038061606e8339818101604052602081101561003357600080fd5b50516001600160a01b03811661007a5760405162461bcd60e51b815260040180806020018281038252602b815260200180616043602b913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055615f9a806100a96000396000f3fe60806040523480156200001157600080fd5b5060043610620001245760003560e01c80637fd6f15c11620000b1578063d7778f92116200007b578063d7778f9214620003f6578063e692e09f146200041f578063efde4e641462000448578063f46901ed1462000452578063fd686494146200047b5762000124565b80637fd6f15c146200036a5780637ffc3eab146200038657806398fabd3a14620003af578063a711e6a114620003b95762000124565b806341d1de9711620000f357806341d1de9714620002ef578063531aa03e146200030f578063723a7c0414620003405780637ce3489b146200034a5762000124565b8063017e7e5814620001295780630702f86c146200014f57806310bd1f4614620002bc57806318198c1714620002c6575b600080fd5b62000133620004a4565b604080516001600160a01b039092168252519081900360200190f35b620002ba60048036036101008110156200016857600080fd5b6001600160a01b038235811692602081013582169260408201358316926060830135169160808101359160a0820135919081019060e0810160c0820135640100000000811115620001b857600080fd5b820183602082011115620001cb57600080fd5b80359060200191846001830284011164010000000083111715620001ee57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156200024257600080fd5b8201836020820111156200025557600080fd5b803590602001918460018302840111640100000000831117156200027857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550620004b3945050505050565b005b6200013362000bf9565b6200013360048036036020811015620002de57600080fd5b50356001600160a01b031662000c08565b62000133600480360360208110156200030757600080fd5b503562000c23565b62000133600480360360408110156200032757600080fd5b506001600160a01b038135811691602001351662000c4b565b620002ba62000c71565b620002ba600480360360208110156200036257600080fd5b503562000d6a565b6200037462000e36565b60408051918252519081900360200190f35b62000133600480360360208110156200039e57600080fd5b50356001600160a01b031662000e3c565b6200013362000e57565b620003e260048036036020811015620003d157600080fd5b50356001600160a01b031662000e66565b604080519115158252519081900360200190f35b620003e2600480360360208110156200040e57600080fd5b50356001600160a01b031662000e7b565b62000133600480360360208110156200043757600080fd5b50356001600160a01b031662000fdc565b6200037462000ff7565b620002ba600480360360208110156200046a57600080fd5b50356001600160a01b031662000ffd565b620002ba600480360360208110156200049357600080fd5b50356001600160a01b0316620010ed565b6000546001600160a01b031681565b6001546001600160a01b0316331462000502576040805162461bcd60e51b815260206004820152601c602482015260008051602062005d10833981519152604482015290519081900360640190fd5b866001600160a01b0316886001600160a01b03161415620005555760405162461bcd60e51b815260040180806020018281038252602681526020018062005d8e6026913960400191505060405180910390fd5b6001600160a01b038816158015906200057657506001600160a01b03871615155b620005c8576040805162461bcd60e51b815260206004820152601f60248201527f4c6f73736c6573735632466163746f72793a205a45524f5f4144445245535300604482015290519081900360640190fd5b6001600160a01b0386166200060f5760405162461bcd60e51b815260040180806020018281038252603081526020018062005f046030913960400191505060405180910390fd5b6001600160a01b038516620006565760405162461bcd60e51b815260040180806020018281038252602a81526020018062005e78602a913960400191505060405180910390fd5b6001600160a01b0388811660009081526005602090815260408083208b851684529091529020541615620006d1576040805162461bcd60e51b815260206004820152601e60248201527f4c6f73736c6573735632466163746f72793a20504f4f4c5f4558495354530000604482015290519081900360640190fd5b60008411620007125760405162461bcd60e51b815260040180806020018281038252603281526020018062005ea26032913960400191505060405180910390fd5b60008311620007535760405162461bcd60e51b815260040180806020018281038252603181526020018062005f346031913960400191505060405180910390fd5b8151620007925760405162461bcd60e51b815260040180806020018281038252602e81526020018062005d60602e913960400191505060405180910390fd5b8051620007d15760405162461bcd60e51b815260040180806020018281038252603081526020018062005ed46030913960400191505060405180910390fd5b600454604080516020808201939093526bffffffffffffffffffffffff1960608c811b8216838501528b811b821660548401528a811b8216606884015289901b16607c8201528151607081830301815260909091019182905280519201919091209060009082908b908b908b908b908b908b906200084f90620016ba565b6001600160a01b0396871681529486166020860152928516604080860191909152919094166060840152608083019390935260a08201529051829181900360c001906000f5905080158015620008a9573d6000803e3d6000fd5b50905060008060006200092687878e6001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015620008f157600080fd5b505afa15801562000906573d6000803e3d6000fd5b505050506040513d60208110156200091d57600080fd5b505187620011dd565b925092509250836001600160a01b031663c0c53b8b8484846040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b03168152602001826001600160a01b031681526020019350505050600060405180830381600087803b1580156200099e57600080fd5b505af1158015620009b3573d6000803e3d6000fd5b5050505083600560008f6001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055506004849080600181540180825580915050600190039060005260206000200160009091909190916101000a8154816001600160a01b0302191690836001600160a01b03160217905550600160066000866001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055508260076000866001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055508160086000866001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055508060096000866001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055508b6001600160a01b03168d6001600160a01b03167febbbe9dc3a19d2f959ac76ac0372b4983cdfb945f5d6aef4873c36fabb2ba8aa8660048054905060405180836001600160a01b031681526020018281526020019250505060405180910390a350505050505050505050505050565b6002546001600160a01b031681565b6009602052600090815260409020546001600160a01b031681565b6004818154811062000c3157fe5b6000918252602090912001546001600160a01b0316905081565b60056020908152600092835260408084209091529082529020546001600160a01b031681565b6001546001600160a01b0316331462000cc0576040805162461bcd60e51b815260206004820152601c602482015260008051602062005d10833981519152604482015290519081900360640190fd5b6002546001600160a01b031662000d095760405162461bcd60e51b815260040180806020018281038252602f81526020018062005e49602f913960400191505060405180910390fd5b60028054600180546001600160a01b038084166001600160a01b03199283161792839055921690925560408051929091168252517f7a62ea533b501818ff8d9bde48cb1382a6df937b9339fe41e7d9a18db20e3e86916020908290030190a1565b6001546001600160a01b0316331462000db9576040805162461bcd60e51b815260206004820152601c602482015260008051602062005d10833981519152604482015290519081900360640190fd5b612710811062000dfb5760405162461bcd60e51b815260040180806020018281038252603981526020018062005db46039913960400191505060405180910390fd5b60038190556040805182815290517f91955c12515f4eb8f1ff79df82d1933ff11b6d3b9a3019c6568840616ec36a749181900360200190a150565b60035481565b6008602052600090815260409020546001600160a01b031681565b6001546001600160a01b031681565b60066020526000908152604090205460ff1681565b6001546000906001600160a01b0316331462000ecd576040805162461bcd60e51b815260206004820152601c602482015260008051602062005d10833981519152604482015290519081900360640190fd5b6001600160a01b03821660009081526006602052604090205460ff16151560011462000f2b5760405162461bcd60e51b815260040180806020018281038252602681526020018062005e236026913960400191505060405180910390fd5b816001600160a01b0316638fe688556040518163ffffffff1660e01b8152600401600060405180830381600087803b15801562000f6757600080fd5b505af115801562000f7c573d6000803e3d6000fd5b5050506001600160a01b038316600081815260066020908152604091829020805460ff19169055815192835290517ffdf10f6f014781f99c9ab5ae596e88402efac50b7fa92bf0b75d36e46fe35bf59350918290030190a1506001919050565b6007602052600090815260409020546001600160a01b031681565b60045490565b6001546001600160a01b031633146200104c576040805162461bcd60e51b815260206004820152601c602482015260008051602062005d10833981519152604482015290519081900360640190fd5b6001600160a01b038116620010935760405162461bcd60e51b815260040180806020018281038252603081526020018062005d306030913960400191505060405180910390fd5b600080546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517f3dedba2a214b4fff9bf20fc473c114824654e0bc70512b4a92f6d5978763c28d916020908290030190a150565b6001546001600160a01b031633146200113c576040805162461bcd60e51b815260206004820152601c602482015260008051602062005d10833981519152604482015290519081900360640190fd5b6001600160a01b038116620011835760405162461bcd60e51b815260040180806020018281038252603681526020018062005ded6036913960400191505060405180910390fd5b600280546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517f72aef41d8c66e458acdacaa2c7361620f63d89f84f6a9ca6eb1ba92bae0fd7a0916020908290030190a150565b600080806001600160a01b038416620012285760405162461bcd60e51b815260040180806020018281038252603081526020018062005f046030913960400191505060405180910390fd5b62001320876040516020018080611cdd60f21b81525060020182805190602001908083835b602083106200126e5780518252601f1990920191602091820191016200124d565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052876040516020018080611cdd60f21b81525060020182805190602001908083835b60208310620012e45780518252601f199092019160209182019101620012c3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528787620014a6565b9250620013dd876040516020018080616c6760f01b81525060020182805190602001908083835b60208310620013685780518252601f19909201916020918201910162001347565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052876040516020018080616c6760f01b815250600201828051906020019080838360208310620012e45780518252601f199092019160209182019101620012c3565b91506200149a87604051602001808061073760f41b81525060020182805190602001908083835b60208310620014255780518252601f19909201916020918201910162001404565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405287604051602001808061073760f41b815250600201828051906020019080838360208310620012e45780518252601f199092019160209182019101620012c3565b90509450945094915050565b600080858585856040516020018085805190602001908083835b60208310620014e15780518252601f199092019160209182019101620014c0565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b602083106200152b5780518252601f1990920191602091820191016200150a565b6001836020036101000a0380198251168184511680821785525050505050509050018360ff1660f81b8152600101826001600160a01b031660601b8152601401945050505050604051602081830303815290604052805190602001209050600081878787876040516200159e90620016c8565b60ff831660408201526001600160a01b038216606082015260808082528551908201528451819060208083019160a084019189019080838360005b83811015620015f3578181015183820152602001620015d9565b50505050905090810190601f168015620016215780820380516001836020036101000a031916815260200191505b50838103825286518152865160209182019188019080838360005b83811015620016565781810151838201526020016200163c565b50505050905090810190601f168015620016845780820380516001836020036101000a031916815260200191505b5096505050505050508190604051809103906000f5905080158015620016ae573d6000803e3d6000fd5b50979650505050505050565b6134c380620016d783390190565b6111768062004b9a8339019056fe608060405261271060068190556007556017805460ff60a01b1916600160a01b1790553480156200002f57600080fd5b50604051620034c3380380620034c3833981810160405260c08110156200005557600080fd5b508051602082015160408301516060840151608085015160a09095015160008054336001600160a01b0319918216179091556001805482166001600160a01b0380891691909117909155600280548316828816179081905560048054909316828716179092559596949593949293620000cf91166200013d565b600380546001600160a01b039283166001600160a01b03199182161790915560058054959092169416939093179092556001600a55600c55600b55505042600d55506009805461ff001962ff0000199091166201000017166101001790556010805460ff191690556200024f565b60048054604080516321f8a72160e01b8152600160f81b9381018490529051600093600193909285926001600160a01b03909216916321f8a72191602480820192602092909190829003018186803b1580156200019957600080fd5b505afa158015620001ae573d6000803e3d6000fd5b505050506040513d6020811015620001c557600080fd5b5051604080516334924edb60e21b81526001600160a01b038881166004830152915192935083929183169163d2493b6c91602480820192606092909190829003018186803b1580156200021757600080fd5b505afa1580156200022c573d6000803e3d6000fd5b505050506040513d60608110156200024357600080fd5b50519695505050505050565b613264806200025f6000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c8063a0c1f15e116100f9578063c45a015511610097578063dfafd4fd11610071578063dfafd4fd1461053f578063e2bbb15814610547578063fb5dfe781461056a578063fdd89a3414610590576101a9565b8063c45a015514610527578063d65ab5f21461052f578063dbc162de14610537576101a9565b8063bb1c9f7f116100d3578063bb1c9f7f1461049e578063bb6e179614610496578063c037646a146104ca578063c0c53b8b146104ef576101a9565b8063a0c1f15e14610486578063aa18ca921461048e578063aaf5eb6814610496576101a9565b80634585e33b116101665780636cbc2ded116101405780636cbc2ded1461035f5780636e04ff0d14610367578063889c0bbd146104585780638fe688551461047e576101a9565b80634585e33b146102ac5780634d5bb1bb1461031c5780635785c18c14610342576101a9565b8063200d2ed2146101ae57806324294b1f1461021c5780632954018c14610226578063344846dd1461024a57806334e08db5146102675780633b3bbc9c14610292575b600080fd5b6101b66105c3565b604051808b151581526020018a15158152602001891515815260200188815260200187815260200186815260200185815260200184815260200183815260200182600381111561020257fe5b81526020019a505050505050505050505060405180910390f35b610224610603565b005b61022e6106df565b604080516001600160a01b039092168252519081900360200190f35b6102246004803603602081101561026057600080fd5b50356106ee565b6102246004803603606081101561027d57600080fd5b5080351515906020810135906040013561089c565b61029a610bfe565b60408051918252519081900360200190f35b610224600480360360208110156102c257600080fd5b8101906020810181356401000000008111156102dd57600080fd5b8201836020820111156102ef57600080fd5b8035906020019184600183028401116401000000008311171561031157600080fd5b509092509050610c04565b61029a6004803603602081101561033257600080fd5b50356001600160a01b0316610c7e565b6102246004803603602081101561035857600080fd5b5035610c90565b610224610f5a565b6103d76004803603602081101561037d57600080fd5b81019060208101813564010000000081111561039857600080fd5b8201836020820111156103aa57600080fd5b803590602001918460018302840111640100000000831117156103cc57600080fd5b5090925090506113ba565b60405180831515815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561041c578181015183820152602001610404565b50505050905090810190601f1680156104495780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b61029a6004803603602081101561046e57600080fd5b50356001600160a01b0316611480565b6102246114e5565b61022e6115ab565b61029a6115ba565b61029a6115c0565b610224600480360360408110156104b457600080fd5b506001600160a01b0381351690602001356115c6565b610224600480360360408110156104e057600080fd5b5080351515906020013561173d565b6102246004803603606081101561050557600080fd5b506001600160a01b0381358116916020810135821691604090910135166119d6565b61022e611a96565b610224611aa5565b61022e611dc8565b61022e611dd7565b6102246004803603604081101561055d57600080fd5b5080359060200135611de6565b61029a6004803603602081101561058057600080fd5b50356001600160a01b03166120a2565b610598612101565b604080516001600160a01b039485168152928416602084015292168183015290519081900360600190f35b600954600a54600b54600c54600d54600e54600f5460105460ff80891698610100810482169862010000909104821697909690959094909390929091168a565b60095462010000900460ff161515600114610665576040805162461bcd60e51b815260206004820181905260248201527f4c6f73736c6573735632506f6f6c3a204e4f5420464952535420524f554e4421604482015290519081900360640190fd5b600060105460ff16600381111561067857fe5b146106b8576040805162461bcd60e51b815260206004820152601c60248201526000805160206131b5833981519152604482015290519081900360640190fd5b42600d556009805462ff000019169055601080546002919060ff19166001835b0217905550565b6004546001600160a01b031681565b601754600160a01b900460ff16151560011461073f576040805162461bcd60e51b81526020600482015260166024820152600080516020613195833981519152604482015290519081900360640190fd5b6017805460ff60a01b191690558061078c576040805162461bcd60e51b815260206004820152601e602482015260008051602061314b833981519152604482015290519081900360640190fd5b60175460408051632770a7eb60e21b81523360048201526024810184905290516001600160a01b0390921691639dc29fac916044808201926020929091908290030181600087803b1580156107e057600080fd5b505af11580156107f4573d6000803e3d6000fd5b505050506040513d602081101561080a57600080fd5b506001905060105460ff16600381111561082057fe5b141561083c5760025461083c906001600160a01b03168261211e565b600254610853906001600160a01b031633836122c8565b6040805182815290517f53f39bc00c1c01fadfe8bb9bd4d3398572c1cd9b0061bebcdd8c1abd4e4e21d19181900360200190a1506017805460ff60a01b1916600160a01b179055565b601754600160a01b900460ff1615156001146108ed576040805162461bcd60e51b81526020600482015260166024820152600080516020613195833981519152604482015290519081900360640190fd5b6017805460ff60a01b19169055811515806109085750600081115b610947576040805162461bcd60e51b815260206004820152601e602482015260008051602061314b833981519152604482015290519081900360640190fd5b601554604080516370a0823160e01b815233600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561099257600080fd5b505afa1580156109a6573d6000803e3d6000fd5b505050506040513d60208110156109bc57600080fd5b5051601654604080516370a0823160e01b815233600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610a0f57600080fd5b505afa158015610a23573d6000803e3d6000fd5b505050506040513d6020811015610a3957600080fd5b50519050838210801590610a4d5750828110155b610a885760405162461bcd60e51b815260040180806020018281038252602481526020018061320b6024913960400191505060405180910390fd5b6000610aab612710610aa56006548861231f90919063ffffffff16565b9061237f565b90506000610aca612710610aa56007548861231f90919063ffffffff16565b336000818152601460205260408120429055919250610aeb919088886123e6565b86610b4d57600160105460ff166003811115610b0357fe5b1415610b2857600254610b28906001600160a01b0316610b238484612508565b61211e565b600254610b48906001600160a01b031633610b438585612508565b6122c8565b610ba0565b600260105460ff166003811115610b6057fe5b1415610b8557600254610b85906001600160a01b0316610b808484612508565b612562565b600354610ba0906001600160a01b031633610b438585612508565b6040805188151581526020810188905280820187905290517ffedb0622d5d5fa46cc706a5c2c169f2bf2eb31a59ff2f70cef3096376f58c2c09181900360600190a150506017805460ff60a01b1916600160a01b1790555050505050565b60065481565b601054600d54600b54600c5460ff909316926002846003811115610c2457fe5b148015610c395750610c368382612508565b42115b15610c4657610c46611aa5565b6001846003811115610c5457fe5b148015610c695750610c668383612508565b42115b15610c7657610c76610f5a565b505050505050565b60146020526000908152604090205481565b601754600160a01b900460ff161515600114610ce1576040805162461bcd60e51b81526020600482015260166024820152600080516020613195833981519152604482015290519081900360640190fd5b6017805460ff60a01b19169055600360105460ff166003811115610d0157fe5b1415610d54576040805162461bcd60e51b815260206004820152601f60248201527f4c6f73736c6573735632506f6f6c3a20504f4f4c205445524d494e4154454400604482015290519081900360640190fd5b60008111610d97576040805162461bcd60e51b815260206004820152601e602482015260008051602061314b833981519152604482015290519081900360640190fd5b600254604080516370a0823160e01b8152336004820152905183926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610de157600080fd5b505afa158015610df5573d6000803e3d6000fd5b505050506040513d6020811015610e0b57600080fd5b50511015610e4a5760405162461bcd60e51b815260040180806020018281038252602481526020018061320b6024913960400191505060405180910390fd5b600254610e62906001600160a01b0316333084612648565b600160105460ff166003811115610e7557fe5b1415610e9157600254610e91906001600160a01b031682612562565b601754604080516340c10f1960e01b81523360048201526024810184905290516001600160a01b03909216916340c10f19916044808201926020929091908290030181600087803b158015610ee557600080fd5b505af1158015610ef9573d6000803e3d6000fd5b505050506040513d6020811015610f0f57600080fd5b50506040805182815290517f40b61effeb22345307b6b4acfbb4580925caf61a4b62d8672e9f3d1214d3479d9181900360200190a1506017805460ff60a01b1916600160a01b179055565b601754600160a01b900460ff161515600114610fab576040805162461bcd60e51b81526020600482015260166024820152600080516020613195833981519152604482015290519081900360640190fd5b6017805460ff60a01b19169055600b54600d54610fc791612508565b8042116110055760405162461bcd60e51b81526004018080602001828103825260278152602001806130d46027913960400191505060405180910390fd5b600160105460ff16600381111561101857fe5b14611058576040805162461bcd60e51b815260206004820152601c60248201526000805160206131b5833981519152604482015290519081900360640190fd5b600a54611066906001612508565b600a5542600d556009805461ff00191661010017905560108054600260ff199091168117909155546110a2906001600160a01b0316600061211e565b6110aa6126a2565b600f819055600e54136110c6576009805460ff191690556110d4565b6009805460ff191660011790555b6000611162612710610aa5600654601560009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561113057600080fd5b505afa158015611144573d6000803e3d6000fd5b505050506040513d602081101561115a57600080fd5b50519061231f565b905060006111c0612710610aa5600754601660009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561113057600080fd5b9050600061121e612710610aa5612710601760009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561113057600080fd5b9050600061123661122f8484612508565b8590612508565b600254604080516370a0823160e01b8152306004820152905192935083926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b15801561128657600080fd5b505afa15801561129a573d6000803e3d6000fd5b505050506040513d60208110156112b057600080fd5b505110156112c2576000600855611349565b600254604080516370a0823160e01b815230600482015290516113459284926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561131357600080fd5b505afa158015611327573d6000803e3d6000fd5b505050506040513d602081101561133d57600080fd5b505190612732565b6008555b611353848461278f565b600954600e54600f546040805160ff90941615158452602084019290925282820152517f363f3c6d2f590883f657a36adeb0d1b0440383e505ebfc904e41834f2c6eba889181900360600190a150506017805460ff60a01b1916600160a01b179055505050565b601054600d54600b54600c5460009360609360ff90911692909160028460038111156113e257fe5b1480156113f757506113f48382612508565b42115b15611405576001955061143b565b600184600381111561141357fe5b14801561142857506114258383612508565b42115b15611436576001955061143b565b600095505b87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250989b929a509198505050505050505050565b600754601654604080516370a0823160e01b81526001600160a01b03858116600483015291516000946114df9461271094610aa59492939116916370a08231916024808301926020929190829003018186803b15801561113057600080fd5b92915050565b6000546001600160a01b03163314611544576040805162461bcd60e51b815260206004820152601f60248201527f4c6f73736c6573735632466163746f72793a20464143544f5259204f4e4c5900604482015290519081900360640190fd5b600260105460ff16600381111561155757fe5b14611597576040805162461bcd60e51b815260206004820152601c60248201526000805160206131b5833981519152604482015290519081900360640190fd5b601080546003919060ff19166001836106d8565b6003546001600160a01b031681565b60075481565b61271081565b6001600160a01b03821661160b5760405162461bcd60e51b815260040180806020018281038252602f81526020018061311c602f913960400191505060405180910390fd5b60008060009054906101000a90046001600160a01b03166001600160a01b031663017e7e586040518163ffffffff1660e01b815260040160206040518083038186803b15801561165a57600080fd5b505afa15801561166e573d6000803e3d6000fd5b505050506040513d602081101561168457600080fd5b505190506001600160a01b0381166116cd5760405162461bcd60e51b815260040180806020018281038252602281526020018061308c6022913960400191505060405180910390fd5b604080516309a99b4f60e41b81526001600160a01b0383811660048301526024820185905291518592831691639a99b4f091604480830192600092919082900301818387803b15801561171f57600080fd5b505af1158015611733573d6000803e3d6000fd5b5050505050505050565b601754600160a01b900460ff16151560011461178e576040805162461bcd60e51b81526020600482015260166024820152600080516020613195833981519152604482015290519081900360640190fd5b6017805460ff60a01b19169055600260105460ff1660038111156117ae57fe5b146117ee576040805162461bcd60e51b815260206004820152601c60248201526000805160206131b5833981519152604482015290519081900360640190fd5b601554604080516370a0823160e01b815233600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561183957600080fd5b505afa15801561184d573d6000803e3d6000fd5b505050506040513d602081101561186357600080fd5b5051601654604080516370a0823160e01b815233600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b1580156118b657600080fd5b505afa1580156118ca573d6000803e3d6000fd5b505050506040513d60208110156118e057600080fd5b505190506000846118f157826118f3565b815b90506000841180156119055750808411155b6119405760405162461bcd60e51b815260040180806020018281038252602481526020018061320b6024913960400191505060405180910390fd5b60018515151415611986576119596000336000876123e6565b61198160003361197a600654610aa56007548a61231f90919063ffffffff16565b6000612a82565b6119bc565b6119946000338660006123e6565b6119bc60003360006119b7600754610aa56006548b61231f90919063ffffffff16565b612a82565b50506017805460ff60a01b1916600160a01b179055505050565b6000546001600160a01b03163314611a35576040805162461bcd60e51b815260206004820152601f60248201527f4c6f73736c6573735632466163746f72793a20464143544f5259204f4e4c5900604482015290519081900360640190fd5b601280546001600160a01b039485166001600160a01b03199182168117909255601180549486169482168517905560138054939095169281168317909455601580548516909117905560168054841690921790915560178054909216179055565b6000546001600160a01b031681565b601754600160a01b900460ff161515600114611af6576040805162461bcd60e51b81526020600482015260166024820152600080516020613195833981519152604482015290519081900360640190fd5b6017805460ff60a01b19169055600c54600d54611b1291612508565b804211611b505760405162461bcd60e51b81526004018080602001828103825260278152602001806130d46027913960400191505060405180910390fd5b600260105460ff166003811115611b6357fe5b14611ba3576040805162461bcd60e51b815260206004820152601c60248201526000805160206131b5833981519152604482015290519081900360640190fd5b601560009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611bf157600080fd5b505afa158015611c05573d6000803e3d6000fd5b505050506040513d6020811015611c1b57600080fd5b505115801590611ca35750601660009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c7457600080fd5b505afa158015611c88573d6000803e3d6000fd5b505050506040513d6020811015611c9e57600080fd5b505115155b611cf4576040805162461bcd60e51b815260206004820152601f60248201527f4c6f73736c6573735632506f6f6c3a204e4f2046554e4420494e20504f4f4c00604482015290519081900360640190fd5b42600d5560095460ff61010090910416151560011415611d2557611d166126a2565b600e556009805461ff00191690555b6010805460ff19166001179055600254604080516370a0823160e01b81523060048201529051611db2926001600160a01b03169182916370a0823191602480820192602092909190829003018186803b158015611d8157600080fd5b505afa158015611d95573d6000803e3d6000fd5b505050506040513d6020811015611dab57600080fd5b5051612562565b506017805460ff60a01b1916600160a01b179055565b6002546001600160a01b031681565b6001546001600160a01b031681565b601754600160a01b900460ff161515600114611e37576040805162461bcd60e51b81526020600482015260166024820152600080516020613195833981519152604482015290519081900360640190fd5b6017805460ff60a01b19169055600260105460ff166003811115611e5757fe5b14611e97576040805162461bcd60e51b815260206004820152601c60248201526000805160206131b5833981519152604482015290519081900360640190fd5b6000821180611ea65750600081115b611ee5576040805162461bcd60e51b815260206004820152601e602482015260008051602061314b833981519152604482015290519081900360640190fd5b60095460ff61010090910416151560011415611f1257611f036126a2565b600e556009805461ff00191690555b601554604080516370a0823160e01b815233600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611f5d57600080fd5b505afa158015611f71573d6000803e3d6000fd5b505050506040513d6020811015611f8757600080fd5b505115801561200a5750601654604080516370a0823160e01b815233600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611fdc57600080fd5b505afa158015611ff0573d6000803e3d6000fd5b505050506040513d602081101561200657600080fd5b5051155b15612022573360009081526014602052604090204290555b600254612043906001600160a01b0316333061203e8686612508565b612648565b6120506001338484612a82565b604080518381526020810183905281517fa3af609bf46297028ce551832669030f9effef2b02606d02cbbcc40fe6b47c55929181900390910190a150506017805460ff60a01b1916600160a01b179055565b600654601554604080516370a0823160e01b81526001600160a01b03858116600483015291516000946114df9461271094610aa59492939116916370a08231916024808301926020929190829003018186803b15801561113057600080fd5b6011546012546013546001600160a01b0392831692918216911683565b6000600460009054906101000a90046001600160a01b03166001600160a01b0316630261bf8b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561216e57600080fd5b505afa158015612182573d6000803e3d6000fd5b505050506040513d602081101561219857600080fd5b50519050806121a684612b9e565b600380546001600160a01b0319166001600160a01b03929092169190911790558261224557600354604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b15801561221657600080fd5b505afa15801561222a573d6000803e3d6000fd5b505050506040513d602081101561224057600080fd5b505192505b60408051631a4ca37b60e21b81526001600160a01b038681166004830152602482018690523060448301529151918316916369328dec916064808201926020929091908290030181600087803b15801561229e57600080fd5b505af11580156122b2573d6000803e3d6000fd5b505050506040513d6020811015610c7657600080fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261231a908490612caa565b505050565b60008261232e575060006114df565b8282028284828161233b57fe5b04146123785760405162461bcd60e51b81526004018080602001828103825260218152602001806130fb6021913960400191505060405180910390fd5b9392505050565b60008082116123d5576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b8183816123de57fe5b049392505050565b6001841515141561241d5760065461240490610aa58461271061231f565b60075490925061241a90610aa58361271061231f565b90505b81156124a65760155460408051632770a7eb60e21b81526001600160a01b0386811660048301526024820186905291519190921691639dc29fac9160448083019260209291908290030181600087803b15801561247957600080fd5b505af115801561248d573d6000803e3d6000fd5b505050506040513d60208110156124a357600080fd5b50505b80156125025760165460408051632770a7eb60e21b81526001600160a01b0386811660048301526024820185905291519190921691639dc29fac9160448083019260209291908290030181600087803b15801561229e57600080fd5b50505050565b600082820183811015612378576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000600460009054906101000a90046001600160a01b03166001600160a01b0316630261bf8b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156125b257600080fd5b505afa1580156125c6573d6000803e3d6000fd5b505050506040513d60208110156125dc57600080fd5b50519050806125ec848285612d5b565b6040805163e8eda9df60e01b81526001600160a01b0386811660048301526024820186905230604483015260006064830181905292519084169263e8eda9df926084808201939182900301818387803b15801561171f57600080fd5b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612502908590612caa565b600080600080600080600560009054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b1580156126f957600080fd5b505afa15801561270d573d6000803e3d6000fd5b505050506040513d60a081101561272357600080fd5b50602001519550505050505090565b600082821115612789576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60008060009054906101000a90046001600160a01b03166001600160a01b031663017e7e586040518163ffffffff1660e01b815260040160206040518083038186803b1580156127de57600080fd5b505afa1580156127f2573d6000803e3d6000fd5b505050506040513d602081101561280857600080fd5b50516000805460408051631ff5bc5760e21b8152905193945091926001600160a01b0390911691637fd6f15c916004808301926020929190829003018186803b15801561285457600080fd5b505afa158015612868573d6000803e3d6000fd5b505050506040513d602081101561287e57600080fd5b505160085490915060009061289b9061271090610aa5908561231f565b905081158015906128b457506001600160a01b03831615155b156128e0576008546128c69082612732565b6008556002546128e0906001600160a01b031684836122c8565b60095460ff16151560011415612991576008546128fe908690612508565b9450612989601560009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561295157600080fd5b505afa158015612965573d6000803e3d6000fd5b505050506040513d602081101561297b57600080fd5b5051610aa58761271061231f565b600655612a38565b60095460ff16612a38576008546129a9908590612508565b9350612a34601660009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156129fc57600080fd5b505afa158015612a10573d6000803e3d6000fd5b505050506040513d6020811015612a2657600080fd5b5051610aa58661271061231f565b6007555b7f3b18646b3983733450bdfbad0272e569b970aa8e53a92ab463689709f0bc4c0e600654600754604051808381526020018281526020019250505060405180910390a15050505050565b60018415151415612ab957600654612aa090610aa58461271061231f565b600754909250612ab690610aa58361271061231f565b90505b8115612b4257601554604080516340c10f1960e01b81526001600160a01b03868116600483015260248201869052915191909216916340c10f199160448083019260209291908290030181600087803b158015612b1557600080fd5b505af1158015612b29573d6000803e3d6000fd5b505050506040513d6020811015612b3f57600080fd5b50505b801561250257601654604080516340c10f1960e01b81526001600160a01b03868116600483015260248201859052915191909216916340c10f199160448083019260209291908290030181600087803b15801561229e57600080fd5b60048054604080516321f8a72160e01b8152600160f81b9381018490529051600093600193909285926001600160a01b03909216916321f8a72191602480820192602092909190829003018186803b158015612bf957600080fd5b505afa158015612c0d573d6000803e3d6000fd5b505050506040513d6020811015612c2357600080fd5b5051604080516334924edb60e21b81526001600160a01b038881166004830152915192935083929183169163d2493b6c91602480820192606092909190829003018186803b158015612c7457600080fd5b505afa158015612c88573d6000803e3d6000fd5b505050506040513d6060811015612c9e57600080fd5b50519695505050505050565b6060612cff826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612e6e9092919063ffffffff16565b80519091501561231a57808060200190516020811015612d1e57600080fd5b505161231a5760405162461bcd60e51b815260040180806020018281038252602a81526020018061316b602a913960400191505060405180910390fd5b801580612de1575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015612db357600080fd5b505afa158015612dc7573d6000803e3d6000fd5b505050506040513d6020811015612ddd57600080fd5b5051155b612e1c5760405162461bcd60e51b81526004018080602001828103825260368152602001806131d56036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261231a908490612caa565b6060612e7d8484600085612e85565b949350505050565b606082471015612ec65760405162461bcd60e51b81526004018080602001828103825260268152602001806130ae6026913960400191505060405180910390fd5b612ecf85612fe1565b612f20576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310612f5f5780518252601f199092019160209182019101612f40565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114612fc1576040519150601f19603f3d011682016040523d82523d6000602084013e612fc6565b606091505b5091509150612fd6828286612fe7565b979650505050505050565b3b151590565b60608315612ff6575081612378565b8251156130065782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613050578181015183820152602001613038565b50505050905090810190601f16801561307d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe4c6f73736c6573735632506f6f6c3a20666565546f205a45524f2041444452455353416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4c6f73736c6573735632506f6f6c3a20494e56414c49442054494d455354414d50204146544552536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774c6f73736c6573735632506f6f6c3a207374616b656441415645416464726573735f205a45524f20414444524553534c6f73736c6573735632506f6f6c3a20494e56414c494420414d4f554e5400005361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644c6f73736c6573735632506f6f6c3a204c4f434b4544000000000000000000004c6f73736c6573735632506f6f6c3a2057524f4e4720535441545553000000005361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e63654c6f73736c6573735632506f6f6c3a20494e53554646494349454e542042414c414e4345a2646970667358221220d5b92d4419ee56a0e9b1e93eae0179a294aa2864eef49bd14249526ee0425bee64736f6c634300060c003360806040523480156200001157600080fd5b506040516200117638038062001176833981810160405260808110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200010a57600080fd5b9083019060208201858111156200012057600080fd5b82516401000000008111828201881017156200013b57600080fd5b82525081516020918201929091019080838360005b838110156200016a57818101518382015260200162000150565b50505050905090810190601f168015620001985780820380516001836020036101000a031916815260200191505b506040908152602082810151929091015186519294509250859185918591620001c891600391908601906200026c565b508151620001de9060049060208501906200026c565b506005805460ff191660ff9290921691909117905550506001600160a01b0381166200023c5760405162461bcd60e51b815260040180806020018281038252602d81526020018062001149602d913960400191505060405180910390fd5b600580546001600160a01b0390921661010002610100600160a81b03199092169190911790555062000308915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002af57805160ff1916838001178555620002df565b82800160010185558215620002df579182015b82811115620002df578251825591602001919060010190620002c2565b50620002ed929150620002f1565b5090565b5b80821115620002ed5760008155600101620002f2565b610e3180620003186000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806370a082311161008c578063a457c2d711610066578063a457c2d7146102cc578063a9059cbb146102f8578063b86a1fb214610324578063dd62ed3e14610348576100ea565b806370a082311461027257806395d89b41146102985780639dc29fac146102a0576100ea565b806323b872dd116100c857806323b872dd146101c6578063313ce567146101fc578063395093511461021a57806340c10f1914610246576100ea565b806306fdde03146100ef578063095ea7b31461016c57806318160ddd146101ac575b600080fd5b6100f7610376565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610131578181015183820152602001610119565b50505050905090810190601f16801561015e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101986004803603604081101561018257600080fd5b506001600160a01b03813516906020013561040c565b604080519115158252519081900360200190f35b6101b4610429565b60408051918252519081900360200190f35b610198600480360360608110156101dc57600080fd5b506001600160a01b0381358116916020810135909116906040013561042f565b6102046104b6565b6040805160ff9092168252519081900360200190f35b6101986004803603604081101561023057600080fd5b506001600160a01b0381351690602001356104bf565b6101986004803603604081101561025c57600080fd5b506001600160a01b03813516906020013561050d565b6101b46004803603602081101561028857600080fd5b50356001600160a01b031661057e565b6100f7610599565b610198600480360360408110156102b657600080fd5b506001600160a01b0381351690602001356105fa565b610198600480360360408110156102e257600080fd5b506001600160a01b03813516906020013561066b565b6101986004803603604081101561030e57600080fd5b506001600160a01b0381351690602001356106d3565b61032c6106e7565b604080516001600160a01b039092168252519081900360200190f35b6101b46004803603604081101561035e57600080fd5b506001600160a01b03813581169160200135166106fb565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104025780601f106103d757610100808354040283529160200191610402565b820191906000526020600020905b8154815290600101906020018083116103e557829003601f168201915b5050505050905090565b6000610420610419610726565b848461072a565b50600192915050565b60025490565b600061043c848484610816565b6104ac84610448610726565b6104a785604051806060016040528060288152602001610d45602891396001600160a01b038a16600090815260016020526040812090610486610726565b6001600160a01b031681526020810191909152604001600020549190610971565b61072a565b5060019392505050565b60055460ff1690565b60006104206104cc610726565b846104a785600160006104dd610726565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610a08565b60055460009061010090046001600160a01b03163314610574576040805162461bcd60e51b815260206004820152601a60248201527f4c6f73736c6573735632546f6b656e3a20464f5242494444454e000000000000604482015290519081900360640190fd5b6104208383610a69565b6001600160a01b031660009081526020819052604090205490565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104025780601f106103d757610100808354040283529160200191610402565b60055460009061010090046001600160a01b03163314610661576040805162461bcd60e51b815260206004820152601a60248201527f4c6f73736c6573735632546f6b656e3a20464f5242494444454e000000000000604482015290519081900360640190fd5b6104208383610b59565b6000610420610678610726565b846104a785604051806060016040528060258152602001610dd760259139600160006106a2610726565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610971565b60006104206106e0610726565b8484610816565b60055461010090046001600160a01b031681565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3390565b6001600160a01b03831661076f5760405162461bcd60e51b8152600401808060200182810382526024815260200180610db36024913960400191505060405180910390fd5b6001600160a01b0382166107b45760405162461bcd60e51b8152600401808060200182810382526022815260200180610cfd6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b03831661085b5760405162461bcd60e51b8152600401808060200182810382526025815260200180610d8e6025913960400191505060405180910390fd5b6001600160a01b0382166108a05760405162461bcd60e51b8152600401808060200182810382526023815260200180610cb86023913960400191505060405180910390fd5b6108ab838383610c55565b6108e881604051806060016040528060268152602001610d1f602691396001600160a01b0386166000908152602081905260409020549190610971565b6001600160a01b0380851660009081526020819052604080822093909355908416815220546109179082610a08565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610a005760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156109c55781810151838201526020016109ad565b50505050905090810190601f1680156109f25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610a62576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610ac4576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610ad060008383610c55565b600254610add9082610a08565b6002556001600160a01b038216600090815260208190526040902054610b039082610a08565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610b9e5760405162461bcd60e51b8152600401808060200182810382526021815260200180610d6d6021913960400191505060405180910390fd5b610baa82600083610c55565b610be781604051806060016040528060228152602001610cdb602291396001600160a01b0385166000908152602081905260409020549190610971565b6001600160a01b038316600090815260208190526040902055600254610c0d9082610c5a565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b505050565b600082821115610cb1576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220c510d96b1e7590f4ed917cc16ea5d43c52ab25325ed1f7430d41a5b2456a4a3764736f6c634300060c00334c6f73736c6573735632546f6b656e3a2073657420706f6f6c20746f20746865207a65726f20616464726573734c6f73736c6573735632466163746f72793a20464f5242494444454e000000004c6f73736c6573735632466163746f72793a2073657420666565546f20746f20746865207a65726f20616464726573734c6f73736c6573735632466163746f72793a20544f4b454e204e414d4520494e50555420495320494e56414c49444c6f73736c6573735632466163746f72793a204944454e544943414c5f4144445245535345534c6f73736c6573735632466163746f72793a2066656550657263656e74206d757374206265206c657373207468616e20505245434953494f4e4c6f73736c6573735632466163746f72793a20736574205f70656e64696e6744414f20746f20746865207a65726f20616464726573734c6f73736c6573735632466163746f72793a20504f4f4c204d555354204245204143544956454c6f73736c6573735632466163746f72793a20736574205f44414f20746f20746865207a65726f20616464726573734c6f73736c6573735632466163746f72793a2041474752454741544f52205a45524f5f414444524553534c6f73736c6573735632466163746f72793a2042494444494e47204455524154494f4e20494e56414c49445f414d4f554e544c6f73736c6573735632466163746f72793a20544f4b454e2053594d424f4c20494e50555420495320494e56414c49444c6f73736c6573735632466163746f72793a20414444524553532050524f5649444552205a45524f5f414444524553534c6f73736c6573735632466163746f72793a2047414d494e47204455524154494f4e20494e56414c49445f414d4f554e54a2646970667358221220e93527757657f498e5582ebe25f1d8d5dace4f5c16e643a75899b0d770245ee964736f6c634300060c00334c6f73736c6573735632466163746f72793a207365742044414f20746865207a65726f2061646472657373000000000000000000000000fd9656df3e4dca84c260137aecba416050aea145

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000fd9656df3e4dca84c260137aecba416050aea145

-----Decoded View---------------
Arg [0] : _DAO (address): 0xfd9656df3e4dca84c260137aecba416050aea145

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000fd9656df3e4dca84c260137aecba416050aea145


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading