@pollum-io/pegasys-protocol
Version:
Contracts for the Pegasys Dex.
233 lines • 2.35 MB
JSON
{
"id": "185e9fcd8c84b866df3540a5cdfa590e",
"_format": "hh-sol-build-info-1",
"solcVersion": "0.6.12",
"solcLongVersion": "0.6.12+commit.27d51765",
"input": {
"language": "Solidity",
"sources": {
"contracts/earn/FeeCollector.sol": {
"content": "// SPDX-License-Identifier: MIT\n\n// P1 - P3: OK\npragma solidity 0.6.12;\n\nimport \"./libraries/SafeERC20.sol\";\n\nimport \"../pegasys-periphery/libraries/PegasysLibrary.sol\";\nimport \"../pegasys-core/interfaces/IPegasysPair.sol\";\nimport \"../pegasys-core/interfaces/IPegasysFactory.sol\";\n\nimport \"openzeppelin-contracts-legacy/access/Ownable.sol\";\nimport \"openzeppelin-contracts-legacy/utils/EnumerableSet.sol\";\n\n/// @title Fee Collector\n/// @author Trader Joe & Pegasys\n/// @notice FeeCollector receives 0.05% of the swaps done on Pegasys in the form of an LP. It swaps those LPs\n/// to a token of choice and sends it to the PegasysStaking\ncontract FeeCollector is Ownable {\n using EnumerableSet for EnumerableSet.AddressSet;\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n IPegasysFactory public immutable factory;\n\n address public immutable pegasysStaking;\n address private immutable wsys;\n /// @notice Any ERC20\n address public tokenTo;\n /// @notice In basis points aka parts per 10,000 so 5000 is 50%, cap of 50%, default is 0\n uint256 public devCut = 0;\n address public devAddr;\n\n // @notice Set of addresses that can perform certain functions\n EnumerableSet.AddressSet private _isAuth;\n\n modifier onlyAuth() {\n require(_isAuth.contains(_msgSender()), \"MoneyMaker: FORBIDDEN\");\n _;\n }\n\n /// @dev Maps a token `token` to another token `bridge` so that it uses `token/bridge` pair to convert token\n mapping(address => address) internal _bridges;\n\n event AddAuthorizedAddress(address indexed _addr);\n event RemoveAuthorizedAddress(address indexed _addr);\n event SetDevAddr(address _addr);\n event SetDevCut(uint256 _amount);\n event SetTokenTo(address _tokenTo);\n event LogBridgeSet(\n address indexed token,\n address indexed oldBridge,\n address indexed bridge\n );\n event LogConvert(\n address indexed server,\n address indexed token0,\n address indexed token1,\n uint256 amount0,\n uint256 amount1,\n uint256 amountTOKEN\n );\n\n /// @notice Constructor\n /// @param _factory The address of PegasysFactory\n /// @param _pegasysStaking The address of pegasysStaking\n /// @param _tokenTo The address of the token we want to convert to\n /// @param _wsys The address of wsys\n constructor(\n address _factory,\n address _pegasysStaking,\n address _tokenTo,\n address _wsys\n ) public {\n require(\n _factory != address(0),\n \"FeeCollector: factory can't be address(0)\"\n );\n require(\n _pegasysStaking != address(0),\n \"FeeCollector: pegasysStaking can't be address(0)\"\n );\n require(\n _tokenTo != address(0),\n \"FeeCollector: token can't be address(0)\"\n );\n require(_wsys != address(0), \"FeeCollector: wsys can't be address(0)\");\n factory = IPegasysFactory(_factory);\n pegasysStaking = _pegasysStaking;\n tokenTo = _tokenTo;\n wsys = _wsys;\n devAddr = _msgSender();\n _isAuth.add(_msgSender());\n }\n\n /// @notice Adds a user to the authorized addresses\n /// @param _auth The address to add\n function addAuth(address _auth) external onlyOwner {\n require(\n _isAuth.add(_auth),\n \"MoneyMaker: Address is already authorized\"\n );\n emit AddAuthorizedAddress(_auth);\n }\n\n /// @notice Remove a user of authorized addresses\n /// @param _auth The address to remove\n function removeAuth(address _auth) external onlyOwner {\n require(_isAuth.remove(_auth), \"MoneyMaker: Address is not authorized\");\n emit RemoveAuthorizedAddress(_auth);\n }\n\n /// @notice Return the list of authorized addresses\n /// @param index Index of the returned address\n /// @return The authorized address at `index`\n function getAuth(uint256 index) external view returns (address) {\n return _isAuth.at(index);\n }\n\n /// @notice Return the length of authorized addresses\n /// @return The number of authorized addresses\n function lenAuth() external view returns (uint256) {\n return _isAuth.length();\n }\n\n /// @notice Force using `pair/bridge` pair to convert `token`\n /// @param token The address of the tokenFrom\n /// @param bridge The address of the tokenTo\n function setBridge(address token, address bridge) external onlyAuth {\n // Checks\n require(\n token != tokenTo && token != wsys && token != bridge,\n \"MoneyMaker: Invalid bridge\"\n );\n\n // Effects\n address oldBridge = _bridges[token];\n _bridges[token] = bridge;\n emit LogBridgeSet(token, oldBridge, bridge);\n }\n\n /// @notice Sets dev cut, which will be sent to `devAddr`, can't be greater than 50%\n /// @param _amount The new devCut value\n function setDevCut(uint256 _amount) external onlyOwner {\n require(_amount <= 5000, \"setDevCut: cut too high\");\n devCut = _amount;\n\n emit SetDevCut(_amount);\n }\n\n /// @notice Sets `devAddr`, the address that will receive the `devCut`\n /// @param _addr The new dev address\n function setDevAddr(address _addr) external onlyOwner {\n require(\n _addr != address(0),\n \"setDevAddr, address cannot be zero address\"\n );\n devAddr = _addr;\n\n emit SetDevAddr(_addr);\n }\n\n /// @notice Sets token that we're buying back\n /// @param _tokenTo The new token address\n function setTokenToAddress(address _tokenTo) external onlyOwner {\n require(\n _tokenTo != address(0),\n \"setTokenToAddress, address cannot be zero address\"\n );\n tokenTo = _tokenTo;\n\n emit SetTokenTo(_tokenTo);\n }\n\n /// @notice Returns the `bridge` of a `token`\n /// @param token The tokenFrom address\n /// @return bridge The tokenTo address\n function bridgeFor(address token) public view returns (address bridge) {\n bridge = _bridges[token];\n if (bridge == address(0)) {\n bridge = wsys;\n }\n }\n\n // C6: It's not a fool proof solution, but it prevents flash loans, so here it's ok to use tx.origin\n modifier onlyEOA() {\n // Try to make flash-loan exploit harder to do by only allowing externally owned addresses.\n require(_msgSender() == tx.origin, \"MoneyMaker: must use EOA\");\n _;\n }\n\n /// @notice Converts a pair of tokens to tokenTo\n /// @dev _convert is separate to save gas by only checking the 'onlyEOA' modifier once in case of convertMultiple\n /// @param token0 The address of the first token of the pair that will be converted\n /// @param token1 The address of the second token of the pair that will be converted\n /// @param slippage The accepted slippage, in basis points aka parts per 10,000 so 5000 is 50%\n function convert(\n address token0,\n address token1,\n uint256 slippage\n ) external onlyEOA onlyAuth {\n require(\n slippage < 5_000,\n \"MoneyMaker: slippage needs to be lower than 50%\"\n );\n _convert(token0, token1, slippage);\n }\n\n /// @notice Converts a list of pairs of tokens to tokenTo\n /// @dev _convert is separate to save gas by only checking the 'onlyEOA' modifier once in case of convertMultiple\n /// @param token0 The list of addresses of the first token of the pairs that will be converted\n /// @param token1 The list of addresses of the second token of the pairs that will be converted\n /// @param slippage The accepted slippage, in basis points aka parts per 10,000 so 5000 is 50%\n function convertMultiple(\n address[] calldata token0,\n address[] calldata token1,\n uint256 slippage\n ) external onlyEOA onlyAuth {\n // TODO: This can be optimized a fair bit, but this is safer and simpler for now\n require(\n slippage < 5_000,\n \"MoneyMaker: slippage needs to be lower than 50%\"\n );\n require(\n token0.length == token1.length,\n \"MoneyMaker: arrays length don't match\"\n );\n\n uint256 len = token0.length;\n for (uint256 i = 0; i < len; i++) {\n _convert(token0[i], token1[i], slippage);\n }\n }\n\n /// @notice Converts a pair of tokens to tokenTo\n /// @dev _convert is separate to save gas by only checking the 'onlyEOA' modifier once in case of convertMultiple\n /// @param token0 The address of the first token of the pair that is currently being converted\n /// @param token1 The address of the second token of the pair that is currently being converted\n /// @param slippage The accepted slippage, in basis points aka parts per 10,000 so 5000 is 50%\n function _convert(\n address token0,\n address token1,\n uint256 slippage\n ) internal {\n uint256 amount0;\n uint256 amount1;\n\n // handle case where non-LP tokens need to be converted\n if (token0 == token1) {\n amount0 = IERC20(token0).balanceOf(address(this));\n amount1 = 0;\n } else {\n IPegasysPair pair = IPegasysPair(factory.getPair(token0, token1));\n require(address(pair) != address(0), \"MoneyMaker: Invalid pair\");\n\n IERC20(address(pair)).safeTransfer(\n address(pair),\n pair.balanceOf(address(this))\n );\n\n // take balance of tokens in this contract before burning the pair, incase there are already some here\n uint256 tok0bal = IERC20(token0).balanceOf(address(this));\n uint256 tok1bal = IERC20(token1).balanceOf(address(this));\n\n pair.burn(address(this));\n\n // subtract old balance of tokens from new balance\n // the return values of pair.burn cant be trusted due to transfer tax tokens\n amount0 = IERC20(token0).balanceOf(address(this)).sub(tok0bal);\n amount1 = IERC20(token1).balanceOf(address(this)).sub(tok1bal);\n }\n emit LogConvert(\n _msgSender(),\n token0,\n token1,\n amount0,\n amount1,\n _convertStep(token0, token1, amount0, amount1, slippage)\n );\n }\n\n /// @notice Used to convert two tokens to `tokenTo`, step by step, called recursively\n /// @param token0 The address of the first token\n /// @param token1 The address of the second token\n /// @param amount0 The amount of the `token0`\n /// @param amount1 The amount of the `token1`\n /// @param slippage The accepted slippage, in basis points aka parts per 10,000 so 5000 is 50%\n /// @return tokenOut The amount of token\n function _convertStep(\n address token0,\n address token1,\n uint256 amount0,\n uint256 amount1,\n uint256 slippage\n ) internal returns (uint256 tokenOut) {\n // Interactions\n if (token0 == token1) {\n uint256 amount = amount0.add(amount1);\n if (token0 == tokenTo) {\n IERC20(tokenTo).safeTransfer(pegasysStaking, amount);\n tokenOut = amount;\n } else if (token0 == wsys) {\n tokenOut = _toToken(wsys, amount, slippage);\n } else {\n address bridge = bridgeFor(token0);\n amount = _swap(token0, bridge, amount, address(this), slippage);\n tokenOut = _convertStep(bridge, bridge, amount, 0, slippage);\n }\n } else if (token0 == tokenTo) {\n // eg. TOKEN - SYS\n IERC20(tokenTo).safeTransfer(pegasysStaking, amount0);\n tokenOut = _toToken(token1, amount1, slippage).add(amount0);\n } else if (token1 == tokenTo) {\n // eg. USDT - SYS\n IERC20(tokenTo).safeTransfer(pegasysStaking, amount1);\n tokenOut = _toToken(token0, amount0, slippage).add(amount1);\n } else if (token0 == wsys) {\n // eg. SYS - USDC\n tokenOut = _toToken(\n wsys,\n _swap(token1, wsys, amount1, address(this), slippage).add(\n amount0\n ),\n slippage\n );\n } else if (token1 == wsys) {\n // eg. USDT - SYS\n tokenOut = _toToken(\n wsys,\n _swap(token0, wsys, amount0, address(this), slippage).add(\n amount1\n ),\n slippage\n );\n } else {\n // eg. MIC - USDT\n address bridge0 = bridgeFor(token0);\n address bridge1 = bridgeFor(token1);\n if (bridge0 == token1) {\n // eg. MIC - USDT - and bridgeFor(MIC) = USDT\n tokenOut = _convertStep(\n bridge0,\n token1,\n _swap(token0, bridge0, amount0, address(this), slippage),\n amount1,\n slippage\n );\n } else if (bridge1 == token0) {\n // eg. WBTC - DSD - and bridgeFor(DSD) = WBTC\n tokenOut = _convertStep(\n token0,\n bridge1,\n amount0,\n _swap(token1, bridge1, amount1, address(this), slippage),\n slippage\n );\n } else {\n tokenOut = _convertStep(\n bridge0,\n bridge1, // eg. USDT - DSD - and bridgeFor(DSD) = WBTC\n _swap(token0, bridge0, amount0, address(this), slippage),\n _swap(token1, bridge1, amount1, address(this), slippage),\n slippage\n );\n }\n }\n }\n\n /// @notice Swaps `amountIn` `fromToken` to `toToken` and sends it to `to`, `amountOut` is required to be greater\n /// than allowed `slippage`\n /// @param fromToken The address of token that will be swapped\n /// @param toToken The address of the token that will be received\n /// @param amountIn The amount of the `fromToken`\n /// @param to The address that will receive the `toToken`\n /// @param slippage The accepted slippage, in basis points aka parts per 10,000 so 5000 is 50%\n /// @return amountOut The amount of `toToken` sent to `to`\n function _swap(\n address fromToken,\n address toToken,\n uint256 amountIn,\n address to,\n uint256 slippage\n ) internal returns (uint256 amountOut) {\n // Checks\n // X1 - X5: OK\n IPegasysPair pair = IPegasysPair(factory.getPair(fromToken, toToken));\n require(address(pair) != address(0), \"MoneyMaker: Cannot convert\");\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n (uint256 reserveInput, uint256 reserveOutput) = fromToken ==\n pair.token0()\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n IERC20(fromToken).safeTransfer(address(pair), amountIn);\n uint256 amountInput = IERC20(fromToken).balanceOf(address(pair)).sub(\n reserveInput\n ); // calculate amount that was transferred, this accounts for transfer taxes\n\n amountOut = PegasysLibrary.getAmountOut(\n amountInput,\n reserveInput,\n reserveOutput\n );\n\n {\n uint256 rest = uint256(10_000).sub(slippage);\n /// @dev We simulate the amount received if we did a swapIn and swapOut without updating the reserves,\n /// hence why we do rest^2, i.e. calculating the slippage twice cause we actually do two swaps.\n /// This allows us to catch if a pair has low liquidity\n require(\n PegasysLibrary.getAmountOut(\n amountOut,\n reserveOutput,\n reserveInput\n ) >= amountInput.mul(rest).mul(rest).div(100_000_000),\n \"MoneyMaker: Slippage caught\"\n );\n }\n\n (uint256 amount0Out, uint256 amount1Out) = fromToken == pair.token0()\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n pair.swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Swaps an amount of token to another token, `tokenTo`\n /// @dev `amountOut` is required to be greater after slippage\n /// @param token The address of token that will be swapped\n /// @param amountIn The amount of the `token`\n /// @param slippage The accepted slippage, in basis points aka parts per 10,000 so 5000 is 50%\n /// @return amountOut The amount of `toToken` sent to PegasysStaking\n function _toToken(\n address token,\n uint256 amountIn,\n uint256 slippage\n ) internal returns (uint256 amountOut) {\n uint256 amount = amountIn;\n if (devCut > 0) {\n amount = amount.mul(devCut).div(10000);\n IERC20(token).safeTransfer(devAddr, amount);\n amount = amountIn.sub(amount);\n }\n amountOut = _swap(token, tokenTo, amount, pegasysStaking, slippage);\n }\n}\n"
},
"contracts/earn/libraries/SafeERC20.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"./IERC20.sol\";\n\nlibrary SafeERC20 {\n function safeSymbol(IERC20 token) internal view returns (string memory) {\n (bool success, bytes memory data) = address(token).staticcall(\n abi.encodeWithSelector(0x95d89b41)\n );\n return success && data.length > 0 ? abi.decode(data, (string)) : \"???\";\n }\n\n function safeName(IERC20 token) internal view returns (string memory) {\n (bool success, bytes memory data) = address(token).staticcall(\n abi.encodeWithSelector(0x06fdde03)\n );\n return success && data.length > 0 ? abi.decode(data, (string)) : \"???\";\n }\n\n function safeDecimals(IERC20 token) internal view returns (uint8) {\n (bool success, bytes memory data) = address(token).staticcall(\n abi.encodeWithSelector(0x313ce567)\n );\n return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;\n }\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 amount\n ) internal {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(0xa9059cbb, to, amount)\n );\n require(\n success && (data.length == 0 || abi.decode(data, (bool))),\n \"SafeERC20: Transfer failed\"\n );\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n uint256 amount\n ) internal {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(0x23b872dd, from, address(this), amount)\n );\n require(\n success && (data.length == 0 || abi.decode(data, (bool))),\n \"SafeERC20: TransferFrom failed\"\n );\n }\n}\n"
},
"contracts/pegasys-periphery/libraries/PegasysLibrary.sol": {
"content": "// SPDX-License-Identifier: GNU\npragma solidity >=0.5.0;\n\nimport \"../../pegasys-core/interfaces/IPegasysFactory.sol\";\nimport \"../../pegasys-core/interfaces/IPegasysPair.sol\";\n\nimport \"./SafeMath.sol\";\n\nlibrary PegasysLibrary {\n using SafeMath for uint256;\n\n // returns sorted token addresses, used to handle return values from pairs sorted in this order\n function sortTokens(address tokenA, address tokenB)\n internal\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"PegasysLibrary: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"PegasysLibrary: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address factory,\n address tokenA,\n address tokenB\n ) internal pure returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1)),\n hex\"85c9b07c539b322c33da730d88df8396983c35a411da73d3d6c2278474890833\" // init code hash\n )\n )\n )\n );\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address factory,\n address tokenA,\n address tokenB\n ) internal view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPegasysPair(\n pairFor(factory, tokenA, tokenB)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quote(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"PegasysLibrary: INSUFFICIENT_AMOUNT\");\n require(\n reserveA > 0 && reserveB > 0,\n \"PegasysLibrary: INSUFFICIENT_LIQUIDITY\"\n );\n amountB = amountA.mul(reserveB) / reserveA;\n }\n\n // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n require(amountIn > 0, \"PegasysLibrary: INSUFFICIENT_INPUT_AMOUNT\");\n require(\n reserveIn > 0 && reserveOut > 0,\n \"PegasysLibrary: INSUFFICIENT_LIQUIDITY\"\n );\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n require(amountOut > 0, \"PegasysLibrary: INSUFFICIENT_OUTPUT_AMOUNT\");\n require(\n reserveIn > 0 && reserveOut > 0,\n \"PegasysLibrary: INSUFFICIENT_LIQUIDITY\"\n );\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(\n address factory,\n uint256 amountIn,\n address[] memory path\n ) internal view returns (uint256[] memory amounts) {\n require(path.length >= 2, \"PegasysLibrary: INVALID_PATH\");\n amounts = new uint256[](path.length);\n amounts[0] = amountIn;\n for (uint256 i; i < path.length - 1; i++) {\n (uint256 reserveIn, uint256 reserveOut) = getReserves(\n factory,\n path[i],\n path[i + 1]\n );\n amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);\n }\n }\n\n // performs chained getAmountIn calculations on any number of pairs\n function getAmountsIn(\n address factory,\n uint256 amountOut,\n address[] memory path\n ) internal view returns (uint256[] memory amounts) {\n require(path.length >= 2, \"PegasysLibrary: INVALID_PATH\");\n amounts = new uint256[](path.length);\n amounts[amounts.length - 1] = amountOut;\n for (uint256 i = path.length - 1; i > 0; i--) {\n (uint256 reserveIn, uint256 reserveOut) = getReserves(\n factory,\n path[i - 1],\n path[i]\n );\n amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);\n }\n }\n}\n"
},
"contracts/pegasys-core/interfaces/IPegasysPair.sol": {
"content": "// SPDX-License-Identifier: GNU\npragma solidity >=0.5.0;\n\ninterface IPegasysPair {\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n function name() external pure returns (string memory);\n\n function symbol() external pure returns (string memory);\n\n function decimals() external pure 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)\n external\n view\n 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 function DOMAIN_SEPARATOR() external view returns (bytes32);\n\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n\n function nonces(address owner) external view returns (uint256);\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\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\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 function MINIMUM_LIQUIDITY() external pure returns (uint256);\n\n function factory() external view returns (address);\n\n function token0() external view returns (address);\n\n function token1() external view returns (address);\n\n function getReserves()\n external\n view\n returns (\n uint112 reserve0,\n uint112 reserve1,\n uint32 blockTimestampLast\n );\n\n function price0CumulativeLast() external view returns (uint256);\n\n function price1CumulativeLast() external view returns (uint256);\n\n function kLast() external view returns (uint256);\n\n function mint(address to) external returns (uint256 liquidity);\n\n function burn(address to)\n external\n returns (uint256 amount0, uint256 amount1);\n\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external;\n\n function skim(address to) external;\n\n function sync() external;\n\n function initialize(address, address) external;\n}\n"
},
"contracts/pegasys-core/interfaces/IPegasysFactory.sol": {
"content": "// SPDX-License-Identifier: GNU\npragma solidity >=0.5.0;\n\ninterface IPegasysFactory {\n event PairCreated(\n address indexed token0,\n address indexed token1,\n address pair,\n uint256\n );\n\n function feeTo() external view returns (address);\n\n function feeToSetter() external view returns (address);\n\n function getPair(address tokenA, address tokenB)\n external\n view\n 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)\n external\n returns (address pair);\n\n function setFeeTo(address) external;\n\n function setFeeToSetter(address) external;\n}\n"
},
"openzeppelin-contracts-legacy/access/Ownable.sol": {
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../GSN/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n"
},
"openzeppelin-contracts-legacy/utils/EnumerableSet.sol": {
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(value)));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(value)));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(value)));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint256(_at(set._inner, index)));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n"
},
"contracts/earn/libraries/IERC20.sol": {
"content": "// SPDX-License-Identifier: GNU\npragma solidity >=0.5.0;\n\ninterface IERC20 {\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\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)\n external\n view\n 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/pegasys-periphery/libraries/SafeMath.sol": {
"content": "// SPDX-License-Identifier: GNU\npragma solidity >=0.6.6 <0.8.0;\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 function div(uint256 a, uint256 b) internal pure returns (uint256 c) {\n require(b > 0, \"SafeMath: Div by Zero\");\n c = a / b;\n }\n}\n"
},
"openzeppelin-contracts-legacy/GSN/Context.sol": {
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n"
}
},
"settings": {
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"output": {
"contracts": {
"contracts/earn/FeeCollector.sol": {
"FeeCollector": {
"abi": [
{
"inputs": [
{
"internalType": "address",
"name": "_factory",
"type": "address"
},
{
"internalType": "address",
"name": "_pegasysStaking",
"type": "address"
},
{
"internalType": "address",
"name": "_tokenTo",
"type": "address"
},
{
"internalType": "address",
"name": "_wsys",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "_addr",
"type": "address"
}
],
"name": "AddAuthorizedAddress",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "token",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "oldBridge",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "bridge",
"type": "address"
}
],
"name": "LogBridgeSet",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "server",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "token0",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "token1",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount0",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount1",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amountTOKEN",
"type": "uint256"
}
],
"name": "LogConvert",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "_addr",
"type": "address"
}
],
"name": "RemoveAuthorizedAddress",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "_addr",
"type": "address"
}
],
"name": "SetDevAddr",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
}
],
"name": "SetDevCut",
"type": "event"
},
{
"anonymous": false,
"i