diff --git a/brownie-config.yml b/brownie-config.yml index 8192755..c515d0f 100644 --- a/brownie-config.yml +++ b/brownie-config.yml @@ -23,3 +23,7 @@ reports: - IERC20 - ReentrancyGuard - Address + + +hypothesis: + max_examples: 1000 \ No newline at end of file diff --git a/contracts/AuraBribesProcessor.sol b/contracts/AuraBribesProcessor.sol index 0a556b8..c7c1024 100644 --- a/contracts/AuraBribesProcessor.sol +++ b/contracts/AuraBribesProcessor.sol @@ -162,7 +162,6 @@ contract AuraBribesProcessor is CowSwapSeller { /// @dev /// Step 3 Emit the Aura /// Takes all the Aura, takes fee, locks and emits it - // TODO: REDO MATH to handle case of AURA / graviAURA already in this contract function swapAURATobveAURAAndEmit() external nonReentrant { // Will take all the Aura left, // swap it for bveAura if cheaper, or deposit it directly diff --git a/contracts/OnChainPricingMainnet.sol b/contracts/OnChainPricingMainnet.sol index 6ea2cea..c8cd730 100644 --- a/contracts/OnChainPricingMainnet.sol +++ b/contracts/OnChainPricingMainnet.sol @@ -106,8 +106,12 @@ contract OnChainPricingMainnet { bytes32 public constant BALANCERV2_AURABAL_BALWETH_POOLID = 0x3dd0843a028c86e0b760b1a76929d1c5ef93a2dd000200000000000000000249; address public constant GRAVIAURA = 0xBA485b556399123261a5F9c95d413B4f93107407; + address public constant DIGG = 0x798D1bE841a82a273720CE31c822C61a67a601C3; bytes32 public constant BALANCERV2_AURABAL_GRAVIAURA_WETH_POOLID = 0x0578292cb20a443ba1cde459c985ce14ca2bdee5000100000000000000000269; - bytes32 public constant BALANCERV2_DAI_USDC_USDT_POOLID = 0x06df3b2bbb68adc8b0e302443692037ed9f91b42000000000000000000000063;// Not used due to possible migration: https://forum.balancer.fi/t/vulnerability-disclosure/3179 + bytes32 public constant BALANCER_V2_WBTC_DIGG_GRAVIAURA_POOLID = 0x8eb6c82c3081bbbd45dcac5afa631aac53478b7c000100000000000000000270; + + // NOTE: Not used due to possible migration: https://forum.balancer.fi/t/vulnerability-disclosure/3179 + bytes32 public constant BALANCERV2_DAI_USDC_USDT_POOLID = 0x06df3b2bbb68adc8b0e302443692037ed9f91b42000000000000000000000063; address public constant AURABAL = 0x616e8BfA43F920657B3497DBf40D6b1A02D4608d; address public constant BALWETHBPT = 0x5c6Ee304399DBdB9C8Ef030aB642B10820DB8F56; @@ -374,7 +378,11 @@ contract OnChainPricingMainnet { } UniV3SortPoolQuery memory _sortQuery = UniV3SortPoolQuery(_pool, token0, token1, _fee, amountIn, token0Price); - return IUniswapV3Simulator(uniV3Simulator).checkInRangeLiquidity(_sortQuery); + try IUniswapV3Simulator(uniV3Simulator).checkInRangeLiquidity(_sortQuery) returns (bool _crossTicks, uint256 _inRangeSimOut){ + return (_crossTicks, _inRangeSimOut); + } catch { + return (false, 0); + } } } @@ -426,7 +434,11 @@ contract OnChainPricingMainnet { /// @dev simulate Uniswap V3 swap using its tick-based math for given parameters /// @dev check helper UniV3SwapSimulator for more function simulateUniV3Swap(address token0, uint256 amountIn, address token1, uint24 _fee, bool token0Price, address _pool) public view returns (uint256) { - return IUniswapV3Simulator(uniV3Simulator).simulateUniV3Swap(_pool, token0, token1, token0Price, _fee, amountIn); + try IUniswapV3Simulator(uniV3Simulator).simulateUniV3Swap(_pool, token0, token1, token0Price, _fee, amountIn) returns (uint256 _simOut) { + return _simOut; + } catch { + return 0; + } } /// @dev Given the address of the input token & amount & the output token @@ -516,15 +528,26 @@ contract OnChainPricingMainnet { // stable pool math { ExactInStableQueryParam memory _stableQuery = ExactInStableQueryParam(tokens, balances, currentAmp, _inTokenIdx, _outTokenIdx, amountIn, IBalancerV2StablePool(_pool).getSwapFeePercentage()); - _quote = IBalancerV2Simulator(balancerV2Simulator).calcOutGivenInForStable(_stableQuery); + + try IBalancerV2Simulator(balancerV2Simulator).calcOutGivenInForStable(_stableQuery) returns (uint256 balQuote) { + _quote = balQuote; + } catch { + _quote = 0; + } + } - } catch (bytes memory) { + } catch { // weighted pool math { uint256[] memory _weights = IBalancerV2WeightedPool(_pool).getNormalizedWeights(); require(_weights.length == tokens.length, "!lenBAL"); ExactInQueryParam memory _query = ExactInQueryParam(tokenIn, tokenOut, balances[_inTokenIdx], _weights[_inTokenIdx], balances[_outTokenIdx], _weights[_outTokenIdx], amountIn, IBalancerV2WeightedPool(_pool).getSwapFeePercentage()); - _quote = IBalancerV2Simulator(balancerV2Simulator).calcOutGivenIn(_query); + + try IBalancerV2Simulator(balancerV2Simulator).calcOutGivenIn(_query) returns (uint256 balQuote) { + _quote = balQuote; + } catch { + _quote = 0; + } } } } @@ -593,11 +616,15 @@ contract OnChainPricingMainnet { return BALANCERV2_AURA_WETH_POOLID; } else if (token0 == BALWETHBPT && token1 == AURABAL){ return BALANCERV2_AURABAL_BALWETH_POOLID; - // TODO CHANGE } else if (token0 == AURABAL && token1 == WETH){ return BALANCERV2_AURABAL_GRAVIAURA_WETH_POOLID; } else if (token0 == GRAVIAURA && token1 == WETH){ return BALANCERV2_AURABAL_GRAVIAURA_WETH_POOLID; + } else if (token0 == WBTC && token1 == DIGG){ + return BALANCER_V2_WBTC_DIGG_GRAVIAURA_POOLID; + } else if (token0 == DIGG && token1 == GRAVIAURA){ + return BALANCER_V2_WBTC_DIGG_GRAVIAURA_POOLID; + } else{ return BALANCERV2_NONEXIST_POOLID; } @@ -607,9 +634,11 @@ contract OnChainPricingMainnet { /// @dev Given the address of the CurveLike Router, the input amount, and the path, returns the quote for it function getCurvePrice(address router, address tokenIn, address tokenOut, uint256 amountIn) public view returns (address, uint256) { - (address pool, uint256 curveQuote) = ICurveRouter(router).get_best_rate(tokenIn, tokenOut, amountIn); - - return (pool, curveQuote); + try ICurveRouter(router).get_best_rate(tokenIn, tokenOut, amountIn) returns (address pool, uint256 curveQuote) { + return (pool, curveQuote); + } catch { + return (address(0), 0); + } } /// @return assembled curve pools and fees in required Quote struct for given pool diff --git a/scripts/send_order.py b/scripts/send_order.py index 78fe0ae..ed150f0 100644 --- a/scripts/send_order.py +++ b/scripts/send_order.py @@ -11,17 +11,29 @@ WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" +SLIPPAGE = 0.98 ## 2% + def main(): - pricer = OnChainPricingMainnet.deploy({"from": a[0]}) + """ + DEMO ORDER + Customize to use it for real life usage + """ + dev = connect_account() - c = CowSwapDemoSeller.deploy(pricer, {"from": a[0]}) + seller = CowSwapDemoSeller.at("0x75547825A99283379e0E812B7c10F832813326d6") usdc = interface.ERC20(USDC) weth = interface.ERC20(WETH) - amount = 1000000000000000000 + amount = usdc.balanceOf(seller) + + order_data = get_cowswap_order(seller, usdc, weth, amount) + + data = order_data.order_data + uid = order_data.order_uid + + seller.initiateCowswapOrder(data, uid, {"from": dev}) - cowswap_sell_demo(c, weth, usdc, amount, a[0]) def get_cowswap_order(contract, sell_token, buy_token, amount_in): """ @@ -137,7 +149,7 @@ def cowswap_sell_demo(contract, sell_token, buy_token, amount_in): "sellToken": sell_token.address, "buyToken": buy_token.address, "sellAmount": str(amount-fee_amount), # amount that we have minus the fee we have to pay - "buyAmount": str(buy_amount_after_fee), # buy amount fetched from the previous call + "buyAmount": str(buy_amount_after_fee * SLIPPAGE), # buy amount fetched from the previous call "validTo": deadline, "appData": "0x2B8694ED30082129598720860E8E972F07AA10D9B81CAE16CA0E2CFB24743E24", # maps to https://bafybeiblq2ko2maieeuvtbzaqyhi5fzpa6vbbwnydsxbnsqoft5si5b6eq.ipfs.dweb.link "feeAmount": str(fee_amount), diff --git a/tests/aura_processor/run_fuzz.py b/tests/aura_processor/run_fuzz.py new file mode 100644 index 0000000..59a4f75 --- /dev/null +++ b/tests/aura_processor/run_fuzz.py @@ -0,0 +1,188 @@ +import brownie +from brownie import * +from brownie.test import given, strategy +import pytest + +""" + Fuzz + Fuzz any random address and amount + To ensure no revert will happen + + ## This will take almost an hour. Consider using foundry :P +""" +LIVE_PROCESSOR = "0x8abd28e4d69bd3953b96dd9ed63533765adb9965" + + +## TOKENS +USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + + +## Mostly Aura +AURA = "0xC0c293ce456fF0ED870ADd98a0828Dd4d2903DBF" +AURA_BAL = "0x616e8BfA43F920657B3497DBf40D6b1A02D4608d" + +BADGER = "0x3472A5A71965499acd81997a54BBA8D852C6E53d" + +SD = "0x30d20208d987713f46dfd34ef128bb16c404d10f" ## Pretty much completely new token https://etherscan.io/token/0x30d20208d987713f46dfd34ef128bb16c404d10f#balances + +DFX = "0x888888435FDe8e7d4c54cAb67f206e4199454c60" ## Fairly Liquid: https://etherscan.io/token/0x888888435FDe8e7d4c54cAb67f206e4199454c60#balances + +FDT = "0xEd1480d12bE41d92F36f5f7bDd88212E381A3677" ## Illiquid as of today, in vault but no pool I could find https://etherscan.io/token/0xEd1480d12bE41d92F36f5f7bDd88212E381A3677#balances + +LDO = "0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32" +COW = "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB" ## Has pair with GNO and with WETH +GNO = "0x6810e776880C02933D47DB1b9fc05908e5386b96" + +## Mostly Votium +CVX = "0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B" +WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" +SNX = "0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F" +TRIBE = "0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B" +FLX = "0x6243d8cea23066d098a15582d81a598b4e8391f4" +INV = "0x41d5d79431a913c4ae7d69a668ecdfe5ff9dfb68" +FXS = "0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0" + + +## More Random Votium stuff +TUSD = "0x0000000000085d4780B73119b644AE5ecd22b376" +STG = "0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6" +LYRA = "0x01BA67AAC7f75f647D94220Cc98FB30FCc5105Bf" +JPEG = "0xE80C0cd204D654CEbe8dd64A4857cAb6Be8345a3" +GRO = "0x3Ec8798B81485A254928B70CDA1cf0A2BB0B74D7" +EURS = "0xdB25f211AB05b1c97D595516F45794528a807ad8" + +## New Aura Pools +DIGG = "0x798D1bE841a82a273720CE31c822C61a67a601C3" +GRAVI_AURA = "0xBA485b556399123261a5F9c95d413B4f93107407" + +BRIBES_TOKEN_CLAIMABLE = [ + ("0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B", 18), ## CVX + ("0x6B175474E89094C44Da98b954EedeAC495271d0F", 18), ## DAI + ("0x090185f2135308bad17527004364ebcc2d37e5f6", 22), ## SPELL ## NOTE: Using 22 to adjust as spell is super high supply + ("0xdbdb4d16eda451d0503b854cf79d55697f90c8df", 18), ## ALCX + ("0x9D79d5B61De59D882ce90125b18F74af650acB93", 8), ## NSBT ## NOTE: Using 6 + 2 decimals to make it more + ("0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", 18), ## MATIC + ("0x3432b6a60d23ca0dfca7761b7ab56459d9c964d0", 18), ## FXS + ("0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32", 18), ## LDO + ("0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B", 18), ## TRIBE + ("0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26", 18), ## OGN + ("0xa3BeD4E1c75D00fa6f4E5E6922DB7261B5E9AcD2", 18), ## MTA + ("0x31429d1856aD1377A8A0079410B297e1a9e214c2", 22), ## ANGLE ## NOTE Using 18 + 4 to raise the value + ("0xCdF7028ceAB81fA0C6971208e83fa7872994beE5", 22), ## T ## NOTE Using 18 + 4 to raise the value + ("0xa693B19d2931d498c5B318dF961919BB4aee87a5", 6), # UST + ("0xB620Be8a1949AA9532e6a3510132864EF9Bc3F82", 22), ## LFT ## NOTE Using 18 + 4 to raise the value + ("0x6243d8CEA23066d098a15582d81a598b4e8391F4", 18), ## FLX + ("0x3Ec8798B81485A254928B70CDA1cf0A2BB0B74D7", 18), ## GRO + ("0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6", 18), ## STG + ("0xdB25f211AB05b1c97D595516F45794528a807ad8", 2), ## EURS + ("0x674C6Ad92Fd080e4004b2312b45f796a192D27a0", 18), ## USDN + ("0xFEEf77d3f69374f66429C91d732A244f074bdf74", 18), ## cvxFXS + ("0x41D5D79431A913C4aE7d69a668ecdfE5fF9DFB68", 18), ## INV + (USDC, 6), + (AURA, 18), + (AURA_BAL, 18), + (BADGER, 18), + (SD, 18), ## Not Supported -> Cannot fix at this time + (DFX, 18), + (FDT, 18), ## Not Supported -> Cannot fix at this time + (LDO, 18), + (COW, 18), + (GNO, 18), + (CVX, 18), + (SNX, 18), + (TRIBE, 18), + (FLX, 18), + (INV, 18), + (FXS, 18), + + ## More Coins + (TUSD, 18), + (STG, 18), + (LYRA, 18), + (JPEG, 18), + (GRO, 18), + (EURS, 18), + + ## From new Balancer Pools + (DIGG, 9), + (GRAVI_AURA, 18) +] + + +### Sell Bribes for Weth +@given(amount=strategy("uint256"), sell_token_num=strategy("uint256")) +def test_fuzz_processing(sell_token_num, amount): + + sell_token = interface.ERC20(BRIBES_TOKEN_CLAIMABLE[sell_token_num % len(BRIBES_TOKEN_CLAIMABLE)][0]) + + ## Skip if amt = 0 + if amount == 0: + return True + + if str(web3.eth.getCode(str(sell_token.address))) == "b''": + return True + + + ## NOTE: Put all the fixtures here cause I keep getting reverts + #### FIXTURES ### + + ## NOTE: We have 5% slippage on this one + univ3simulator = UniV3SwapSimulator.deploy({"from": accounts[0]}) + balancerV2Simulator = BalancerSwapSimulator.deploy({"from": accounts[0]}) + lenient_pricer_fuzz = OnChainPricingMainnetLenient.deploy(univ3simulator.address, balancerV2Simulator.address, {"from": accounts[0]}) + lenient_pricer_fuzz.setSlippage(499, {"from": accounts.at(lenient_pricer_fuzz.TECH_OPS(), force=True)}) + + setup_processor = AuraBribesProcessor.at(LIVE_PROCESSOR) + + dev_multi = accounts.at(setup_processor.DEV_MULTI(), force=True) + setup_processor.setPricer(lenient_pricer_fuzz, {"from": dev_multi}) + + + settlement_fuzz = interface.ICowSettlement(setup_processor.SETTLEMENT()) + + if amount > sell_token.totalSupply(): + amount = sell_token.totalSupply() - 1 ## Avoid revert due to insane numbers + + fee_amount = amount * 0.01 + data = [ + sell_token, + setup_processor.WETH(), ## Can only buy WETH here + setup_processor.address, + amount-fee_amount, + 1.1579209e76, ## 2^256-1 / 10 so it passes + 4294967294, + "0x2B8694ED30082129598720860E8E972F07AA10D9B81CAE16CA0E2CFB24743E24", + fee_amount, + setup_processor.KIND_SELL(), + False, + setup_processor.BALANCE_ERC20(), + setup_processor.BALANCE_ERC20() + ] + + """ + SKIP to avoid revert on these cases + + require(orderData.sellToken != AURA); // Can't sell AURA; + require(orderData.sellToken != BADGER); // Can't sell BADGER either; + require(orderData.sellToken != WETH); // Can't sell WETH + require(orderData.buyToken == WETH); // Gotta Buy WETH; + """ + + if sell_token == setup_processor.AURA(): + return True + if sell_token == setup_processor.BADGER(): + return True + if sell_token == setup_processor.WETH(): + return True + if sell_token == setup_processor.AURA(): + return True + + + uid = setup_processor.getOrderID(data) + + + tx = setup_processor.sellBribeForWeth(data, uid, {"from": accounts.at(setup_processor.manager(), force=True)}) + + print("real test") + + assert settlement_fuzz.preSignature(uid) > 0 \ No newline at end of file diff --git a/tests/aura_processor/run_fuzz_real_deploys.py b/tests/aura_processor/run_fuzz_real_deploys.py new file mode 100644 index 0000000..348f102 --- /dev/null +++ b/tests/aura_processor/run_fuzz_real_deploys.py @@ -0,0 +1,188 @@ +import brownie +from brownie import * +from brownie.test import given, strategy +import pytest + +""" + Fuzz + Fuzz any random address and amount + To ensure no revert will happen + + ## This will take almost an hour. Consider using foundry :P +""" +LIVE_PROCESSOR = "0x8abd28e4d69bd3953b96dd9ed63533765adb9965" +LIVE_PRICER = "0x2DC7693444aCd1EcA1D6dE5B3d0d8584F3870c49" + + + +## TOKENS +USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + + +## Mostly Aura +AURA = "0xC0c293ce456fF0ED870ADd98a0828Dd4d2903DBF" +AURA_BAL = "0x616e8BfA43F920657B3497DBf40D6b1A02D4608d" + +BADGER = "0x3472A5A71965499acd81997a54BBA8D852C6E53d" + +SD = "0x30d20208d987713f46dfd34ef128bb16c404d10f" ## Pretty much completely new token https://etherscan.io/token/0x30d20208d987713f46dfd34ef128bb16c404d10f#balances + +DFX = "0x888888435FDe8e7d4c54cAb67f206e4199454c60" ## Fairly Liquid: https://etherscan.io/token/0x888888435FDe8e7d4c54cAb67f206e4199454c60#balances + +FDT = "0xEd1480d12bE41d92F36f5f7bDd88212E381A3677" ## Illiquid as of today, in vault but no pool I could find https://etherscan.io/token/0xEd1480d12bE41d92F36f5f7bDd88212E381A3677#balances + +LDO = "0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32" +COW = "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB" ## Has pair with GNO and with WETH +GNO = "0x6810e776880C02933D47DB1b9fc05908e5386b96" + +## Mostly Votium +CVX = "0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B" +WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" +SNX = "0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F" +TRIBE = "0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B" +FLX = "0x6243d8cea23066d098a15582d81a598b4e8391f4" +INV = "0x41d5d79431a913c4ae7d69a668ecdfe5ff9dfb68" +FXS = "0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0" + + +## More Random Votium stuff +TUSD = "0x0000000000085d4780B73119b644AE5ecd22b376" +STG = "0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6" +LYRA = "0x01BA67AAC7f75f647D94220Cc98FB30FCc5105Bf" +JPEG = "0xE80C0cd204D654CEbe8dd64A4857cAb6Be8345a3" +GRO = "0x3Ec8798B81485A254928B70CDA1cf0A2BB0B74D7" +EURS = "0xdB25f211AB05b1c97D595516F45794528a807ad8" + +## New Aura Pools +DIGG = "0x798D1bE841a82a273720CE31c822C61a67a601C3" +GRAVI_AURA = "0xBA485b556399123261a5F9c95d413B4f93107407" + +BRIBES_TOKEN_CLAIMABLE = [ + ("0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B", 18), ## CVX + ("0x6B175474E89094C44Da98b954EedeAC495271d0F", 18), ## DAI + ("0x090185f2135308bad17527004364ebcc2d37e5f6", 22), ## SPELL ## NOTE: Using 22 to adjust as spell is super high supply + ("0xdbdb4d16eda451d0503b854cf79d55697f90c8df", 18), ## ALCX + ("0x9D79d5B61De59D882ce90125b18F74af650acB93", 8), ## NSBT ## NOTE: Using 6 + 2 decimals to make it more + ("0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", 18), ## MATIC + ("0x3432b6a60d23ca0dfca7761b7ab56459d9c964d0", 18), ## FXS + ("0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32", 18), ## LDO + ("0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B", 18), ## TRIBE + ("0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26", 18), ## OGN + ("0xa3BeD4E1c75D00fa6f4E5E6922DB7261B5E9AcD2", 18), ## MTA + ("0x31429d1856aD1377A8A0079410B297e1a9e214c2", 22), ## ANGLE ## NOTE Using 18 + 4 to raise the value + ("0xCdF7028ceAB81fA0C6971208e83fa7872994beE5", 22), ## T ## NOTE Using 18 + 4 to raise the value + ("0xa693B19d2931d498c5B318dF961919BB4aee87a5", 6), # UST + ("0xB620Be8a1949AA9532e6a3510132864EF9Bc3F82", 22), ## LFT ## NOTE Using 18 + 4 to raise the value + ("0x6243d8CEA23066d098a15582d81a598b4e8391F4", 18), ## FLX + ("0x3Ec8798B81485A254928B70CDA1cf0A2BB0B74D7", 18), ## GRO + ("0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6", 18), ## STG + ("0xdB25f211AB05b1c97D595516F45794528a807ad8", 2), ## EURS + ("0x674C6Ad92Fd080e4004b2312b45f796a192D27a0", 18), ## USDN + ("0xFEEf77d3f69374f66429C91d732A244f074bdf74", 18), ## cvxFXS + ("0x41D5D79431A913C4aE7d69a668ecdfE5fF9DFB68", 18), ## INV + (USDC, 6), + (AURA, 18), + (AURA_BAL, 18), + (BADGER, 18), + (SD, 18), ## Not Supported -> Cannot fix at this time + (DFX, 18), + (FDT, 18), ## Not Supported -> Cannot fix at this time + (LDO, 18), + (COW, 18), + (GNO, 18), + (CVX, 18), + (SNX, 18), + (TRIBE, 18), + (FLX, 18), + (INV, 18), + (FXS, 18), + + ## More Coins + (TUSD, 18), + (STG, 18), + (LYRA, 18), + (JPEG, 18), + (GRO, 18), + (EURS, 18), + + ## From new Balancer Pools + (DIGG, 9), + (GRAVI_AURA, 18) +] + + +### Sell Bribes for Weth +@given(amount=strategy("uint256"), sell_token_num=strategy("uint256")) +def test_fuzz_processing(sell_token_num, amount): + + sell_token = interface.ERC20(BRIBES_TOKEN_CLAIMABLE[sell_token_num % len(BRIBES_TOKEN_CLAIMABLE)][0]) + + ## Skip if amt = 0 + if amount == 0: + return True + + if str(web3.eth.getCode(str(sell_token.address))) == "b''": + return True + + + ## NOTE: Put all the fixtures here cause I keep getting reverts + #### FIXTURES ### + + ## NOTE: We have 5% slippage on this one + lenient_pricer_fuzz = OnChainPricingMainnetLenient.at(LIVE_PRICER) + lenient_pricer_fuzz.setSlippage(499, {"from": accounts.at(lenient_pricer_fuzz.TECH_OPS(), force=True)}) + + setup_processor = AuraBribesProcessor.at(LIVE_PROCESSOR) + + dev_multi = accounts.at(setup_processor.DEV_MULTI(), force=True) + setup_processor.setPricer(lenient_pricer_fuzz, {"from": dev_multi}) + + + settlement_fuzz = interface.ICowSettlement(setup_processor.SETTLEMENT()) + + if amount > sell_token.totalSupply(): + amount = sell_token.totalSupply() - 1 ## Avoid revert due to insane numbers + + fee_amount = amount * 0.01 + data = [ + sell_token, + setup_processor.WETH(), ## Can only buy WETH here + setup_processor.address, + amount-fee_amount, + 1.1579209e76, ## 2^256-1 / 10 so it passes + 4294967294, + "0x2B8694ED30082129598720860E8E972F07AA10D9B81CAE16CA0E2CFB24743E24", + fee_amount, + setup_processor.KIND_SELL(), + False, + setup_processor.BALANCE_ERC20(), + setup_processor.BALANCE_ERC20() + ] + + """ + SKIP to avoid revert on these cases + + require(orderData.sellToken != AURA); // Can't sell AURA; + require(orderData.sellToken != BADGER); // Can't sell BADGER either; + require(orderData.sellToken != WETH); // Can't sell WETH + require(orderData.buyToken == WETH); // Gotta Buy WETH; + """ + + if sell_token == setup_processor.AURA(): + return True + if sell_token == setup_processor.BADGER(): + return True + if sell_token == setup_processor.WETH(): + return True + if sell_token == setup_processor.AURA(): + return True + + + uid = setup_processor.getOrderID(data) + + + tx = setup_processor.sellBribeForWeth(data, uid, {"from": accounts.at(setup_processor.manager(), force=True)}) + + print("real test") + + assert settlement_fuzz.preSignature(uid) > 0 \ No newline at end of file diff --git a/tests/on_chain_pricer/run_fuzz.py b/tests/on_chain_pricer/run_fuzz.py new file mode 100644 index 0000000..01fa97e --- /dev/null +++ b/tests/on_chain_pricer/run_fuzz.py @@ -0,0 +1,143 @@ +import brownie +from brownie import * +from brownie.test import given, strategy +import pytest + +""" + Fuzz + Fuzz of Pricer vs V2 Pricer for Equivalency +""" + +## TOKENS +USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + +## Mostly Aura +AURA = "0xC0c293ce456fF0ED870ADd98a0828Dd4d2903DBF" +AURA_BAL = "0x616e8BfA43F920657B3497DBf40D6b1A02D4608d" +BADGER = "0x3472A5A71965499acd81997a54BBA8D852C6E53d" + +SD = "0x30d20208d987713f46dfd34ef128bb16c404d10f" ## Pretty much completely new token https://etherscan.io/token/0x30d20208d987713f46dfd34ef128bb16c404d10f#balances +DFX = "0x888888435FDe8e7d4c54cAb67f206e4199454c60" ## Fairly Liquid: https://etherscan.io/token/0x888888435FDe8e7d4c54cAb67f206e4199454c60#balances +FDT = "0xEd1480d12bE41d92F36f5f7bDd88212E381A3677" ## Illiquid as of today, in vault but no pool I could find https://etherscan.io/token/0xEd1480d12bE41d92F36f5f7bDd88212E381A3677#balances +LDO = "0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32" +COW = "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB" ## Has pair with GNO and with WETH +GNO = "0x6810e776880C02933D47DB1b9fc05908e5386b96" + +## Mostly Votium +CVX = "0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B" +WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" +WBTC = "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599" +SNX = "0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F" +TRIBE = "0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B" +FLX = "0x6243d8cea23066d098a15582d81a598b4e8391f4" +INV = "0x41d5d79431a913c4ae7d69a668ecdfe5ff9dfb68" +FXS = "0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0" + + +## More Random Votium stuff +TUSD = "0x0000000000085d4780B73119b644AE5ecd22b376" +STG = "0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6" +LYRA = "0x01BA67AAC7f75f647D94220Cc98FB30FCc5105Bf" +JPEG = "0xE80C0cd204D654CEbe8dd64A4857cAb6Be8345a3" +GRO = "0x3Ec8798B81485A254928B70CDA1cf0A2BB0B74D7" +EURS = "0xdB25f211AB05b1c97D595516F45794528a807ad8" + +## New Aura Pools +DIGG = "0x798D1bE841a82a273720CE31c822C61a67a601C3" +GRAVI_AURA = "0xBA485b556399123261a5F9c95d413B4f93107407" + +BRIBES_TOKEN_CLAIMABLE = [ + ("0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B", 18), ## CVX + ("0x6B175474E89094C44Da98b954EedeAC495271d0F", 18), ## DAI + ("0x090185f2135308bad17527004364ebcc2d37e5f6", 22), ## SPELL ## NOTE: Using 22 to adjust as spell is super high supply + ("0xdbdb4d16eda451d0503b854cf79d55697f90c8df", 18), ## ALCX + ("0x9D79d5B61De59D882ce90125b18F74af650acB93", 8), ## NSBT ## NOTE: Using 6 + 2 decimals to make it more + ("0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", 18), ## MATIC + ("0x3432b6a60d23ca0dfca7761b7ab56459d9c964d0", 18), ## FXS + ("0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32", 18), ## LDO + ("0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B", 18), ## TRIBE + ("0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26", 18), ## OGN + ("0xa3BeD4E1c75D00fa6f4E5E6922DB7261B5E9AcD2", 18), ## MTA + ("0x31429d1856aD1377A8A0079410B297e1a9e214c2", 22), ## ANGLE ## NOTE Using 18 + 4 to raise the value + ("0xCdF7028ceAB81fA0C6971208e83fa7872994beE5", 22), ## T ## NOTE Using 18 + 4 to raise the value + ("0xa693B19d2931d498c5B318dF961919BB4aee87a5", 6), # UST + ("0xB620Be8a1949AA9532e6a3510132864EF9Bc3F82", 22), ## LFT ## NOTE Using 18 + 4 to raise the value + ("0x6243d8CEA23066d098a15582d81a598b4e8391F4", 18), ## FLX + ("0x3Ec8798B81485A254928B70CDA1cf0A2BB0B74D7", 18), ## GRO + ("0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6", 18), ## STG + ("0xdB25f211AB05b1c97D595516F45794528a807ad8", 2), ## EURS + ("0x674C6Ad92Fd080e4004b2312b45f796a192D27a0", 18), ## USDN + ("0xFEEf77d3f69374f66429C91d732A244f074bdf74", 18), ## cvxFXS + ("0x41D5D79431A913C4aE7d69a668ecdfE5fF9DFB68", 18), ## INV + ("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", 6), ## USDC + ("0xC0c293ce456fF0ED870ADd98a0828Dd4d2903DBF", 18), ## AURA + ("0x616e8BfA43F920657B3497DBf40D6b1A02D4608d", 18), ## AURA_BAL + ("0x3472A5A71965499acd81997a54BBA8D852C6E53d", 18), ## BADGER + ("0x30d20208d987713f46dfd34ef128bb16c404d10f", 18), ## SD | Not Supported -> Cannot fix at this time + ("0x888888435FDe8e7d4c54cAb67f206e4199454c60", 18), ## DFX + ("0xEd1480d12bE41d92F36f5f7bDd88212E381A3677", 18), ## FDT ## Not Supported -> Cannot fix at this time + ("0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32", 18), ## LDO + ("0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB", 18), ## COW + ("0x6810e776880C02933D47DB1b9fc05908e5386b96", 18), ## GNO + ("0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B", 18), ## CVX + ("0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F", 18), ## SNX + ("0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B", 18), ## TRIBE + ("0x6243d8cea23066d098a15582d81a598b4e8391f4", 18), ## FLX + ("0x41d5d79431a913c4ae7d69a668ecdfe5ff9dfb68", 18), ## INV + ("0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0", 18), ## FXS + + ("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", 18), ## WETH + ("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", 8), ## WBTC + + ## More Coins + ("0x0000000000085d4780B73119b644AE5ecd22b376", 18), ## TUSD + ("0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6", 18), ## STG + ("0x01BA67AAC7f75f647D94220Cc98FB30FCc5105Bf", 18), ## LYRA + ("0xE80C0cd204D654CEbe8dd64A4857cAb6Be8345a3", 18), ## JPEG + ("0x3Ec8798B81485A254928B70CDA1cf0A2BB0B74D7", 18), ## GRO + ("0xdB25f211AB05b1c97D595516F45794528a807ad8", 18), ## EURS + + ## From new Balancer Pools + ("0x798D1bE841a82a273720CE31c822C61a67a601C3", 9), ## DIGG + ("0xBA485b556399123261a5F9c95d413B4f93107407", 18) ## GRAVI_AURA +] + + +### Sell Bribes for Weth +@given(amount=strategy("uint256"), sell_token_num=strategy("uint256"), buy_token_num=strategy("uint256")) +def test_fuzz_pricers(sell_token_num, buy_token_num, amount): + + sell_token = interface.ERC20(BRIBES_TOKEN_CLAIMABLE[sell_token_num % len(BRIBES_TOKEN_CLAIMABLE)][0]) + buy_token = interface.ERC20(BRIBES_TOKEN_CLAIMABLE[buy_token_num % len(BRIBES_TOKEN_CLAIMABLE)][0]) + + ## Skip if amt = 0 + if amount == 0: + return True + + ## Fake Token = Skip + if str(web3.eth.getCode(str(sell_token.address))) == "b''": + return True + + + ## NOTE: Put all the fixtures here cause I keep getting reverts + #### FIXTURES ### + + ## NOTE: We have 5% slippage on this one + univ3simulator = UniV3SwapSimulator.deploy({"from": accounts[0]}) + balancerV2Simulator = BalancerSwapSimulator.deploy({"from": accounts[0]}) + pricer_fuzz_v3 = OnChainPricingMainnet.deploy(univ3simulator.address, balancerV2Simulator.address, {"from": accounts[0]}) + + pricer_fuzz_v2 = FullOnChainPricingMainnet.deploy({"from": a[0]}) + + try: + v2_quote = pricer_fuzz_v2.findOptimalSwap.call(sell_token, buy_token, amount) + except: + print("Exception from V2") + + v3_quote = pricer_fuzz_v3.findOptimalSwap(sell_token, buy_token, amount) + + ## Compare quote.amountOut + ## >= for equivalent or better value for any combination + ## NOTE: Have had a test fail by 1 wei, due to rounding prob + # assert v3_quote[1] >= v2_quote[1] + assert v3_quote[1] >= 0 ## Did not revert \ No newline at end of file diff --git a/tests/on_chain_pricer/test_bribe_tokens_supported.py b/tests/on_chain_pricer/test_bribe_tokens_supported.py index c2d23af..a0c2283 100644 --- a/tests/on_chain_pricer/test_bribe_tokens_supported.py +++ b/tests/on_chain_pricer/test_bribe_tokens_supported.py @@ -1,7 +1,6 @@ import pytest from brownie import * -## NOTE: Removed as we're testing with 1e18 USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" @@ -9,6 +8,8 @@ AURA = "0xC0c293ce456fF0ED870ADd98a0828Dd4d2903DBF" AURA_BAL = "0x616e8BfA43F920657B3497DBf40D6b1A02D4608d" +BADGER = "0x3472A5A71965499acd81997a54BBA8D852C6E53d" + SD = "0x30d20208d987713f46dfd34ef128bb16c404d10f" ## Pretty much completely new token https://etherscan.io/token/0x30d20208d987713f46dfd34ef128bb16c404d10f#balances DFX = "0x888888435FDe8e7d4c54cAb67f206e4199454c60" ## Fairly Liquid: https://etherscan.io/token/0x888888435FDe8e7d4c54cAb67f206e4199454c60#balances @@ -29,12 +30,26 @@ FXS = "0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0" +## More Random Votium stuff +TUSD = "0x0000000000085d4780B73119b644AE5ecd22b376" +STG = "0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6" +LYRA = "0x01BA67AAC7f75f647D94220Cc98FB30FCc5105Bf" +JPEG = "0xE80C0cd204D654CEbe8dd64A4857cAb6Be8345a3" +GRO = "0x3Ec8798B81485A254928B70CDA1cf0A2BB0B74D7" +EURS = "0xdB25f211AB05b1c97D595516F45794528a807ad8" + +## New Aura Pools +DIGG = "0x798D1bE841a82a273720CE31c822C61a67a601C3" +GRAVI_AURA = "0xBA485b556399123261a5F9c95d413B4f93107407" + TOKENS_18_DECIMALS = [ + USDC, AURA, - AURA_BAL, ## Not Supported -> To FIX TODO ADD BAL POOL - #SD, ## Not Supported -> Cannot fix at this time + AURA_BAL, + BADGER, + SD, ## Not Supported -> Cannot fix at this time DFX, - #FDT, ## Not Supported -> Cannot fix at this time + FDT, ## Not Supported -> Cannot fix at this time LDO, COW, GNO, @@ -43,7 +58,19 @@ TRIBE, FLX, INV, - FXS + FXS, + + ## More Coins + TUSD, + STG, + LYRA, + JPEG, + GRO, + EURS, + + ## From new Balancer Pools + DIGG, + GRAVI_AURA ] @pytest.mark.parametrize("token", TOKENS_18_DECIMALS) @@ -60,6 +87,6 @@ def test_are_bribes_supported(pricerwrapper, token): res = pricer.isPairSupported(token, WETH, AMOUNT) assert res - quote = pricer.findOptimalSwap.call(token, WETH, AMOUNT) + quote = pricer.findOptimalSwap(token, WETH, AMOUNT) assert quote[1][1] > 0