ETH Price: $2,636.69 (+3.18%)

Transaction Decoder

Block:
12376584 at May-05-2021 09:07:00 PM +UTC
Transaction Fee:
0.00888741 ETH $23.43
Gas Used:
126,963 Gas / 70 Gwei

Emitted Events:

108 VotingToken.Transfer( from=[Receiver] DFOStake, to=[Sender] 0x03cd01aa64e16922ed79495190f3fb7b67bf6dbf, value=12500000000000000000 )
109 UniswapV2Pair.Transfer( from=[Receiver] DFOStake, to=[Sender] 0x03cd01aa64e16922ed79495190f3fb7b67bf6dbf, value=6528724495874005021 )
110 DFOStake.Withdrawn( sender=[Sender] 0x03cd01aa64e16922ed79495190f3fb7b67bf6dbf, receiver=[Sender] 0x03cd01aa64e16922ed79495190f3fb7b67bf6dbf, tier=0, poolPosition=1, firstAmount=50000000000000000000, secondAmount=1032738702086038280, poolAmount=6528724495874005021, reward=12500000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x03CD01Aa...B67bf6Dbf
0.100000016406530821 Eth
Nonce: 414
0.091112606406530821 Eth
Nonce: 415
0.00888741
0x2dC7b857...74e4de161
0x2e231cbf...29703D0bA
(Spark Pool)
35.290308371863647519 Eth35.299195781863647519 Eth0.00888741
0xA3Ee876D...13fD391f7

Execution Trace

DFOStake.withdraw( tier=0, position=2 )
  • DoubleProxy.STATICCALL( )
  • MVDProxy.STATICCALL( )
  • VotingToken.transfer( recipient=0x03CD01Aa64E16922ED79495190f3fb7B67bf6Dbf, amount=12500000000000000000 ) => ( True )
  • UniswapV2Factory.getPair( 0x2dC7b857772A4Ef7F9f39A88048F15374e4de161, 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 ) => ( 0x2e231cbf03ea19f8a5BED1c053E678729703D0bA )
  • UniswapV2Pair.transfer( to=0x03CD01Aa64E16922ED79495190f3fb7B67bf6Dbf, value=6528724495874005021 ) => ( True )
    File 1 of 6: DFOStake
    pragma solidity ^0.7.1;
    
    contract DFOStake {
    
        address private constant UNISWAP_V2_FACTORY = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
    
        address private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
    
        address private WETH_ADDRESS = IUniswapV2Router(UNISWAP_V2_ROUTER).WETH();
    
        address[] private TOKENS;
    
        mapping(uint256 => uint256) private _totalPoolAmount;
    
        uint256[] private TIME_WINDOWS;
    
        uint256[] private REWARD_MULTIPLIERS;
    
        uint256[] private REWARD_DIVIDERS;
    
        uint256[] private REWARD_SPLIT_TRANCHES;
    
        address private _doubleProxy;
    
        struct StakeInfo {
            address sender;
            uint256 poolPosition;
            uint256 firstAmount;
            uint256 secondAmount;
            uint256 poolAmount;
            uint256 reward;
            uint256 endBlock;
            uint256[] partialRewardBlockTimes;
            uint256 splittedReward;
        }
    
        uint256 private _startBlock;
    
        mapping(uint256 => mapping(uint256 => StakeInfo)) private _stakeInfo;
        mapping(uint256 => uint256) private _stakeInfoLength;
    
        event Staked(address indexed sender, uint256 indexed tier, uint256 indexed poolPosition, uint256 firstAmount, uint256 secondAmount, uint256 poolAmount, uint256 reward, uint256 endBlock, uint256[] partialRewardBlockTimes, uint256 splittedReward);
        event Withdrawn(address sender, address indexed receiver, uint256 indexed tier, uint256 indexed poolPosition, uint256 firstAmount, uint256 secondAmount, uint256 poolAmount, uint256 reward);
        event PartialWithdrawn(address sender, address indexed receiver, uint256 indexed tier, uint256 reward);
    
        constructor(uint256 startBlock, address doubleProxy, address[] memory tokens, uint256[] memory timeWindows, uint256[] memory rewardMultipliers, uint256[] memory rewardDividers, uint256[] memory rewardSplitTranches) public {
    
            _startBlock = startBlock;
    
            _doubleProxy = doubleProxy;
    
            for(uint256 i = 0; i < tokens.length; i++) {
                TOKENS.push(tokens[i]);
            }
    
            assert(timeWindows.length == rewardMultipliers.length && rewardMultipliers.length == rewardDividers.length && rewardDividers.length == rewardSplitTranches.length);
            for(uint256 i = 0; i < timeWindows.length; i++) {
                TIME_WINDOWS.push(timeWindows[i]);
            }
    
            for(uint256 i = 0; i < rewardMultipliers.length; i++) {
                REWARD_MULTIPLIERS.push(rewardMultipliers[i]);
            }
    
            for(uint256 i = 0; i < rewardDividers.length; i++) {
                REWARD_DIVIDERS.push(rewardDividers[i]);
            }
    
            for(uint256 i = 0; i < rewardSplitTranches.length; i++) {
                REWARD_SPLIT_TRANCHES.push(rewardSplitTranches[i]);
            }
        }
    
        function doubleProxy() public view returns(address) {
            return _doubleProxy;
        }
    
        function tokens() public view returns(address[] memory) {
            return TOKENS;
        }
    
        function tierData() public view returns(uint256[] memory, uint256[] memory, uint256[] memory, uint256[] memory) {
            return (TIME_WINDOWS, REWARD_MULTIPLIERS, REWARD_DIVIDERS, REWARD_SPLIT_TRANCHES);
        }
    
        function startBlock() public view returns(uint256) {
            return _startBlock;
        }
    
        function totalPoolAmount(uint256 poolPosition) public view returns(uint256) {
            return _totalPoolAmount[poolPosition];
        }
    
        function setDoubleProxy(address newDoubleProxy) public {
            require(IMVDFunctionalitiesManager(IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getMVDFunctionalitiesManagerAddress()).isAuthorizedFunctionality(msg.sender), "Unauthorized Action!");
            _doubleProxy = newDoubleProxy;
        }
    
        function emergencyFlush() public {
            IMVDProxy proxy = IMVDProxy(IDoubleProxy(_doubleProxy).proxy());
            require(IMVDFunctionalitiesManager(proxy.getMVDFunctionalitiesManagerAddress()).isAuthorizedFunctionality(msg.sender), "Unauthorized Action!");
            address walletAddress = proxy.getMVDWalletAddress();
            address tokenAddress = proxy.getToken();
            IERC20 token = IERC20(tokenAddress);
            uint256 balanceOf = token.balanceOf(address(this));
            if(balanceOf > 0) {
                token.transfer(walletAddress, balanceOf);
            }
            balanceOf = 0;
            for(uint256 i = 0; i < TOKENS.length; i++) {
                token = IERC20(IUniswapV2Factory(UNISWAP_V2_FACTORY).getPair(tokenAddress, TOKENS[i]));
                balanceOf = token.balanceOf(address(this));
                if(balanceOf > 0) {
                    token.transfer(walletAddress, balanceOf);
                    _totalPoolAmount[i] = 0;
                }
                balanceOf = 0;
            }
        }
    
        function stake(uint256 tier, uint256 poolPosition, uint256 originalFirstAmount, uint256 firstAmountMin, uint256 value, uint256 secondAmountMin) public payable {
            require(block.number >= _startBlock, "Staking is still not available");
            require(poolPosition < TOKENS.length, "Unknown Pool");
            require(tier < TIME_WINDOWS.length, "Unknown tier");
    
            require(originalFirstAmount > 0, "First amount must be greater than 0");
    
            uint256 originalSecondAmount = TOKENS[poolPosition] == WETH_ADDRESS ? msg.value : value;
            require(originalSecondAmount > 0, "Second amount must be greater than 0");
    
            IMVDProxy proxy = IMVDProxy(IDoubleProxy(_doubleProxy).proxy());
            address tokenAddress = proxy.getToken();
    
            _transferTokensAndCheckAllowance(tokenAddress, originalFirstAmount);
            _transferTokensAndCheckAllowance(TOKENS[poolPosition], originalSecondAmount);
    
            address secondToken = TOKENS[poolPosition];
    
            (uint256 firstAmount, uint256 secondAmount, uint256 poolAmount) = _createPoolToken(originalFirstAmount, firstAmountMin, originalSecondAmount, secondAmountMin, tokenAddress, secondToken);
    
            _totalPoolAmount[poolPosition] += poolAmount;
    
            (uint256 minCap,, uint256 remainingToStake) = getStakingInfo(tier);
            require(firstAmount >= minCap, "Amount to stake is less than the current min cap");
            require(firstAmount <= remainingToStake, "Amount to stake must be less than the current remaining one");
    
            calculateRewardAndAddStakingPosition(tier, poolPosition, firstAmount, secondAmount, poolAmount, proxy);
        }
    
        function getStakingInfo(uint256 tier) public view returns(uint256 minCap, uint256 hardCap, uint256 remainingToStake) {
            (minCap, hardCap) = getStakingCap(tier);
            remainingToStake = hardCap;
            uint256 length = _stakeInfoLength[tier];
            for(uint256 i = 0; i < length; i++) {
                if(_stakeInfo[tier][i].endBlock > block.number) {
                    remainingToStake -= _stakeInfo[tier][i].firstAmount;
                }
            }
        }
    
        function getStakingCap(uint256 tier) public view returns(uint256, uint256) {
            IStateHolder stateHolder = IStateHolder(IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getStateHolderAddress());
            string memory tierString = _toString(tier);
            string memory addressString = _toLowerCase(_toString(address(this)));
            return (
                stateHolder.getUint256(string(abi.encodePacked("staking.", addressString, ".tiers[", tierString, "].minCap"))),
                stateHolder.getUint256(string(abi.encodePacked("staking.", addressString, ".tiers[", tierString, "].hardCap")))
            );
        }
    
        function _transferTokensAndCheckAllowance(address tokenAddress, uint256 value) private {
            if(tokenAddress == WETH_ADDRESS) {
                return;
            }
            IERC20 token = IERC20(tokenAddress);
            token.transferFrom(msg.sender, address(this), value);
            if(token.allowance(address(this), UNISWAP_V2_ROUTER) <= value) {
                token.approve(UNISWAP_V2_ROUTER, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
            }
        }
    
        function _createPoolToken(uint256 originalFirstAmount, uint256 firstAmountMin, uint256 originalSecondAmount, uint256 secondAmountMin, address firstToken, address secondToken) private returns(uint256 firstAmount, uint256 secondAmount, uint256 poolAmount) {
            if(secondToken == WETH_ADDRESS) {
                (firstAmount, secondAmount, poolAmount) = IUniswapV2Router(UNISWAP_V2_ROUTER).addLiquidityETH{value: originalSecondAmount}(
                    firstToken,
                    originalFirstAmount,
                    firstAmountMin,
                    secondAmountMin,
                    address(this),
                    block.timestamp + 1000
                );
            } else {
                (firstAmount, secondAmount, poolAmount) = IUniswapV2Router(UNISWAP_V2_ROUTER).addLiquidity(
                    firstToken,
                    secondToken,
                    originalFirstAmount,
                    originalSecondAmount,
                    firstAmountMin,
                    secondAmountMin,
                    address(this),
                    block.timestamp + 1000
                );
            }
            if(firstAmount < originalFirstAmount) {
                IERC20(firstToken).transfer(msg.sender, originalFirstAmount - firstAmount);
            }
            if(secondAmount < originalSecondAmount) {
                if(secondToken == WETH_ADDRESS) {
                    payable(msg.sender).transfer(originalSecondAmount - secondAmount);
                } else {
                    IERC20(secondToken).transfer(msg.sender, originalSecondAmount - secondAmount);
                }
            }
        }
    
        function calculateRewardAndAddStakingPosition(uint256 tier, uint256 poolPosition, uint256 firstAmount, uint256 secondAmount, uint256 poolAmount, IMVDProxy proxy) private {
            uint256 partialRewardSingleBlockTime = TIME_WINDOWS[tier] / REWARD_SPLIT_TRANCHES[tier];
            uint256[] memory partialRewardBlockTimes = new uint256[](REWARD_SPLIT_TRANCHES[tier]);
            if(partialRewardBlockTimes.length > 0) {
                partialRewardBlockTimes[0] = block.number + partialRewardSingleBlockTime;
                for(uint256 i = 1; i < partialRewardBlockTimes.length; i++) {
                    partialRewardBlockTimes[i] = partialRewardBlockTimes[i - 1] + partialRewardSingleBlockTime;
                }
            }
            uint256 reward = firstAmount * REWARD_MULTIPLIERS[tier] / REWARD_DIVIDERS[tier];
            StakeInfo memory stakeInfo = StakeInfo(msg.sender, poolPosition, firstAmount, secondAmount, poolAmount, reward, block.number + TIME_WINDOWS[tier], partialRewardBlockTimes, reward / REWARD_SPLIT_TRANCHES[tier]);
            _add(tier, stakeInfo);
            proxy.submit("stakingTransfer", abi.encode(address(0), 0, reward, address(this)));
            emit Staked(msg.sender, tier, poolPosition, firstAmount, secondAmount, poolAmount, reward, stakeInfo.endBlock, partialRewardBlockTimes, stakeInfo.splittedReward);
        }
    
        function _add(uint256 tier, StakeInfo memory element) private returns(uint256, uint256) {
            _stakeInfo[tier][_stakeInfoLength[tier]] = element;
            _stakeInfoLength[tier] = _stakeInfoLength[tier] + 1;
            return (element.reward, element.endBlock);
        }
    
        function _remove(uint256 tier, uint256 i) private {
            if(_stakeInfoLength[tier] <= i) {
                return;
            }
            _stakeInfoLength[tier] = _stakeInfoLength[tier] - 1;
            if(_stakeInfoLength[tier] > i) {
                _stakeInfo[tier][i] = _stakeInfo[tier][_stakeInfoLength[tier]];
            }
            delete _stakeInfo[tier][_stakeInfoLength[tier]];
        }
    
        function length(uint256 tier) public view returns(uint256) {
            return _stakeInfoLength[tier];
        }
    
        function stakeInfo(uint256 tier, uint256 position) public view returns(
            address,
            uint256,
            uint256,
            uint256,
            uint256,
            uint256,
            uint256,
            uint256[] memory,
            uint256
        ) {
            StakeInfo memory tierStakeInfo = _stakeInfo[tier][position];
            return(
                tierStakeInfo.sender,
                tierStakeInfo.poolPosition,
                tierStakeInfo.firstAmount,
                tierStakeInfo.secondAmount,
                tierStakeInfo.poolAmount,
                tierStakeInfo.reward,
                tierStakeInfo.endBlock,
                tierStakeInfo.partialRewardBlockTimes,
                tierStakeInfo.splittedReward
            );
        }
    
        function partialReward(uint256 tier, uint256 position) public {
            StakeInfo memory tierStakeInfo = _stakeInfo[tier][position];
            if(block.number >= tierStakeInfo.endBlock) {
                return withdraw(tier, position);
            }
            require(tierStakeInfo.reward > 0, "No more reward for this staking position");
            uint256 reward = 0;
            for(uint256 i = 0; i < tierStakeInfo.partialRewardBlockTimes.length; i++) {
                if(tierStakeInfo.partialRewardBlockTimes[i] > 0 && block.number >= tierStakeInfo.partialRewardBlockTimes[i]) {
                    reward += tierStakeInfo.splittedReward;
                    tierStakeInfo.partialRewardBlockTimes[i] = 0;
                }
            }
            reward = reward > tierStakeInfo.reward ? tierStakeInfo.reward : reward;
            require(reward > 0, "No reward to redeem");
            IERC20 token = IERC20(IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getToken());
            token.transfer(tierStakeInfo.sender, reward);
            tierStakeInfo.reward = tierStakeInfo.reward - reward;
            _stakeInfo[tier][position] = tierStakeInfo;
            emit PartialWithdrawn(msg.sender, tierStakeInfo.sender, tier, reward);
        }
    
        function withdraw(uint256 tier, uint256 position) public {
            StakeInfo memory tierStakeInfo = _stakeInfo[tier][position];
            require(block.number >= tierStakeInfo.endBlock, "Cannot actually withdraw this position");
            IERC20 token = IERC20(IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getToken());
            if(tierStakeInfo.reward > 0) {
                token.transfer(tierStakeInfo.sender, tierStakeInfo.reward);
            }
            token = IERC20(IUniswapV2Factory(UNISWAP_V2_FACTORY).getPair(address(token), TOKENS[tierStakeInfo.poolPosition]));
            token.transfer(tierStakeInfo.sender, tierStakeInfo.poolAmount);
            _totalPoolAmount[tierStakeInfo.poolPosition] = _totalPoolAmount[tierStakeInfo.poolPosition] - tierStakeInfo.poolAmount;
            emit Withdrawn(msg.sender, tierStakeInfo.sender, tier, tierStakeInfo.poolPosition, tierStakeInfo.firstAmount, tierStakeInfo.secondAmount, tierStakeInfo.poolAmount, tierStakeInfo.reward);
            _remove(tier, position);
        }
    
        function _toString(uint _i) private pure returns(string memory) {
            if (_i == 0) {
                return "0";
            }
            uint j = _i;
            uint len;
            while (j != 0) {
                len++;
                j /= 10;
            }
            bytes memory bstr = new bytes(len);
            uint k = len - 1;
            while (_i != 0) {
                bstr[k--] = byte(uint8(48 + _i % 10));
                _i /= 10;
            }
            return string(bstr);
        }
    
        function _toString(address _addr) private pure returns(string memory) {
            bytes32 value = bytes32(uint256(_addr));
            bytes memory alphabet = "0123456789abcdef";
    
            bytes memory str = new bytes(42);
            str[0] = '0';
            str[1] = 'x';
            for (uint i = 0; i < 20; i++) {
                str[2+i*2] = alphabet[uint(uint8(value[i + 12] >> 4))];
                str[3+i*2] = alphabet[uint(uint8(value[i + 12] & 0x0f))];
            }
            return string(str);
        }
    
        function _toLowerCase(string memory str) private pure returns(string memory) {
            bytes memory bStr = bytes(str);
            for (uint i = 0; i < bStr.length; i++) {
                bStr[i] = bStr[i] >= 0x41 && bStr[i] <= 0x5A ? bytes1(uint8(bStr[i]) + 0x20) : bStr[i];
            }
            return string(bStr);
        }
    }
    
    interface IMVDProxy {
        function getToken() external view returns(address);
        function getStateHolderAddress() external view returns(address);
        function getMVDWalletAddress() external view returns(address);
        function getMVDFunctionalitiesManagerAddress() external view returns(address);
        function submit(string calldata codeName, bytes calldata data) external payable returns(bytes memory returnData);
    }
    
    interface IStateHolder {
        function setUint256(string calldata name, uint256 value) external returns(uint256);
        function getUint256(string calldata name) external view returns(uint256);
        function getBool(string calldata varName) external view returns (bool);
        function clear(string calldata varName) external returns(string memory oldDataType, bytes memory oldVal);
    }
    
    interface IMVDFunctionalitiesManager {
        function isAuthorizedFunctionality(address functionality) external view returns(bool);
    }
    
    interface IERC20 {
        function balanceOf(address account) external view returns (uint256);
        function allowance(address owner, address spender) external view returns (uint256);
        function approve(address spender, uint256 amount) external returns (bool);
        function transfer(address recipient, uint256 amount) external returns (bool);
        function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    }
    
    interface IUniswapV2Router {
        function WETH() external pure returns (address);
        function addLiquidity(
            address tokenA,
            address tokenB,
            uint amountADesired,
            uint amountBDesired,
            uint amountAMin,
            uint amountBMin,
            address to,
            uint deadline
        ) external returns (uint amountA, uint amountB, uint liquidity);
    
        function addLiquidityETH(
            address token,
            uint amountTokenDesired,
            uint amountTokenMin,
            uint amountETHMin,
            address to,
            uint deadline
        ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
    }
    
    interface IUniswapV2Factory {
        function getPair(address tokenA, address tokenB) external view returns (address pair);
    }
    
    interface IDoubleProxy {
        function proxy() external view returns(address);
    }

    File 2 of 6: VotingToken
    {"ICommonUtilities.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface ICommonUtilities {\r\n    function toString(address _addr) external pure returns(string memory);\r\n    function toString(uint _i) external pure returns(string memory);\r\n    function toUint256(bytes calldata bs) external pure returns(uint256 x);\r\n    function toAddress(bytes calldata b) external pure returns (address addr);\r\n    function compareStrings(string calldata a, string calldata b) external pure returns(bool);\r\n    function getFirstJSONPart(address sourceLocation, uint256 sourceLocationId, address location) external pure returns(bytes memory);\r\n    function formatReturnAbiParametersArray(string calldata m) external pure returns(string memory);\r\n    function toLowerCase(string calldata str) external pure returns(string memory);\r\n}"},"IERC20.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface IERC20 {\r\n    function totalSupply() external view returns (uint256);\r\n    function balanceOf(address account) external view returns (uint256);\r\n    function transfer(address recipient, uint256 amount) external returns (bool);\r\n    function allowance(address owner, address spender) external view returns (uint256);\r\n    function approve(address spender, uint256 amount) external returns (bool);\r\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\r\n\r\n    event Transfer(address indexed from, address indexed to, uint256 value);\r\n    event Approval(address indexed owner, address indexed spender, uint256 value);\r\n}"},"IERC721.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IERC721 {\n    function ownerOf(uint256 _tokenId) external view returns (address);\n    function transferFrom(address _from, address _to, uint256 _tokenId) external payable;\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n}"},"IERC721Receiver.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IERC721Receiver {\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\n}"},"IMVDFunctionalitiesManager.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDFunctionalitiesManager {\n\n    function getProxy() external view returns (address);\n    function setProxy() external;\n\n    function init(address sourceLocation,\n        uint256 getMinimumBlockNumberSourceLocationId, address getMinimumBlockNumberFunctionalityAddress,\n        uint256 getEmergencyMinimumBlockNumberSourceLocationId, address getEmergencyMinimumBlockNumberFunctionalityAddress,\n        uint256 getEmergencySurveyStakingSourceLocationId, address getEmergencySurveyStakingFunctionalityAddress,\n        uint256 checkVoteResultSourceLocationId, address checkVoteResultFunctionalityAddress) external;\n\n    function addFunctionality(string calldata codeName, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, bool needsSender) external;\n    function addFunctionality(string calldata codeName, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, bool needsSender, uint256 position) external;\n    function removeFunctionality(string calldata codeName) external returns(bool removed, uint256 position);\n    function isValidFunctionality(address functionality) external view returns(bool);\n    function isAuthorizedFunctionality(address functionality) external view returns(bool);\n    function setCallingContext(address location) external returns(bool);\n    function clearCallingContext() external;\n    function getFunctionalityData(string calldata codeName) external view returns(address, uint256, string memory, address, uint256);\n    function hasFunctionality(string calldata codeName) external view returns(bool);\n    function getFunctionalitiesAmount() external view returns(uint256);\n    function functionalitiesToJSON() external view returns(string memory);\n    function functionalitiesToJSON(uint256 start, uint256 l) external view returns(string memory functionsJSONArray);\n    function functionalityNames() external view returns(string memory);\n    function functionalityNames(uint256 start, uint256 l) external view returns(string memory functionsJSONArray);\n    function functionalityToJSON(string calldata codeName) external view returns(string memory);\n\n    function preConditionCheck(string calldata codeName, bytes calldata data, uint8 submitable, address sender, uint256 value) external view returns(address location, bytes memory payload);\n\n    function setupFunctionality(address proposalAddress) external returns (bool);\n}"},"IMVDFunctionalityModelsManager.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface IMVDFunctionalityModelsManager {\r\n    function init() external;\r\n    function checkWellKnownFunctionalities(string calldata codeName, bool submitable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, bool needsSender, string calldata replaces) external view;\r\n}"},"IMVDFunctionalityProposal.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDFunctionalityProposal {\n\n    function init(string calldata codeName, address location, string calldata methodSignature, string calldata returnAbiParametersArray, string calldata replaces, address proxy) external;\n    function setCollateralData(bool emergency, address sourceLocation, uint256 sourceLocationId, bool submitable, bool isInternal, bool needsSender, address proposer, uint256 votesHardCap) external;\n\n    function getProxy() external view returns(address);\n    function getCodeName() external view returns(string memory);\n    function isEmergency() external view returns(bool);\n    function getSourceLocation() external view returns(address);\n    function getSourceLocationId() external view returns(uint256);\n    function getLocation() external view returns(address);\n    function isSubmitable() external view returns(bool);\n    function getMethodSignature() external view returns(string memory);\n    function getReturnAbiParametersArray() external view returns(string memory);\n    function isInternal() external view returns(bool);\n    function needsSender() external view returns(bool);\n    function getReplaces() external view returns(string memory);\n    function getProposer() external view returns(address);\n    function getSurveyEndBlock() external view returns(uint256);\n    function getSurveyDuration() external view returns(uint256);\n    function isVotesHardCapReached() external view returns(bool);\n    function getVotesHardCapToReach() external view returns(uint256);\n    function toJSON() external view returns(string memory);\n    function getVote(address addr) external view returns(uint256 accept, uint256 refuse);\n    function getVotes() external view returns(uint256, uint256);\n    function start() external;\n    function disable() external;\n    function isDisabled() external view returns(bool);\n    function isTerminated() external view returns(bool);\n    function accept(uint256 amount) external;\n    function retireAccept(uint256 amount) external;\n    function moveToAccept(uint256 amount) external;\n    function refuse(uint256 amount) external;\n    function retireRefuse(uint256 amount) external;\n    function moveToRefuse(uint256 amount) external;\n    function retireAll() external;\n    function withdraw() external;\n    function terminate() external;\n    function set() external;\n\n    event Accept(address indexed voter, uint256 amount);\n    event RetireAccept(address indexed voter, uint256 amount);\n    event MoveToAccept(address indexed voter, uint256 amount);\n    event Refuse(address indexed voter, uint256 amount);\n    event RetireRefuse(address indexed voter, uint256 amount);\n    event MoveToRefuse(address indexed voter, uint256 amount);\n    event RetireAll(address indexed voter, uint256 amount);\n}"},"IMVDFunctionalityProposalManager.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDFunctionalityProposalManager {\n    function newProposal(string calldata codeName, address location, string calldata methodSignature, string calldata returnAbiParametersArray, string calldata replaces) external returns(address);\n    function checkProposal(address proposalAddress) external;\n    function getProxy() external view returns (address);\n    function setProxy() external;\n    function isValidProposal(address proposal) external view returns (bool);\n}"},"IMVDProxy.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDProxy {\n\n    function init(address votingTokenAddress, address functionalityProposalManagerAddress, address stateHolderAddress, address functionalityModelsManagerAddress, address functionalitiesManagerAddress, address walletAddress) external;\n\n    function getDelegates() external view returns(address,address,address,address,address,address);\n    function getToken() external view returns(address);\n    function getMVDFunctionalityProposalManagerAddress() external view returns(address);\n    function getStateHolderAddress() external view returns(address);\n    function getMVDFunctionalityModelsManagerAddress() external view returns(address);\n    function getMVDFunctionalitiesManagerAddress() external view returns(address);\n    function getMVDWalletAddress() external view returns(address);\n    function setDelegate(uint256 position, address newAddress) external returns(address oldAddress);\n    function changeProxy(address newAddress, bytes calldata initPayload) external;\n    function isValidProposal(address proposal) external view returns (bool);\n    function isAuthorizedFunctionality(address functionality) external view returns(bool);\n    function newProposal(string calldata codeName, bool emergency, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string calldata methodSignature, string calldata returnParametersJSONArray, bool isInternal, bool needsSender, string calldata replaces) external returns(address proposalAddress);\n    function startProposal(address proposalAddress) external;\n    function disableProposal(address proposalAddress) external;\n    function transfer(address receiver, uint256 value, address token) external;\n    function transfer721(address receiver, uint256 tokenId, bytes calldata data, bool safe, address token) external;\n    function flushToWallet(address tokenAddress, bool is721, uint256 tokenId) external;\n    function setProposal() external;\n    function read(string calldata codeName, bytes calldata data) external view returns(bytes memory returnData);\n    function submit(string calldata codeName, bytes calldata data) external payable returns(bytes memory returnData);\n    function callFromManager(address location, bytes calldata payload) external returns(bool, bytes memory);\n    function emitFromManager(string calldata codeName, address proposal, string calldata replaced, address replacedSourceLocation, uint256 replacedSourceLocationId, address location, bool submitable, string calldata methodSignature, bool isInternal, bool needsSender, address proposalAddress) external;\n\n    function emitEvent(string calldata eventSignature, bytes calldata firstIndex, bytes calldata secondIndex, bytes calldata data) external;\n\n    event ProxyChanged(address indexed newAddress);\n    event DelegateChanged(uint256 position, address indexed oldAddress, address indexed newAddress);\n\n    event Proposal(address proposal);\n    event ProposalCheck(address indexed proposal);\n    event ProposalSet(address indexed proposal, bool success);\n    event FunctionalitySet(string codeName, address indexed proposal, string replaced, address replacedSourceLocation, uint256 replacedSourceLocationId, address indexed replacedLocation, bool replacedWasSubmitable, string replacedMethodSignature, bool replacedWasInternal, bool replacedNeededSender, address indexed replacedProposal);\n\n    event Event(string indexed key, bytes32 indexed firstIndex, bytes32 indexed secondIndex, bytes data);\n}"},"IMVDWallet.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDWallet {\n\n    function getProxy() external view returns (address);\n\n    function setProxy() external;\n\n    function setNewWallet(address payable newWallet, address tokenAddress) external;\n\n    function transfer(address receiver, uint256 value, address tokenAddress) external;\n    \n    function transfer(address receiver, uint256 tokenId, bytes calldata data, bool safe, address token) external;\n\n    function flushToNewWallet(address token) external;\n\n    function flush721ToNewWallet(uint256 tokenId, bytes calldata data, bool safe, address tokenAddress) external;\n}"},"IStateHolder.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IStateHolder {\n\n    function init() external;\n\n    function getProxy() external view returns (address);\n    function setProxy() external;\n    function toJSON() external view returns(string memory);\n    function toJSON(uint256 start, uint256 l) external view returns(string memory);\n    function getStateSize() external view returns (uint256);\n    function exists(string calldata varName) external view returns(bool);\n    function getDataType(string calldata varName) external view returns(string memory dataType);\n    function clear(string calldata varName) external returns(string memory oldDataType, bytes memory oldVal);\n    function setBytes(string calldata varName, bytes calldata val) external returns(bytes memory);\n    function getBytes(string calldata varName) external view returns(bytes memory);\n    function setString(string calldata varName, string calldata val) external returns(string memory);\n    function getString(string calldata varName) external view returns (string memory);\n    function setBool(string calldata varName, bool val) external returns(bool);\n    function getBool(string calldata varName) external view returns (bool);\n    function getUint256(string calldata varName) external view returns (uint256);\n    function setUint256(string calldata varName, uint256 val) external returns(uint256);\n    function getAddress(string calldata varName) external view returns (address);\n    function setAddress(string calldata varName, address val) external returns (address);\n}"},"IVotingToken.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface IVotingToken {\r\n    function init(string calldata name, string calldata symbol, uint256 decimals, uint256 totalSupply) external;\r\n\r\n    function getProxy() external view returns (address);\r\n    function setProxy() external;\r\n\r\n    function name() external view returns(string memory);\r\n    function symbol() external view returns(string memory);\r\n    function decimals() external view returns(uint256);\r\n\r\n    function mint(uint256 amount) external;\r\n    function burn(uint256 amount) external;\r\n\r\n    function increaseAllowance(address spender, uint256 addedValue) external returns (bool);\r\n    function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);\r\n}"},"VotingToken.sol":{"content":"pragma solidity ^0.6.0;\n\nimport \"./IMVDProxy.sol\";\nimport \"./IERC20.sol\";\nimport \"./IVotingToken.sol\";\nimport \"./IMVDFunctionalityProposalManager.sol\";\nimport \"./IMVDFunctionalitiesManager.sol\";\n\ncontract VotingToken is IERC20, IVotingToken {\n\n    mapping (address =\u003e uint256) private _balances;\n\n    mapping (address =\u003e mapping (address =\u003e uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n    uint256 private _decimals;\n    address private _proxy;\n    string private _name;\n    string private _symbol;\n\n    constructor(string memory name, string memory symbol, uint256 decimals, uint256 totalSupply) public {\n        if(totalSupply == 0) {\n            return;\n        }\n        init(name, symbol, decimals, totalSupply);\n    }\n\n    function init(string memory name, string memory symbol, uint256 decimals, uint256 totalSupply) public override {\n        require(_totalSupply == 0, \"Init already called!\");\n\n        _name = name;\n        _symbol = symbol;\n        _decimals = decimals;\n        _totalSupply = totalSupply * (10 ** decimals);\n        _balances[msg.sender] = _totalSupply;\n        emit Transfer(address(this), msg.sender, _totalSupply);\n    }\n\n    receive() external payable {\n        revert(\"ETH not accepted\");\n    }\n\n    function getProxy() public override view returns(address) {\n        return _proxy;\n    }\n\n    function name() public override view returns(string memory) {\n        return _name;\n    }\n\n    function symbol() public override view returns(string memory) {\n        return _symbol;\n    }\n\n    function decimals() public override view returns(uint256) {\n        return _decimals;\n    }\n\n    function totalSupply() public override view returns (uint256) {\n        return _totalSupply;\n    }\n\n    function balanceOf(address account) public override view returns (uint256) {\n        return _balances[account];\n    }\n\n    function transfer(address recipient, uint256 amount) public override returns (bool) {\n        _transfer(msg.sender, recipient, amount);\n        return true;\n    }\n\n    function allowance(address owner, address spender) public override view returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    function approve(address spender, uint256 amount) public override returns (bool) {\n        _approve(msg.sender, spender, amount);\n        return true;\n    }\n\n    function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {\n        _transfer(sender, recipient, amount);\n        address txSender = msg.sender;\n        if(_proxy == address(0) || !(IMVDFunctionalityProposalManager(IMVDProxy(_proxy).getMVDFunctionalityProposalManagerAddress()).isValidProposal(txSender) \u0026\u0026 recipient == txSender)) {\n            _approve(sender, txSender, _allowances[sender][txSender] = sub(_allowances[sender][txSender], amount, \"ERC20: transfer amount exceeds allowance\"));\n        }\n        return true;\n    }\n\n    function increaseAllowance(address spender, uint256 addedValue) public override returns (bool) {\n        _approve(msg.sender, spender, add(_allowances[msg.sender][spender], addedValue));\n        return true;\n    }\n\n    function decreaseAllowance(address spender, uint256 subtractedValue) public override returns (bool) {\n        _approve(msg.sender, spender, sub(_allowances[msg.sender][spender], subtractedValue, \"ERC20: decreased allowance below zero\"));\n        return true;\n    }\n\n    function _transfer(address sender, address recipient, uint256 amount) internal {\n        require(sender != address(0), \"ERC20: transfer from the zero address\");\n        require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n        _balances[sender] = sub(_balances[sender], amount, \"ERC20: transfer amount exceeds balance\");\n        _balances[recipient] = add(_balances[recipient], amount);\n        emit Transfer(sender, recipient, amount);\n    }\n\n    function _approve(address owner, address spender, uint256 amount) internal {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    function add(uint256 a, uint256 b) internal pure returns (uint256 c) {\n        c = a + b;\n        require(c \u003e= a, \"SafeMath: addition overflow\");\n    }\n\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256 c) {\n        require(b \u003c= a, errorMessage);\n        c = a - b;\n    }\n\n    function setProxy() public override {\n        require(_totalSupply != 0, \"Init not called!\");\n        require(_proxy == address(0) || _proxy == msg.sender, _proxy != address(0) ? \"Proxy already set!\" : \"Only Proxy can toggle itself!\");\n        _proxy = _proxy == address(0) ?  msg.sender : address(0);\n    }\n\n    function mint(uint256 amount) public override {\n        require(IMVDFunctionalitiesManager(IMVDProxy(_proxy).getMVDFunctionalitiesManagerAddress()).isAuthorizedFunctionality(msg.sender), \"Unauthorized access!\");\n\n        _totalSupply = add(_totalSupply, amount);\n        _balances[_proxy] = add(_balances[_proxy], amount);\n        emit Transfer(address(0), _proxy, amount);\n    }\n\n    function burn(uint256 amount) public override {\n        _balances[msg.sender] = sub(_balances[msg.sender], amount, \"VotingToken: burn amount exceeds balance\");\n        _totalSupply = sub(_totalSupply, amount, \"VotingToken: burn amount exceeds total supply\");\n        emit Transfer(msg.sender, address(0), amount);\n    }\n}"}}

    File 3 of 6: UniswapV2Pair
    // File: contracts/interfaces/IUniswapV2Pair.sol
    
    pragma solidity >=0.5.0;
    
    interface IUniswapV2Pair {
        event Approval(address indexed owner, address indexed spender, uint value);
        event Transfer(address indexed from, address indexed to, uint value);
    
        function name() external pure returns (string memory);
        function symbol() external pure returns (string memory);
        function decimals() external pure returns (uint8);
        function totalSupply() external view returns (uint);
        function balanceOf(address owner) external view returns (uint);
        function allowance(address owner, address spender) external view returns (uint);
    
        function approve(address spender, uint value) external returns (bool);
        function transfer(address to, uint value) external returns (bool);
        function transferFrom(address from, address to, uint value) external returns (bool);
    
        function DOMAIN_SEPARATOR() external view returns (bytes32);
        function PERMIT_TYPEHASH() external pure returns (bytes32);
        function nonces(address owner) external view returns (uint);
    
        function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
    
        event Mint(address indexed sender, uint amount0, uint amount1);
        event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
        event Swap(
            address indexed sender,
            uint amount0In,
            uint amount1In,
            uint amount0Out,
            uint amount1Out,
            address indexed to
        );
        event Sync(uint112 reserve0, uint112 reserve1);
    
        function MINIMUM_LIQUIDITY() external pure returns (uint);
        function factory() external view returns (address);
        function token0() external view returns (address);
        function token1() external view returns (address);
        function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
        function price0CumulativeLast() external view returns (uint);
        function price1CumulativeLast() external view returns (uint);
        function kLast() external view returns (uint);
    
        function mint(address to) external returns (uint liquidity);
        function burn(address to) external returns (uint amount0, uint amount1);
        function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
        function skim(address to) external;
        function sync() external;
    
        function initialize(address, address) external;
    }
    
    // File: contracts/interfaces/IUniswapV2ERC20.sol
    
    pragma solidity >=0.5.0;
    
    interface IUniswapV2ERC20 {
        event Approval(address indexed owner, address indexed spender, uint value);
        event Transfer(address indexed from, address indexed to, uint value);
    
        function name() external pure returns (string memory);
        function symbol() external pure returns (string memory);
        function decimals() external pure returns (uint8);
        function totalSupply() external view returns (uint);
        function balanceOf(address owner) external view returns (uint);
        function allowance(address owner, address spender) external view returns (uint);
    
        function approve(address spender, uint value) external returns (bool);
        function transfer(address to, uint value) external returns (bool);
        function transferFrom(address from, address to, uint value) external returns (bool);
    
        function DOMAIN_SEPARATOR() external view returns (bytes32);
        function PERMIT_TYPEHASH() external pure returns (bytes32);
        function nonces(address owner) external view returns (uint);
    
        function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
    }
    
    // File: contracts/libraries/SafeMath.sol
    
    pragma solidity =0.5.16;
    
    // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
    
    library SafeMath {
        function add(uint x, uint y) internal pure returns (uint z) {
            require((z = x + y) >= x, 'ds-math-add-overflow');
        }
    
        function sub(uint x, uint y) internal pure returns (uint z) {
            require((z = x - y) <= x, 'ds-math-sub-underflow');
        }
    
        function mul(uint x, uint y) internal pure returns (uint z) {
            require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
        }
    }
    
    // File: contracts/UniswapV2ERC20.sol
    
    pragma solidity =0.5.16;
    
    
    
    contract UniswapV2ERC20 is IUniswapV2ERC20 {
        using SafeMath for uint;
    
        string public constant name = 'Uniswap V2';
        string public constant symbol = 'UNI-V2';
        uint8 public constant decimals = 18;
        uint  public totalSupply;
        mapping(address => uint) public balanceOf;
        mapping(address => mapping(address => uint)) public allowance;
    
        bytes32 public DOMAIN_SEPARATOR;
        // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
        bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
        mapping(address => uint) public nonces;
    
        event Approval(address indexed owner, address indexed spender, uint value);
        event Transfer(address indexed from, address indexed to, uint value);
    
        constructor() public {
            uint chainId;
            assembly {
                chainId := chainid
            }
            DOMAIN_SEPARATOR = keccak256(
                abi.encode(
                    keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
                    keccak256(bytes(name)),
                    keccak256(bytes('1')),
                    chainId,
                    address(this)
                )
            );
        }
    
        function _mint(address to, uint value) internal {
            totalSupply = totalSupply.add(value);
            balanceOf[to] = balanceOf[to].add(value);
            emit Transfer(address(0), to, value);
        }
    
        function _burn(address from, uint value) internal {
            balanceOf[from] = balanceOf[from].sub(value);
            totalSupply = totalSupply.sub(value);
            emit Transfer(from, address(0), value);
        }
    
        function _approve(address owner, address spender, uint value) private {
            allowance[owner][spender] = value;
            emit Approval(owner, spender, value);
        }
    
        function _transfer(address from, address to, uint value) private {
            balanceOf[from] = balanceOf[from].sub(value);
            balanceOf[to] = balanceOf[to].add(value);
            emit Transfer(from, to, value);
        }
    
        function approve(address spender, uint value) external returns (bool) {
            _approve(msg.sender, spender, value);
            return true;
        }
    
        function transfer(address to, uint value) external returns (bool) {
            _transfer(msg.sender, to, value);
            return true;
        }
    
        function transferFrom(address from, address to, uint value) external returns (bool) {
            if (allowance[from][msg.sender] != uint(-1)) {
                allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
            }
            _transfer(from, to, value);
            return true;
        }
    
        function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
            require(deadline >= block.timestamp, 'UniswapV2: EXPIRED');
            bytes32 digest = keccak256(
                abi.encodePacked(
                    '\x19\x01',
                    DOMAIN_SEPARATOR,
                    keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
                )
            );
            address recoveredAddress = ecrecover(digest, v, r, s);
            require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE');
            _approve(owner, spender, value);
        }
    }
    
    // File: contracts/libraries/Math.sol
    
    pragma solidity =0.5.16;
    
    // a library for performing various math operations
    
    library Math {
        function min(uint x, uint y) internal pure returns (uint z) {
            z = x < y ? x : y;
        }
    
        // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
        function sqrt(uint y) internal pure returns (uint z) {
            if (y > 3) {
                z = y;
                uint x = y / 2 + 1;
                while (x < z) {
                    z = x;
                    x = (y / x + x) / 2;
                }
            } else if (y != 0) {
                z = 1;
            }
        }
    }
    
    // File: contracts/libraries/UQ112x112.sol
    
    pragma solidity =0.5.16;
    
    // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
    
    // range: [0, 2**112 - 1]
    // resolution: 1 / 2**112
    
    library UQ112x112 {
        uint224 constant Q112 = 2**112;
    
        // encode a uint112 as a UQ112x112
        function encode(uint112 y) internal pure returns (uint224 z) {
            z = uint224(y) * Q112; // never overflows
        }
    
        // divide a UQ112x112 by a uint112, returning a UQ112x112
        function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
            z = x / uint224(y);
        }
    }
    
    // File: contracts/interfaces/IERC20.sol
    
    pragma solidity >=0.5.0;
    
    interface IERC20 {
        event Approval(address indexed owner, address indexed spender, uint value);
        event Transfer(address indexed from, address indexed to, uint value);
    
        function name() external view returns (string memory);
        function symbol() external view returns (string memory);
        function decimals() external view returns (uint8);
        function totalSupply() external view returns (uint);
        function balanceOf(address owner) external view returns (uint);
        function allowance(address owner, address spender) external view returns (uint);
    
        function approve(address spender, uint value) external returns (bool);
        function transfer(address to, uint value) external returns (bool);
        function transferFrom(address from, address to, uint value) external returns (bool);
    }
    
    // File: contracts/interfaces/IUniswapV2Factory.sol
    
    pragma solidity >=0.5.0;
    
    interface IUniswapV2Factory {
        event PairCreated(address indexed token0, address indexed token1, address pair, uint);
    
        function feeTo() external view returns (address);
        function feeToSetter() external view returns (address);
    
        function getPair(address tokenA, address tokenB) external view returns (address pair);
        function allPairs(uint) external view returns (address pair);
        function allPairsLength() external view returns (uint);
    
        function createPair(address tokenA, address tokenB) external returns (address pair);
    
        function setFeeTo(address) external;
        function setFeeToSetter(address) external;
    }
    
    // File: contracts/interfaces/IUniswapV2Callee.sol
    
    pragma solidity >=0.5.0;
    
    interface IUniswapV2Callee {
        function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external;
    }
    
    // File: contracts/UniswapV2Pair.sol
    
    pragma solidity =0.5.16;
    
    
    
    
    
    
    
    
    contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
        using SafeMath  for uint;
        using UQ112x112 for uint224;
    
        uint public constant MINIMUM_LIQUIDITY = 10**3;
        bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));
    
        address public factory;
        address public token0;
        address public token1;
    
        uint112 private reserve0;           // uses single storage slot, accessible via getReserves
        uint112 private reserve1;           // uses single storage slot, accessible via getReserves
        uint32  private blockTimestampLast; // uses single storage slot, accessible via getReserves
    
        uint public price0CumulativeLast;
        uint public price1CumulativeLast;
        uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event
    
        uint private unlocked = 1;
        modifier lock() {
            require(unlocked == 1, 'UniswapV2: LOCKED');
            unlocked = 0;
            _;
            unlocked = 1;
        }
    
        function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
            _reserve0 = reserve0;
            _reserve1 = reserve1;
            _blockTimestampLast = blockTimestampLast;
        }
    
        function _safeTransfer(address token, address to, uint value) private {
            (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
            require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED');
        }
    
        event Mint(address indexed sender, uint amount0, uint amount1);
        event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
        event Swap(
            address indexed sender,
            uint amount0In,
            uint amount1In,
            uint amount0Out,
            uint amount1Out,
            address indexed to
        );
        event Sync(uint112 reserve0, uint112 reserve1);
    
        constructor() public {
            factory = msg.sender;
        }
    
        // called once by the factory at time of deployment
        function initialize(address _token0, address _token1) external {
            require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check
            token0 = _token0;
            token1 = _token1;
        }
    
        // update reserves and, on the first call per block, price accumulators
        function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {
            require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'UniswapV2: OVERFLOW');
            uint32 blockTimestamp = uint32(block.timestamp % 2**32);
            uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
            if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
                // * never overflows, and + overflow is desired
                price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
                price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
            }
            reserve0 = uint112(balance0);
            reserve1 = uint112(balance1);
            blockTimestampLast = blockTimestamp;
            emit Sync(reserve0, reserve1);
        }
    
        // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k)
        function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) {
            address feeTo = IUniswapV2Factory(factory).feeTo();
            feeOn = feeTo != address(0);
            uint _kLast = kLast; // gas savings
            if (feeOn) {
                if (_kLast != 0) {
                    uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1));
                    uint rootKLast = Math.sqrt(_kLast);
                    if (rootK > rootKLast) {
                        uint numerator = totalSupply.mul(rootK.sub(rootKLast));
                        uint denominator = rootK.mul(5).add(rootKLast);
                        uint liquidity = numerator / denominator;
                        if (liquidity > 0) _mint(feeTo, liquidity);
                    }
                }
            } else if (_kLast != 0) {
                kLast = 0;
            }
        }
    
        // this low-level function should be called from a contract which performs important safety checks
        function mint(address to) external lock returns (uint liquidity) {
            (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
            uint balance0 = IERC20(token0).balanceOf(address(this));
            uint balance1 = IERC20(token1).balanceOf(address(this));
            uint amount0 = balance0.sub(_reserve0);
            uint amount1 = balance1.sub(_reserve1);
    
            bool feeOn = _mintFee(_reserve0, _reserve1);
            uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
            if (_totalSupply == 0) {
                liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);
               _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
            } else {
                liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1);
            }
            require(liquidity > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED');
            _mint(to, liquidity);
    
            _update(balance0, balance1, _reserve0, _reserve1);
            if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date
            emit Mint(msg.sender, amount0, amount1);
        }
    
        // this low-level function should be called from a contract which performs important safety checks
        function burn(address to) external lock returns (uint amount0, uint amount1) {
            (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
            address _token0 = token0;                                // gas savings
            address _token1 = token1;                                // gas savings
            uint balance0 = IERC20(_token0).balanceOf(address(this));
            uint balance1 = IERC20(_token1).balanceOf(address(this));
            uint liquidity = balanceOf[address(this)];
    
            bool feeOn = _mintFee(_reserve0, _reserve1);
            uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
            amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution
            amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution
            require(amount0 > 0 && amount1 > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED');
            _burn(address(this), liquidity);
            _safeTransfer(_token0, to, amount0);
            _safeTransfer(_token1, to, amount1);
            balance0 = IERC20(_token0).balanceOf(address(this));
            balance1 = IERC20(_token1).balanceOf(address(this));
    
            _update(balance0, balance1, _reserve0, _reserve1);
            if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date
            emit Burn(msg.sender, amount0, amount1, to);
        }
    
        // this low-level function should be called from a contract which performs important safety checks
        function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
            require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT');
            (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
            require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY');
    
            uint balance0;
            uint balance1;
            { // scope for _token{0,1}, avoids stack too deep errors
            address _token0 = token0;
            address _token1 = token1;
            require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO');
            if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
            if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
            if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data);
            balance0 = IERC20(_token0).balanceOf(address(this));
            balance1 = IERC20(_token1).balanceOf(address(this));
            }
            uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
            uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
            require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT');
            { // scope for reserve{0,1}Adjusted, avoids stack too deep errors
            uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));
            uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));
            require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K');
            }
    
            _update(balance0, balance1, _reserve0, _reserve1);
            emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
        }
    
        // force balances to match reserves
        function skim(address to) external lock {
            address _token0 = token0; // gas savings
            address _token1 = token1; // gas savings
            _safeTransfer(_token0, to, IERC20(_token0).balanceOf(address(this)).sub(reserve0));
            _safeTransfer(_token1, to, IERC20(_token1).balanceOf(address(this)).sub(reserve1));
        }
    
        // force reserves to match balances
        function sync() external lock {
            _update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1);
        }
    }

    File 4 of 6: DoubleProxy
    {"DoubleProxy.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\nimport \"./IDoubleProxy.sol\";\r\n\r\ncontract DoubleProxy is IDoubleProxy {\r\n\r\n    address private _proxy;\r\n\r\n    mapping(address =\u003e bool) private _isProxy;\r\n\r\n    address[] private _proxies;\r\n\r\n    constructor(address[] memory proxies, address currentProxy) public {\r\n        init(proxies, currentProxy);\r\n    }\r\n\r\n    function init(address[] memory proxies, address currentProxy) public override {\r\n        require(_proxies.length == 0, \"Init already called!\");\r\n        for(uint256 i = 0; i \u003c proxies.length; i++) {\r\n            if(proxies[i] != address(0)) {\r\n                _proxies.push(proxies[i]);\r\n                _isProxy[proxies[i]] = true;\r\n            }\r\n        }\r\n        if(currentProxy != address(0)) {\r\n            _proxy = currentProxy;\r\n            if(!_isProxy[currentProxy]) {\r\n                _proxies.push(currentProxy);\r\n                _isProxy[currentProxy] = true;\r\n            }\r\n        }\r\n    }\r\n\r\n    function proxy() public override view returns(address) {\r\n        return _proxy;\r\n    }\r\n\r\n    function setProxy() public override {\r\n        require(_proxy == address(0) || _proxy == msg.sender, _proxy != address(0) ? \"Proxy already set!\" : \"Only Proxy can toggle itself!\");\r\n        _proxy = _proxy == address(0) ?  msg.sender : address(0);\r\n        if(_proxy != address(0) \u0026\u0026 !_isProxy[_proxy]) {\r\n            _proxies.push(_proxy);\r\n            _isProxy[_proxy] = true;\r\n        }\r\n    }\r\n\r\n    function isProxy(address addr) public override view returns(bool) {\r\n        return _isProxy[addr];\r\n    }\r\n\r\n    function proxiesLength() public override view returns(uint256) {\r\n        return _proxies.length;\r\n    }\r\n\r\n    function proxies() public override view returns(address[] memory) {\r\n        return proxies(0, _proxies.length);\r\n    }\r\n\r\n    function proxies(uint256 start, uint256 offset) public override view returns(address[] memory out) {\r\n        require(start \u003c _proxies.length, \"Invalid start\");\r\n        uint256 length = offset \u003e _proxies.length ? _proxies.length : offset;\r\n        out = new address[](length);\r\n        length += start;\r\n        length = length \u003e _proxies.length ? _proxies.length : length;\r\n        uint256 pos = 0;\r\n        for(uint256 i = start; i \u003c length; i++) {\r\n            out[pos++] = _proxies[i];\r\n        }\r\n    }\r\n}"},"IDoubleProxy.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface IDoubleProxy {\r\n    function init(address[] calldata proxies, address currentProxy) external;\r\n    function proxy() external view returns(address);\r\n    function setProxy() external;\r\n    function isProxy(address) external view returns(bool);\r\n    function proxiesLength() external view returns(uint256);\r\n    function proxies(uint256 start, uint256 offset) external view returns(address[] memory);\r\n    function proxies() external view returns(address[] memory);\r\n}"}}

    File 5 of 6: MVDProxy
    {"ICommonUtilities.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface ICommonUtilities {\r\n    function toString(address _addr) external pure returns(string memory);\r\n    function toString(uint _i) external pure returns(string memory);\r\n    function toUint256(bytes calldata bs) external pure returns(uint256 x);\r\n    function toAddress(bytes calldata b) external pure returns (address addr);\r\n    function compareStrings(string calldata a, string calldata b) external pure returns(bool);\r\n    function getFirstJSONPart(address sourceLocation, uint256 sourceLocationId, address location) external pure returns(bytes memory);\r\n    function formatReturnAbiParametersArray(string calldata m) external pure returns(string memory);\r\n    function toLowerCase(string calldata str) external pure returns(string memory);\r\n}"},"IDoubleProxy.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface IDoubleProxy {\r\n    function init(address[] calldata proxies, address currentProxy) external;\r\n    function proxy() external view returns(address);\r\n    function setProxy() external;\r\n    function isProxy(address) external view returns(bool);\r\n    function proxiesLength() external view returns(uint256);\r\n    function proxies(uint256 start, uint256 offset) external view returns(address[] memory);\r\n    function proxies() external view returns(address[] memory);\r\n}"},"IERC20.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface IERC20 {\r\n    function totalSupply() external view returns (uint256);\r\n    function balanceOf(address account) external view returns (uint256);\r\n    function transfer(address recipient, uint256 amount) external returns (bool);\r\n    function allowance(address owner, address spender) external view returns (uint256);\r\n    function approve(address spender, uint256 amount) external returns (bool);\r\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\r\n\r\n    event Transfer(address indexed from, address indexed to, uint256 value);\r\n    event Approval(address indexed owner, address indexed spender, uint256 value);\r\n}"},"IERC721.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IERC721 {\n    function ownerOf(uint256 _tokenId) external view returns (address);\n    function transferFrom(address _from, address _to, uint256 _tokenId) external payable;\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n}"},"IERC721Receiver.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IERC721Receiver {\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\n}"},"IMVDFunctionalitiesManager.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDFunctionalitiesManager {\n\n    function getProxy() external view returns (address);\n    function setProxy() external;\n\n    function init(address sourceLocation,\n        uint256 getMinimumBlockNumberSourceLocationId, address getMinimumBlockNumberFunctionalityAddress,\n        uint256 getEmergencyMinimumBlockNumberSourceLocationId, address getEmergencyMinimumBlockNumberFunctionalityAddress,\n        uint256 getEmergencySurveyStakingSourceLocationId, address getEmergencySurveyStakingFunctionalityAddress,\n        uint256 checkVoteResultSourceLocationId, address checkVoteResultFunctionalityAddress) external;\n\n    function addFunctionality(string calldata codeName, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, bool needsSender) external;\n    function addFunctionality(string calldata codeName, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, bool needsSender, uint256 position) external;\n    function removeFunctionality(string calldata codeName) external returns(bool removed, uint256 position);\n    function isValidFunctionality(address functionality) external view returns(bool);\n    function isAuthorizedFunctionality(address functionality) external view returns(bool);\n    function setCallingContext(address location) external returns(bool);\n    function clearCallingContext() external;\n    function getFunctionalityData(string calldata codeName) external view returns(address, uint256, string memory, address, uint256);\n    function hasFunctionality(string calldata codeName) external view returns(bool);\n    function getFunctionalitiesAmount() external view returns(uint256);\n    function functionalitiesToJSON() external view returns(string memory);\n    function functionalitiesToJSON(uint256 start, uint256 l) external view returns(string memory functionsJSONArray);\n    function functionalityNames() external view returns(string memory);\n    function functionalityNames(uint256 start, uint256 l) external view returns(string memory functionsJSONArray);\n    function functionalityToJSON(string calldata codeName) external view returns(string memory);\n\n    function preConditionCheck(string calldata codeName, bytes calldata data, uint8 submitable, address sender, uint256 value) external view returns(address location, bytes memory payload);\n\n    function setupFunctionality(address proposalAddress) external returns (bool);\n}"},"IMVDFunctionalityModelsManager.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface IMVDFunctionalityModelsManager {\r\n    function init() external;\r\n    function checkWellKnownFunctionalities(string calldata codeName, bool submitable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, bool needsSender, string calldata replaces) external view;\r\n}"},"IMVDFunctionalityProposal.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDFunctionalityProposal {\n\n    function init(string calldata codeName, address location, string calldata methodSignature, string calldata returnAbiParametersArray, string calldata replaces, address proxy) external;\n    function setCollateralData(bool emergency, address sourceLocation, uint256 sourceLocationId, bool submitable, bool isInternal, bool needsSender, address proposer, uint256 votesHardCap) external;\n\n    function getProxy() external view returns(address);\n    function getCodeName() external view returns(string memory);\n    function isEmergency() external view returns(bool);\n    function getSourceLocation() external view returns(address);\n    function getSourceLocationId() external view returns(uint256);\n    function getLocation() external view returns(address);\n    function isSubmitable() external view returns(bool);\n    function getMethodSignature() external view returns(string memory);\n    function getReturnAbiParametersArray() external view returns(string memory);\n    function isInternal() external view returns(bool);\n    function needsSender() external view returns(bool);\n    function getReplaces() external view returns(string memory);\n    function getProposer() external view returns(address);\n    function getSurveyEndBlock() external view returns(uint256);\n    function getSurveyDuration() external view returns(uint256);\n    function isVotesHardCapReached() external view returns(bool);\n    function getVotesHardCapToReach() external view returns(uint256);\n    function toJSON() external view returns(string memory);\n    function getVote(address addr) external view returns(uint256 accept, uint256 refuse);\n    function getVotes() external view returns(uint256, uint256);\n    function start() external;\n    function disable() external;\n    function isDisabled() external view returns(bool);\n    function isTerminated() external view returns(bool);\n    function accept(uint256 amount) external;\n    function retireAccept(uint256 amount) external;\n    function moveToAccept(uint256 amount) external;\n    function refuse(uint256 amount) external;\n    function retireRefuse(uint256 amount) external;\n    function moveToRefuse(uint256 amount) external;\n    function retireAll() external;\n    function withdraw() external;\n    function terminate() external;\n    function set() external;\n\n    event Accept(address indexed voter, uint256 amount);\n    event RetireAccept(address indexed voter, uint256 amount);\n    event MoveToAccept(address indexed voter, uint256 amount);\n    event Refuse(address indexed voter, uint256 amount);\n    event RetireRefuse(address indexed voter, uint256 amount);\n    event MoveToRefuse(address indexed voter, uint256 amount);\n    event RetireAll(address indexed voter, uint256 amount);\n}"},"IMVDFunctionalityProposalManager.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDFunctionalityProposalManager {\n    function newProposal(string calldata codeName, address location, string calldata methodSignature, string calldata returnAbiParametersArray, string calldata replaces) external returns(address);\n    function checkProposal(address proposalAddress) external;\n    function getProxy() external view returns (address);\n    function setProxy() external;\n    function isValidProposal(address proposal) external view returns (bool);\n}"},"IMVDProxy.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDProxy {\n\n    function init(address votingTokenAddress, address functionalityProposalManagerAddress, address stateHolderAddress, address functionalityModelsManagerAddress, address functionalitiesManagerAddress, address walletAddress, address doubleProxyAddress) external;\n\n    function getDelegates() external view returns(address[] memory);\n    function getToken() external view returns(address);\n    function getMVDFunctionalityProposalManagerAddress() external view returns(address);\n    function getStateHolderAddress() external view returns(address);\n    function getMVDFunctionalityModelsManagerAddress() external view returns(address);\n    function getMVDFunctionalitiesManagerAddress() external view returns(address);\n    function getMVDWalletAddress() external view returns(address);\n    function getDoubleProxyAddress() external view returns(address);\n    function setDelegate(uint256 position, address newAddress) external returns(address oldAddress);\n    function changeProxy(address newAddress, bytes calldata initPayload) external;\n    function isValidProposal(address proposal) external view returns (bool);\n    function isAuthorizedFunctionality(address functionality) external view returns(bool);\n    function newProposal(string calldata codeName, bool emergency, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string calldata methodSignature, string calldata returnParametersJSONArray, bool isInternal, bool needsSender, string calldata replaces) external returns(address proposalAddress);\n    function startProposal(address proposalAddress) external;\n    function disableProposal(address proposalAddress) external;\n    function transfer(address receiver, uint256 value, address token) external;\n    function transfer721(address receiver, uint256 tokenId, bytes calldata data, bool safe, address token) external;\n    function flushToWallet(address tokenAddress, bool is721, uint256 tokenId) external;\n    function setProposal() external;\n    function read(string calldata codeName, bytes calldata data) external view returns(bytes memory returnData);\n    function submit(string calldata codeName, bytes calldata data) external payable returns(bytes memory returnData);\n    function callFromManager(address location, bytes calldata payload) external returns(bool, bytes memory);\n    function emitFromManager(string calldata codeName, address proposal, string calldata replaced, address replacedSourceLocation, uint256 replacedSourceLocationId, address location, bool submitable, string calldata methodSignature, bool isInternal, bool needsSender, address proposalAddress) external;\n\n    function emitEvent(string calldata eventSignature, bytes calldata firstIndex, bytes calldata secondIndex, bytes calldata data) external;\n\n    event ProxyChanged(address indexed newAddress);\n    event DelegateChanged(uint256 position, address indexed oldAddress, address indexed newAddress);\n\n    event Proposal(address proposal);\n    event ProposalCheck(address indexed proposal);\n    event ProposalSet(address indexed proposal, bool success);\n    event FunctionalitySet(string codeName, address indexed proposal, string replaced, address replacedSourceLocation, uint256 replacedSourceLocationId, address indexed replacedLocation, bool replacedWasSubmitable, string replacedMethodSignature, bool replacedWasInternal, bool replacedNeededSender, address indexed replacedProposal);\n\n    event Event(string indexed key, bytes32 indexed firstIndex, bytes32 indexed secondIndex, bytes data);\n}"},"IMVDWallet.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDWallet {\n\n    function getProxy() external view returns (address);\n\n    function setProxy() external;\n\n    function setNewWallet(address payable newWallet, address tokenAddress) external;\n\n    function transfer(address receiver, uint256 value, address tokenAddress) external;\n    \n    function transfer(address receiver, uint256 tokenId, bytes calldata data, bool safe, address token) external;\n\n    function flushToNewWallet(address token) external;\n\n    function flush721ToNewWallet(uint256 tokenId, bytes calldata data, bool safe, address tokenAddress) external;\n}"},"IStateHolder.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IStateHolder {\n\n    function init() external;\n\n    function getProxy() external view returns (address);\n    function setProxy() external;\n    function toJSON() external view returns(string memory);\n    function toJSON(uint256 start, uint256 l) external view returns(string memory);\n    function getStateSize() external view returns (uint256);\n    function exists(string calldata varName) external view returns(bool);\n    function getDataType(string calldata varName) external view returns(string memory dataType);\n    function clear(string calldata varName) external returns(string memory oldDataType, bytes memory oldVal);\n    function setBytes(string calldata varName, bytes calldata val) external returns(bytes memory);\n    function getBytes(string calldata varName) external view returns(bytes memory);\n    function setString(string calldata varName, string calldata val) external returns(string memory);\n    function getString(string calldata varName) external view returns (string memory);\n    function setBool(string calldata varName, bool val) external returns(bool);\n    function getBool(string calldata varName) external view returns (bool);\n    function getUint256(string calldata varName) external view returns (uint256);\n    function setUint256(string calldata varName, uint256 val) external returns(uint256);\n    function getAddress(string calldata varName) external view returns (address);\n    function setAddress(string calldata varName, address val) external returns (address);\n}"},"IVotingToken.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface IVotingToken {\r\n    function init(string calldata name, string calldata symbol, uint256 decimals, uint256 totalSupply) external;\r\n\r\n    function getProxy() external view returns (address);\r\n    function setProxy() external;\r\n\r\n    function name() external view returns(string memory);\r\n    function symbol() external view returns(string memory);\r\n    function decimals() external view returns(uint256);\r\n\r\n    function mint(uint256 amount) external;\r\n    function burn(uint256 amount) external;\r\n\r\n    function increaseAllowance(address spender, uint256 addedValue) external returns (bool);\r\n    function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);\r\n}"},"MVDProxy.sol":{"content":"pragma solidity ^0.6.0;\n\nimport \"./IMVDProxy.sol\";\nimport \"./IMVDFunctionalityProposalManager.sol\";\nimport \"./IMVDFunctionalityProposal.sol\";\nimport \"./IERC20.sol\";\nimport \"./IMVDFunctionalityModelsManager.sol\";\nimport \"./ICommonUtilities.sol\";\nimport \"./IMVDFunctionalitiesManager.sol\";\nimport \"./IMVDWallet.sol\";\nimport \"./IERC721.sol\";\n\ncontract MVDProxy is IMVDProxy {\n\n    address[] private _delegates;\n\n    constructor(address votingTokenAddress, address functionalityProposalManagerAddress, address stateHolderAddress, address functionalityModelsManagerAddress, address functionalitiesManagerAddress, address walletAddress, address doubleProxyAddress) public {\n        if(votingTokenAddress == address(0)) {\n            return;\n        }\n        init(votingTokenAddress, functionalityProposalManagerAddress, stateHolderAddress, functionalityModelsManagerAddress, functionalitiesManagerAddress, walletAddress, doubleProxyAddress);\n    }\n\n    function init(address votingTokenAddress, address functionalityProposalManagerAddress, address stateHolderAddress, address functionalityModelsManagerAddress, address functionalitiesManagerAddress, address walletAddress, address doubleProxyAddress) public override {\n\n        require(_delegates.length == 0, \"Init already called!\");\n\n        _delegates = new address[](7);\n\n        IMVDProxyDelegate(_delegates[0] = votingTokenAddress).setProxy();\n\n        IMVDProxyDelegate(_delegates[1] = functionalityProposalManagerAddress).setProxy();\n\n        IMVDProxyDelegate(_delegates[2] = stateHolderAddress).setProxy();\n\n        _delegates[3] = functionalityModelsManagerAddress;\n\n        IMVDProxyDelegate(_delegates[4] = functionalitiesManagerAddress).setProxy();\n\n        IMVDProxyDelegate(_delegates[5] = walletAddress).setProxy();\n\n        IMVDProxyDelegate(_delegates[6] = doubleProxyAddress).setProxy();\n    }\n\n    receive() external payable {\n        revert(\"No Eth Accepted\");\n    }\n\n    function getDelegates() public override view returns(address[] memory) {\n        return _delegates;\n    }\n\n    function getToken() public override view returns(address) {\n        return _delegates[0];\n    }\n\n    function getMVDFunctionalityProposalManagerAddress() public override view returns(address) {\n        return _delegates[1];\n    }\n\n    function getStateHolderAddress() public override view returns(address) {\n        return _delegates[2];\n    }\n\n    function getMVDFunctionalityModelsManagerAddress() public override view returns(address) {\n        return _delegates[3];\n    }\n\n    function getMVDFunctionalitiesManagerAddress() public override view returns(address) {\n        return _delegates[4];\n    }\n\n    function getMVDWalletAddress() public override view returns(address) {\n        return _delegates[5];\n    }\n\n    function getDoubleProxyAddress() public override view returns(address) {\n        return _delegates[6];\n    }\n\n    function flushToWallet(address tokenAddress, bool is721, uint256 tokenId) public override {\n        require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), \"Unauthorized action!\");\n        if(tokenAddress == address(0)) {\n            payable(_delegates[5]).transfer(payable(address(this)).balance);\n            return;\n        }\n        if(is721) {\n            IERC721(tokenAddress).transferFrom(address(this), _delegates[5], tokenId);\n            return;\n        }\n        IERC20 token = IERC20(tokenAddress);\n        token.transfer(_delegates[5], token.balanceOf(address(this)));\n    }\n\n    function setDelegate(uint256 position, address newAddress) public override returns(address oldAddress) {\n        require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), \"Unauthorized action!\");\n        require(newAddress != address(0), \"Cannot set void address!\");\n        if(position == 5) {\n            IMVDWallet(_delegates[5]).setNewWallet(payable(newAddress), _delegates[0]);\n        }\n        oldAddress = _delegates[position];\n        _delegates[position] = newAddress;\n        if(position != 3) {\n            IMVDProxyDelegate(oldAddress).setProxy();\n            IMVDProxyDelegate(newAddress).setProxy();\n        }\n        emit DelegateChanged(position, oldAddress, newAddress);\n    }\n\n    function changeProxy(address newAddress, bytes memory initPayload) public override {\n        require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), \"Unauthorized action!\");\n        require(newAddress != address(0), \"Cannot set void address!\");\n        for(uint256 i = 0; i \u003c _delegates.length; i++) {\n            if(i != 3) {\n                IMVDProxyDelegate(_delegates[i]).setProxy();\n            }\n        }\n        _delegates = new address[](0);\n        emit ProxyChanged(newAddress);\n        (bool response,) = newAddress.call(initPayload);\n        require(response, \"New Proxy initPayload failed!\");\n    }\n\n    function isValidProposal(address proposal) public override view returns (bool) {\n        return IMVDFunctionalityProposalManager(_delegates[1]).isValidProposal(proposal);\n    }\n\n    function isAuthorizedFunctionality(address functionality) public override view returns(bool) {\n        return IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(functionality);\n    }\n\n    function newProposal(string memory codeName, bool emergency, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string memory methodSignature, string memory returnAbiParametersArray, bool isInternal, bool needsSender, string memory replaces) public override returns(address proposalAddress) {\n        emergencyBehavior(emergency);\n\n        IMVDFunctionalityModelsManager(_delegates[3]).checkWellKnownFunctionalities(codeName, submitable, methodSignature, returnAbiParametersArray, isInternal, needsSender, replaces);\n\n        IMVDFunctionalitiesManager functionalitiesManager = IMVDFunctionalitiesManager(_delegates[4]);\n\n        IMVDFunctionalityProposal proposal = IMVDFunctionalityProposal(proposalAddress = IMVDFunctionalityProposalManager(_delegates[1]).newProposal(codeName, location, methodSignature, returnAbiParametersArray, replaces));\n        proposal.setCollateralData(emergency, sourceLocation, sourceLocationId, submitable, isInternal, needsSender, msg.sender, functionalitiesManager.hasFunctionality(\"getVotesHardCap\") ? toUint256(read(\"getVotesHardCap\", \"\")) : 0);\n\n        if(functionalitiesManager.hasFunctionality(\"onNewProposal\")) {\n            submit(\"onNewProposal\", abi.encode(proposalAddress));\n        }\n\n        if(!IMVDFunctionalitiesManager(_delegates[4]).hasFunctionality(\"startProposal\") || !IMVDFunctionalitiesManager(_delegates[4]).hasFunctionality(\"disableProposal\")) {\n            proposal.start();\n        }\n\n        emit Proposal(proposalAddress);\n    }\n\n    function emergencyBehavior(bool emergency) private {\n        if(!emergency) {\n            return;\n        }\n        (address loc, , string memory meth,,) = IMVDFunctionalitiesManager(_delegates[4]).getFunctionalityData(\"getEmergencySurveyStaking\");\n        (, bytes memory payload) = loc.staticcall(abi.encodeWithSignature(meth));\n        uint256 staking = toUint256(payload);\n        if(staking \u003e 0) {\n            IERC20(_delegates[0]).transferFrom(msg.sender, address(this), staking);\n        }\n    }\n\n    function startProposal(address proposalAddress) public override {\n        require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), \"Unauthorized action!\");\n        (address location,,,,) = IMVDFunctionalitiesManager(_delegates[4]).getFunctionalityData(\"startProposal\");\n        require(location == msg.sender, \"Only startProposal Functionality can enable a delayed proposal\");\n        require(IMVDFunctionalityProposalManager(_delegates[1]).isValidProposal(proposalAddress), \"Invalid Proposal Address!\");\n        IMVDFunctionalityProposal(proposalAddress).start();\n    }\n\n    function disableProposal(address proposalAddress) public override {\n        require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), \"Unauthorized action!\");\n        (address location,,,,) = IMVDFunctionalitiesManager(_delegates[4]).getFunctionalityData(\"disableProposal\");\n        require(location == msg.sender, \"Only disableProposal Functionality can disable a delayed proposal\");\n        IMVDFunctionalityProposal(proposalAddress).disable();\n    }\n\n    function transfer(address receiver, uint256 value, address token) public override {\n        require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), \"Only functionalities can transfer Proxy balances!\");\n        IMVDWallet(_delegates[5]).transfer(receiver, value, token);\n    }\n\n    function transfer721(address receiver, uint256 tokenId, bytes memory data, bool safe, address token) public override {\n        require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), \"Only functionalities can transfer Proxy balances!\");\n        IMVDWallet(_delegates[5]).transfer(receiver, tokenId, data, safe, token);\n    }\n\n    function setProposal() public override {\n\n        IMVDFunctionalityProposalManager(_delegates[1]).checkProposal(msg.sender);\n\n        emit ProposalCheck(msg.sender);\n\n        IMVDFunctionalitiesManager functionalitiesManager = IMVDFunctionalitiesManager(_delegates[4]);\n\n        (address addressToCall,,string memory methodSignature,,) = functionalitiesManager.getFunctionalityData(\"checkSurveyResult\");\n\n        (bool surveyResult, bytes memory response) = addressToCall.staticcall(abi.encodeWithSignature(methodSignature, msg.sender));\n\n        surveyResult = toUint256(response) \u003e 0;\n\n        bool collateralCallResult = true;\n        (addressToCall,,methodSignature,,) = functionalitiesManager.getFunctionalityData(\"proposalEnd\");\n        if(addressToCall != address(0)) {\n            functionalitiesManager.setCallingContext(addressToCall);\n            (collateralCallResult,) = addressToCall.call(abi.encodeWithSignature(methodSignature, msg.sender, surveyResult));\n            functionalitiesManager.clearCallingContext();\n        }\n\n        IMVDFunctionalityProposal proposal = IMVDFunctionalityProposal(msg.sender);\n\n        uint256 staking = 0;\n        address tokenAddress = _delegates[0];\n        address walletAddress = _delegates[5];\n\n        if(proposal.isEmergency()) {\n            (addressToCall,,methodSignature,,) = functionalitiesManager.getFunctionalityData(\"getEmergencySurveyStaking\");\n            (, response) = addressToCall.staticcall(abi.encodeWithSignature(methodSignature));\n            staking = toUint256(response);\n        }\n\n        if(!surveyResult) {\n            if(collateralCallResult) {\n                proposal.set();\n                emit ProposalSet(msg.sender, surveyResult);\n                if(staking \u003e 0) {\n                    IERC20(tokenAddress).transfer(walletAddress, staking);\n                }\n            }\n            return;\n        }\n\n        if(collateralCallResult) {\n            try functionalitiesManager.setupFunctionality(msg.sender) returns(bool managerResult) {\n                collateralCallResult = managerResult;\n            } catch {\n                collateralCallResult = false;\n            }\n        }\n\n        if(collateralCallResult) {\n            proposal.set();\n            emit ProposalSet(msg.sender, surveyResult);\n            if(staking \u003e 0) {\n                IERC20(tokenAddress).transfer(surveyResult ? proposal.getProposer() : walletAddress, staking);\n            }\n        }\n    }\n\n    function read(string memory codeName, bytes memory data) public override view returns(bytes memory returnData) {\n\n        (address location, bytes memory payload) = IMVDFunctionalitiesManager(_delegates[4]).preConditionCheck(codeName, data, 0, msg.sender, 0);\n\n        bool ok;\n        (ok, returnData) = location.staticcall(payload);\n\n        require(ok, \"Failed to read from functionality\");\n    }\n\n    function submit(string memory codeName, bytes memory data) public override payable returns(bytes memory returnData) {\n\n        if(msg.value \u003e 0) {\n            payable(_delegates[5]).transfer(msg.value);\n        }\n\n        IMVDFunctionalitiesManager manager = IMVDFunctionalitiesManager(_delegates[4]);\n        (address location, bytes memory payload) = manager.preConditionCheck(codeName, data, 1, msg.sender, msg.value);\n\n        bool changed = manager.setCallingContext(location);\n\n        bool ok;\n        (ok, returnData) = location.call(payload);\n\n        if(changed) {\n            manager.clearCallingContext();\n        }\n        require(ok, \"Failed to submit functionality\");\n    }\n\n    function callFromManager(address location, bytes memory payload) public override returns(bool, bytes memory) {\n        require(msg.sender == _delegates[4], \"Only Functionalities Manager can call this!\");\n        return location.call(payload);\n    }\n\n    function emitFromManager(string memory codeName, address proposal, string memory replaced, address replacedSourceLocation, uint256 replacedSourceLocationId, address location, bool submitable, string memory methodSignature, bool isInternal, bool needsSender, address proposalAddress) public override {\n        require(msg.sender == _delegates[4], \"Only Functionalities Manager can call this!\");\n        emit FunctionalitySet(codeName, proposal, replaced, replacedSourceLocation, replacedSourceLocationId, location, submitable, methodSignature, isInternal, needsSender, proposalAddress);\n    }\n\n    function emitEvent(string memory eventSignature, bytes memory firstIndex, bytes memory secondIndex, bytes memory data) public override {\n        require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), \"Only authorized functionalities can emit events!\");\n        emit Event(eventSignature, keccak256(firstIndex), keccak256(secondIndex), data);\n    }\n\n    function compareStrings(string memory a, string memory b) private pure returns(bool) {\n        return keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n\n    function toUint256(bytes memory bs) internal pure returns(uint256 x) {\n        if(bs.length \u003e= 32) {\n            assembly {\n                x := mload(add(bs, add(0x20, 0)))\n            }\n        }\n    }\n}\n\ninterface IMVDProxyDelegate {\n    function setProxy() external;\n}"}}

    File 6 of 6: UniswapV2Factory
    pragma solidity =0.5.16;
    
    interface IUniswapV2Factory {
        event PairCreated(address indexed token0, address indexed token1, address pair, uint);
    
        function feeTo() external view returns (address);
        function feeToSetter() external view returns (address);
    
        function getPair(address tokenA, address tokenB) external view returns (address pair);
        function allPairs(uint) external view returns (address pair);
        function allPairsLength() external view returns (uint);
    
        function createPair(address tokenA, address tokenB) external returns (address pair);
    
        function setFeeTo(address) external;
        function setFeeToSetter(address) external;
    }
    
    interface IUniswapV2Pair {
        event Approval(address indexed owner, address indexed spender, uint value);
        event Transfer(address indexed from, address indexed to, uint value);
    
        function name() external pure returns (string memory);
        function symbol() external pure returns (string memory);
        function decimals() external pure returns (uint8);
        function totalSupply() external view returns (uint);
        function balanceOf(address owner) external view returns (uint);
        function allowance(address owner, address spender) external view returns (uint);
    
        function approve(address spender, uint value) external returns (bool);
        function transfer(address to, uint value) external returns (bool);
        function transferFrom(address from, address to, uint value) external returns (bool);
    
        function DOMAIN_SEPARATOR() external view returns (bytes32);
        function PERMIT_TYPEHASH() external pure returns (bytes32);
        function nonces(address owner) external view returns (uint);
    
        function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
    
        event Mint(address indexed sender, uint amount0, uint amount1);
        event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
        event Swap(
            address indexed sender,
            uint amount0In,
            uint amount1In,
            uint amount0Out,
            uint amount1Out,
            address indexed to
        );
        event Sync(uint112 reserve0, uint112 reserve1);
    
        function MINIMUM_LIQUIDITY() external pure returns (uint);
        function factory() external view returns (address);
        function token0() external view returns (address);
        function token1() external view returns (address);
        function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
        function price0CumulativeLast() external view returns (uint);
        function price1CumulativeLast() external view returns (uint);
        function kLast() external view returns (uint);
    
        function mint(address to) external returns (uint liquidity);
        function burn(address to) external returns (uint amount0, uint amount1);
        function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
        function skim(address to) external;
        function sync() external;
    
        function initialize(address, address) external;
    }
    
    interface IUniswapV2ERC20 {
        event Approval(address indexed owner, address indexed spender, uint value);
        event Transfer(address indexed from, address indexed to, uint value);
    
        function name() external pure returns (string memory);
        function symbol() external pure returns (string memory);
        function decimals() external pure returns (uint8);
        function totalSupply() external view returns (uint);
        function balanceOf(address owner) external view returns (uint);
        function allowance(address owner, address spender) external view returns (uint);
    
        function approve(address spender, uint value) external returns (bool);
        function transfer(address to, uint value) external returns (bool);
        function transferFrom(address from, address to, uint value) external returns (bool);
    
        function DOMAIN_SEPARATOR() external view returns (bytes32);
        function PERMIT_TYPEHASH() external pure returns (bytes32);
        function nonces(address owner) external view returns (uint);
    
        function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
    }
    
    interface IERC20 {
        event Approval(address indexed owner, address indexed spender, uint value);
        event Transfer(address indexed from, address indexed to, uint value);
    
        function name() external view returns (string memory);
        function symbol() external view returns (string memory);
        function decimals() external view returns (uint8);
        function totalSupply() external view returns (uint);
        function balanceOf(address owner) external view returns (uint);
        function allowance(address owner, address spender) external view returns (uint);
    
        function approve(address spender, uint value) external returns (bool);
        function transfer(address to, uint value) external returns (bool);
        function transferFrom(address from, address to, uint value) external returns (bool);
    }
    
    interface IUniswapV2Callee {
        function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external;
    }
    
    contract UniswapV2ERC20 is IUniswapV2ERC20 {
        using SafeMath for uint;
    
        string public constant name = 'Uniswap V2';
        string public constant symbol = 'UNI-V2';
        uint8 public constant decimals = 18;
        uint  public totalSupply;
        mapping(address => uint) public balanceOf;
        mapping(address => mapping(address => uint)) public allowance;
    
        bytes32 public DOMAIN_SEPARATOR;
        // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
        bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
        mapping(address => uint) public nonces;
    
        event Approval(address indexed owner, address indexed spender, uint value);
        event Transfer(address indexed from, address indexed to, uint value);
    
        constructor() public {
            uint chainId;
            assembly {
                chainId := chainid
            }
            DOMAIN_SEPARATOR = keccak256(
                abi.encode(
                    keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
                    keccak256(bytes(name)),
                    keccak256(bytes('1')),
                    chainId,
                    address(this)
                )
            );
        }
    
        function _mint(address to, uint value) internal {
            totalSupply = totalSupply.add(value);
            balanceOf[to] = balanceOf[to].add(value);
            emit Transfer(address(0), to, value);
        }
    
        function _burn(address from, uint value) internal {
            balanceOf[from] = balanceOf[from].sub(value);
            totalSupply = totalSupply.sub(value);
            emit Transfer(from, address(0), value);
        }
    
        function _approve(address owner, address spender, uint value) private {
            allowance[owner][spender] = value;
            emit Approval(owner, spender, value);
        }
    
        function _transfer(address from, address to, uint value) private {
            balanceOf[from] = balanceOf[from].sub(value);
            balanceOf[to] = balanceOf[to].add(value);
            emit Transfer(from, to, value);
        }
    
        function approve(address spender, uint value) external returns (bool) {
            _approve(msg.sender, spender, value);
            return true;
        }
    
        function transfer(address to, uint value) external returns (bool) {
            _transfer(msg.sender, to, value);
            return true;
        }
    
        function transferFrom(address from, address to, uint value) external returns (bool) {
            if (allowance[from][msg.sender] != uint(-1)) {
                allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
            }
            _transfer(from, to, value);
            return true;
        }
    
        function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
            require(deadline >= block.timestamp, 'UniswapV2: EXPIRED');
            bytes32 digest = keccak256(
                abi.encodePacked(
                    '\x19\x01',
                    DOMAIN_SEPARATOR,
                    keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
                )
            );
            address recoveredAddress = ecrecover(digest, v, r, s);
            require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE');
            _approve(owner, spender, value);
        }
    }
    
    contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
        using SafeMath  for uint;
        using UQ112x112 for uint224;
    
        uint public constant MINIMUM_LIQUIDITY = 10**3;
        bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));
    
        address public factory;
        address public token0;
        address public token1;
    
        uint112 private reserve0;           // uses single storage slot, accessible via getReserves
        uint112 private reserve1;           // uses single storage slot, accessible via getReserves
        uint32  private blockTimestampLast; // uses single storage slot, accessible via getReserves
    
        uint public price0CumulativeLast;
        uint public price1CumulativeLast;
        uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event
    
        uint private unlocked = 1;
        modifier lock() {
            require(unlocked == 1, 'UniswapV2: LOCKED');
            unlocked = 0;
            _;
            unlocked = 1;
        }
    
        function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
            _reserve0 = reserve0;
            _reserve1 = reserve1;
            _blockTimestampLast = blockTimestampLast;
        }
    
        function _safeTransfer(address token, address to, uint value) private {
            (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
            require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED');
        }
    
        event Mint(address indexed sender, uint amount0, uint amount1);
        event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
        event Swap(
            address indexed sender,
            uint amount0In,
            uint amount1In,
            uint amount0Out,
            uint amount1Out,
            address indexed to
        );
        event Sync(uint112 reserve0, uint112 reserve1);
    
        constructor() public {
            factory = msg.sender;
        }
    
        // called once by the factory at time of deployment
        function initialize(address _token0, address _token1) external {
            require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check
            token0 = _token0;
            token1 = _token1;
        }
    
        // update reserves and, on the first call per block, price accumulators
        function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {
            require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'UniswapV2: OVERFLOW');
            uint32 blockTimestamp = uint32(block.timestamp % 2**32);
            uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
            if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
                // * never overflows, and + overflow is desired
                price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
                price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
            }
            reserve0 = uint112(balance0);
            reserve1 = uint112(balance1);
            blockTimestampLast = blockTimestamp;
            emit Sync(reserve0, reserve1);
        }
    
        // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k)
        function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) {
            address feeTo = IUniswapV2Factory(factory).feeTo();
            feeOn = feeTo != address(0);
            uint _kLast = kLast; // gas savings
            if (feeOn) {
                if (_kLast != 0) {
                    uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1));
                    uint rootKLast = Math.sqrt(_kLast);
                    if (rootK > rootKLast) {
                        uint numerator = totalSupply.mul(rootK.sub(rootKLast));
                        uint denominator = rootK.mul(5).add(rootKLast);
                        uint liquidity = numerator / denominator;
                        if (liquidity > 0) _mint(feeTo, liquidity);
                    }
                }
            } else if (_kLast != 0) {
                kLast = 0;
            }
        }
    
        // this low-level function should be called from a contract which performs important safety checks
        function mint(address to) external lock returns (uint liquidity) {
            (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
            uint balance0 = IERC20(token0).balanceOf(address(this));
            uint balance1 = IERC20(token1).balanceOf(address(this));
            uint amount0 = balance0.sub(_reserve0);
            uint amount1 = balance1.sub(_reserve1);
    
            bool feeOn = _mintFee(_reserve0, _reserve1);
            uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
            if (_totalSupply == 0) {
                liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);
               _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
            } else {
                liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1);
            }
            require(liquidity > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED');
            _mint(to, liquidity);
    
            _update(balance0, balance1, _reserve0, _reserve1);
            if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date
            emit Mint(msg.sender, amount0, amount1);
        }
    
        // this low-level function should be called from a contract which performs important safety checks
        function burn(address to) external lock returns (uint amount0, uint amount1) {
            (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
            address _token0 = token0;                                // gas savings
            address _token1 = token1;                                // gas savings
            uint balance0 = IERC20(_token0).balanceOf(address(this));
            uint balance1 = IERC20(_token1).balanceOf(address(this));
            uint liquidity = balanceOf[address(this)];
    
            bool feeOn = _mintFee(_reserve0, _reserve1);
            uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
            amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution
            amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution
            require(amount0 > 0 && amount1 > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED');
            _burn(address(this), liquidity);
            _safeTransfer(_token0, to, amount0);
            _safeTransfer(_token1, to, amount1);
            balance0 = IERC20(_token0).balanceOf(address(this));
            balance1 = IERC20(_token1).balanceOf(address(this));
    
            _update(balance0, balance1, _reserve0, _reserve1);
            if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date
            emit Burn(msg.sender, amount0, amount1, to);
        }
    
        // this low-level function should be called from a contract which performs important safety checks
        function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
            require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT');
            (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
            require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY');
    
            uint balance0;
            uint balance1;
            { // scope for _token{0,1}, avoids stack too deep errors
            address _token0 = token0;
            address _token1 = token1;
            require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO');
            if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
            if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
            if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data);
            balance0 = IERC20(_token0).balanceOf(address(this));
            balance1 = IERC20(_token1).balanceOf(address(this));
            }
            uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
            uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
            require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT');
            { // scope for reserve{0,1}Adjusted, avoids stack too deep errors
            uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));
            uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));
            require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K');
            }
    
            _update(balance0, balance1, _reserve0, _reserve1);
            emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
        }
    
        // force balances to match reserves
        function skim(address to) external lock {
            address _token0 = token0; // gas savings
            address _token1 = token1; // gas savings
            _safeTransfer(_token0, to, IERC20(_token0).balanceOf(address(this)).sub(reserve0));
            _safeTransfer(_token1, to, IERC20(_token1).balanceOf(address(this)).sub(reserve1));
        }
    
        // force reserves to match balances
        function sync() external lock {
            _update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1);
        }
    }
    
    contract UniswapV2Factory is IUniswapV2Factory {
        address public feeTo;
        address public feeToSetter;
    
        mapping(address => mapping(address => address)) public getPair;
        address[] public allPairs;
    
        event PairCreated(address indexed token0, address indexed token1, address pair, uint);
    
        constructor(address _feeToSetter) public {
            feeToSetter = _feeToSetter;
        }
    
        function allPairsLength() external view returns (uint) {
            return allPairs.length;
        }
    
        function createPair(address tokenA, address tokenB) external returns (address pair) {
            require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES');
            (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
            require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS');
            require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS'); // single check is sufficient
            bytes memory bytecode = type(UniswapV2Pair).creationCode;
            bytes32 salt = keccak256(abi.encodePacked(token0, token1));
            assembly {
                pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
            }
            IUniswapV2Pair(pair).initialize(token0, token1);
            getPair[token0][token1] = pair;
            getPair[token1][token0] = pair; // populate mapping in the reverse direction
            allPairs.push(pair);
            emit PairCreated(token0, token1, pair, allPairs.length);
        }
    
        function setFeeTo(address _feeTo) external {
            require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');
            feeTo = _feeTo;
        }
    
        function setFeeToSetter(address _feeToSetter) external {
            require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');
            feeToSetter = _feeToSetter;
        }
    }
    
    // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
    
    library SafeMath {
        function add(uint x, uint y) internal pure returns (uint z) {
            require((z = x + y) >= x, 'ds-math-add-overflow');
        }
    
        function sub(uint x, uint y) internal pure returns (uint z) {
            require((z = x - y) <= x, 'ds-math-sub-underflow');
        }
    
        function mul(uint x, uint y) internal pure returns (uint z) {
            require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
        }
    }
    
    // a library for performing various math operations
    
    library Math {
        function min(uint x, uint y) internal pure returns (uint z) {
            z = x < y ? x : y;
        }
    
        // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
        function sqrt(uint y) internal pure returns (uint z) {
            if (y > 3) {
                z = y;
                uint x = y / 2 + 1;
                while (x < z) {
                    z = x;
                    x = (y / x + x) / 2;
                }
            } else if (y != 0) {
                z = 1;
            }
        }
    }
    
    // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
    
    // range: [0, 2**112 - 1]
    // resolution: 1 / 2**112
    
    library UQ112x112 {
        uint224 constant Q112 = 2**112;
    
        // encode a uint112 as a UQ112x112
        function encode(uint112 y) internal pure returns (uint224 z) {
            z = uint224(y) * Q112; // never overflows
        }
    
        // divide a UQ112x112 by a uint112, returning a UQ112x112
        function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
            z = x / uint224(y);
        }
    }