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