From e169d04ba6cc033f625eac6d3d479a84a653f446 Mon Sep 17 00:00:00 2001 From: Tonkers Date: Thu, 25 Aug 2022 17:49:23 -0700 Subject: [PATCH 01/10] test: 1inch tests --- tests/test_one_inch.py | 131 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-) diff --git a/tests/test_one_inch.py b/tests/test_one_inch.py index 590c8d6..0b2273a 100644 --- a/tests/test_one_inch.py +++ b/tests/test_one_inch.py @@ -1,4 +1,5 @@ -from brownie import Contract, accounts, Wei, chain, TestableVM +from brownie import Contract, accounts, Wei, chain, TestableVM, convert +from brownie.convert.datatypes import HexString from weiroll import WeirollContract, WeirollPlanner import requests @@ -43,3 +44,131 @@ def test_one_inch(weiroll_vm): ) assert crv.balanceOf(weiroll_vm) > 0 + + +def test_one_inch_replace_calldata_amount(weiroll_vm): + whale = accounts.at("0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True) + weth = Contract("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") + crv = Contract("0xD533a949740bb3306d119CC777fa900bA034cd52") + one_inch = Contract("0x1111111254fb6c44bAC0beD2854e76F90643097d") + + weth.transfer(weiroll_vm.address, Wei("10 ether"), {"from": whale}) + + swap_url = "https://api.1inch.io/v4.0/1/swap" + r = requests.get( + swap_url, + params={ + "fromTokenAddress": weth.address, + "toTokenAddress": crv.address, + "amount": Wei("10 ether"), + "fromAddress": weiroll_vm.address, + "slippage": 5, + "disableEstimate": "true", + "allowPartialFill": "false", + }, + ) + + assert r.ok and r.status_code == 200 + tx = r.json()["tx"] + + weth.approve(one_inch, 2 ** 256 - 1, {"from": weiroll_vm, "gas_price": 0}) + + decoded = one_inch.decode_input(tx["data"]) + func_name = decoded[0] + params = decoded[1] + calldata = params[2] + + # change inputs + wei9 = Wei("9 ether") + params[1][4] = wei9 + params[1][5] = 1 + + # Operations to edit decoded swap data + # convert dec to hex (0xHexDec) -> (0x00...HexDec) -> (00..HexDec) string + hex10 = HexString(hex(Wei("10 ether")), "bytes32").hex() + hex9 = HexString(hex(wei9), "bytes32").hex() + + # HexString to string + calldata_str = calldata.hex() + + # string replacement + replaced = calldata_str.replace(hex10, hex9) + + # back to hexstring + params[2] = HexString(replaced, "bytes") + + planner = WeirollPlanner(weiroll_vm) + planner.call(one_inch, func_name, *params) + + cmds, state = planner.plan() + weiroll_tx = weiroll_vm.execute( + cmds, state, {"from": whale, "gas_limit": 8_000_000, "gas_price": 0} + ) + + assert crv.balanceOf(weiroll_vm) > 0 + print(crv.balanceOf(weiroll_vm)) + + +def test_one_inch_replace_calldata_amount_2(weiroll_vm): + whale = accounts.at("0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True) + weth = Contract("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") + crv = Contract("0xD533a949740bb3306d119CC777fa900bA034cd52") + one_inch = Contract("0x1111111254fb6c44bAC0beD2854e76F90643097d") + + weth.transfer(weiroll_vm.address, Wei("10 ether"), {"from": whale}) + + swap_url = "https://api.1inch.io/v4.0/1/swap" + r = requests.get( + swap_url, + params={ + "fromTokenAddress": weth.address, + "toTokenAddress": crv.address, + "amount": Wei("10 ether"), + "fromAddress": weiroll_vm.address, + "slippage": 5, + "disableEstimate": "true", + "allowPartialFill": "false", + }, + ) + + assert r.ok and r.status_code == 200 + tx = r.json()["tx"] + + weth.approve(one_inch, 2 ** 256 - 1, {"from": weiroll_vm, "gas_price": 0}) + + decoded = one_inch.decode_input(tx["data"]) + func_name = decoded[0] + params = decoded[1] + calldata = params[2] + + # change inputs + wei9 = Wei("9 ether") + + # testing with calldata amount < struct amount at 10 wei still + # params[1][4] = wei9 + params[1][5] = 1 + + # Operations to edit decoded swap data + # convert dec to hex (0xHexDec) -> (0x00...HexDec) -> (00..HexDec) string + hex10 = HexString(hex(Wei("10 ether")), "bytes32").hex() + hex9 = HexString(hex(wei9), "bytes32").hex() + + # HexString to string + calldata_str = calldata.hex() + + # string replacement + replaced = calldata_str.replace(hex10, hex9) + + # back to hexstring + params[2] = HexString(replaced, "bytes") + + planner = WeirollPlanner(weiroll_vm) + planner.call(one_inch, func_name, *params) + + cmds, state = planner.plan() + weiroll_tx = weiroll_vm.execute( + cmds, state, {"from": whale, "gas_limit": 8_000_000, "gas_price": 0} + ) + + assert crv.balanceOf(weiroll_vm) > 0 + print(crv.balanceOf(weiroll_vm)) From bb4cdf4ed3584d291db5686e33da899be86ea416 Mon Sep 17 00:00:00 2001 From: Tonkers Date: Thu, 25 Aug 2022 23:58:34 -0700 Subject: [PATCH 02/10] chaining 1inch wip --- tests/test_chaining_actions.py | 40 +++++++++++++++++-- tests/test_one_inch.py | 71 +++++++++++++++++++++++++++++++++- 2 files changed, 106 insertions(+), 5 deletions(-) diff --git a/tests/test_chaining_actions.py b/tests/test_chaining_actions.py index 3d4b980..3cbe53d 100644 --- a/tests/test_chaining_actions.py +++ b/tests/test_chaining_actions.py @@ -27,7 +27,7 @@ def test_chaining_action(weiroll_vm, tuple_helper): w_crv_yfi_weth = WeirollContract.createContract(crv_yfi_weth) # One inch section, eth->yfi - planner.add(w_weth.approve(one_inch.address, 2**256-1)) + planner.add(w_weth.approve(one_inch.address, 2 ** 256 - 1)) swap_url = "https://api.1inch.io/v4.0/1/swap" r = requests.get( swap_url, @@ -60,11 +60,12 @@ def test_chaining_action(weiroll_vm, tuple_helper): yfi_int_amount = ReturnValue('uint256', one_inch_amount.command) # Now that we have the yfi amount, let's do curve logic - planner.add(w_weth.approve(w_curve_swap.address, 2**256-1)) - planner.add(w_yfi.approve(w_curve_swap.address, 2**256-1)) + planner.add(w_weth.approve(w_curve_swap.address, 2 ** 256 - 1)) + planner.add(w_yfi.approve(w_curve_swap.address, 2 ** 256 - 1)) + params = [Wei("5 ether"), yfi_int_amount] curve_ret = planner.add( - w_curve_swap.add_liquidity([Wei("5 ether"), yfi_int_amount], 0) + w_curve_swap.add_liquidity(params, 0) ) planner.add(w_crv_yfi_weth.transfer(w_tuple_helper.address, curve_ret)) @@ -75,3 +76,34 @@ def test_chaining_action(weiroll_vm, tuple_helper): ) assert crv_yfi_weth.balanceOf(w_tuple_helper.address) > 0 + + +def test_return_value(weiroll_vm, tuple_helper): + yfi = Contract("0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e") + crv_yfi_weth = Contract("0x29059568bB40344487d62f7450E78b8E6C74e0e5") + curve_swap = Contract("0xC26b89A667578ec7b3f11b2F98d6Fd15C07C54ba") + yfi_whale = accounts.at("0xfeb4acf3df3cdea7399794d0869ef76a6efaff52", force=True) + + # Planner and all weiroll contracts + planner = WeirollPlanner(weiroll_vm) + w_yfi = WeirollContract.createContract(yfi) + w_curve_swap = WeirollContract.createContract(curve_swap) + + yfi.transfer(weiroll_vm.address, 10 ** 18, {'from': yfi_whale}) + + w_yfi_bal = planner.call(yfi, "balanceOf", weiroll_vm.address) + # Now that we have the yfi amount, let's do curve logic + planner.add(w_yfi.approve(w_curve_swap.address, 2 ** 256 - 1)) + + params = [0, w_yfi_bal] + planner.add( + w_curve_swap.add_liquidity(params, 0) + ) + + cmds, state = planner.plan() + weiroll_tx = weiroll_vm.execute( + cmds, state, {"from": yfi_whale, "gas_limit": 8_000_000, "gas_price": 0} + ) + + assert crv_yfi_weth.balanceOf(weiroll_vm.address) > 0 + assert False diff --git a/tests/test_one_inch.py b/tests/test_one_inch.py index 0b2273a..7d4d1eb 100644 --- a/tests/test_one_inch.py +++ b/tests/test_one_inch.py @@ -1,6 +1,8 @@ from brownie import Contract, accounts, Wei, chain, TestableVM, convert from brownie.convert.datatypes import HexString -from weiroll import WeirollContract, WeirollPlanner + +import weiroll +from weiroll import WeirollContract, WeirollPlanner, ReturnValue import requests @@ -165,6 +167,73 @@ def test_one_inch_replace_calldata_amount_2(weiroll_vm): planner = WeirollPlanner(weiroll_vm) planner.call(one_inch, func_name, *params) + cmds, state = planner.plan() + weiroll_tx = weiroll_vm.execute( + cmds, state, {"from": whale, "gas_limit": 8_000_000, "gas_price": 0} + ) + + assert crv.balanceOf(weiroll_vm) > 0 + print(crv.balanceOf(weiroll_vm)) + +import re +def test_one_inch_replace_calldata_with_weiroll(weiroll_vm, tuple_helper): + whale = accounts.at("0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True) + weth = Contract("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") + crv = Contract("0xD533a949740bb3306d119CC777fa900bA034cd52") + one_inch = Contract("0x1111111254fb6c44bAC0beD2854e76F90643097d") + w_tuple_helper = WeirollContract.createContract(tuple_helper) + + planner = WeirollPlanner(weiroll_vm) + + weth.transfer(weiroll_vm.address, Wei("10 ether"), {"from": whale}) + w_weth_balance = planner.call(weth, "balanceOf", weiroll_vm.address) + swap_url = "https://api.1inch.io/v4.0/1/swap" + r = requests.get( + swap_url, + params={ + "fromTokenAddress": weth.address, + "toTokenAddress": crv.address, + "amount": Wei("10 ether"), + "fromAddress": weiroll_vm.address, + "slippage": 5, + "disableEstimate": "true", + "allowPartialFill": "false", + }, + ) + + assert r.ok and r.status_code == 200 + tx = r.json()["tx"] + + weth.approve(one_inch, 2 ** 256 - 1, {"from": weiroll_vm, "gas_price": 0}) + + decoded = one_inch.decode_input(tx["data"]) + func_name = decoded[0] + params = decoded[1] + calldata = params[2] + + # change inputs + # amount_in + params[1][4] = w_weth_balance + # minOut + params[1][5] = 1 + + # TODO: I believe calldata can also be weirolled like this (?) + # calldata = params[3] + # # to string + # calldata_str = calldata.hex() + # hex10 = HexString(hex(Wei("10 ether")), "bytes32").hex() + # + # indices = [m.start() for m in re.finditer(hex10, calldata_str)] + # for i in indices: + # w_calldata = planner.add(w_tuple_helper.replaceElement(calldata, i, w_weth_balance,Fales)) + # params[2] = w_calldata + + w_one_inch = weiroll.WeirollContract(one_inch) + planner.add(w_one_inch.swap(params[0], params[1], params[2])) + # TODO: not sure why the w_weth_balance part isn't working + # TODO: EncodingTypeError: Value `ReturnValue(param...` of type cannot be encoded by UnsignedIntegerEncoder + + cmds, state = planner.plan() weiroll_tx = weiroll_vm.execute( cmds, state, {"from": whale, "gas_limit": 8_000_000, "gas_price": 0} From a8bec11d1ae7cc88567e404daa38506abfaec22c Mon Sep 17 00:00:00 2001 From: Tonkers Date: Mon, 26 Sep 2022 19:12:07 -0700 Subject: [PATCH 03/10] patching wip --- tests/test_one_inch.py | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/tests/test_one_inch.py b/tests/test_one_inch.py index 7d4d1eb..08d4d85 100644 --- a/tests/test_one_inch.py +++ b/tests/test_one_inch.py @@ -175,7 +175,15 @@ def test_one_inch_replace_calldata_amount_2(weiroll_vm): assert crv.balanceOf(weiroll_vm) > 0 print(crv.balanceOf(weiroll_vm)) + import re +import eth_abi +from brownie import Contract, accounts, Wei, chain, TestableVM, convert +from brownie.convert.datatypes import HexString +import weiroll +from weiroll import WeirollContract, WeirollPlanner, ReturnValue +import requests + def test_one_inch_replace_calldata_with_weiroll(weiroll_vm, tuple_helper): whale = accounts.at("0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True) weth = Contract("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") @@ -185,9 +193,12 @@ def test_one_inch_replace_calldata_with_weiroll(weiroll_vm, tuple_helper): planner = WeirollPlanner(weiroll_vm) + weth.approve(weiroll_vm.address, Wei("10 ether"), {"from": whale}) weth.transfer(weiroll_vm.address, Wei("10 ether"), {"from": whale}) w_weth_balance = planner.call(weth, "balanceOf", weiroll_vm.address) + w_weth_balance = weiroll.ReturnValue("bytes32", w_weth_balance.command) swap_url = "https://api.1inch.io/v4.0/1/swap" + print(weiroll_vm.address) r = requests.get( swap_url, params={ @@ -198,6 +209,7 @@ def test_one_inch_replace_calldata_with_weiroll(weiroll_vm, tuple_helper): "slippage": 5, "disableEstimate": "true", "allowPartialFill": "false", + "usePatching": "true" }, ) @@ -210,29 +222,20 @@ def test_one_inch_replace_calldata_with_weiroll(weiroll_vm, tuple_helper): func_name = decoded[0] params = decoded[1] calldata = params[2] - + print(func_name) # change inputs # amount_in - params[1][4] = w_weth_balance - # minOut - params[1][5] = 1 - - # TODO: I believe calldata can also be weirolled like this (?) - # calldata = params[3] - # # to string - # calldata_str = calldata.hex() - # hex10 = HexString(hex(Wei("10 ether")), "bytes32").hex() - # - # indices = [m.start() for m in re.finditer(hex10, calldata_str)] - # for i in indices: - # w_calldata = planner.add(w_tuple_helper.replaceElement(calldata, i, w_weth_balance,Fales)) - # params[2] = w_calldata + struct_layout = '(address,address,address,address,uint256,uint256,uint256,bytes)' + tuple_bytes = eth_abi.encode_single(struct_layout, params[1]) + one_wei = eth_abi.encode_single("uint256", 1) + tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_bytes, 4, w_weth_balance, True).rawValue()) + tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_bytes, 5, one_wei, True).rawValue()) + tuple_description = weiroll.ReturnValue(struct_layout, tuple_description.command) w_one_inch = weiroll.WeirollContract(one_inch) - planner.add(w_one_inch.swap(params[0], params[1], params[2])) - # TODO: not sure why the w_weth_balance part isn't working - # TODO: EncodingTypeError: Value `ReturnValue(param...` of type cannot be encoded by UnsignedIntegerEncoder - + params[1] = tuple_description + print(params) + planner.add(w_one_inch.swap(params[0], tuple_description, params[2]).rawValue()) cmds, state = planner.plan() weiroll_tx = weiroll_vm.execute( From 734f6f5eb66e638807ee3efdc361d900e003f062 Mon Sep 17 00:00:00 2001 From: Tonkers Date: Mon, 26 Sep 2022 19:14:47 -0700 Subject: [PATCH 04/10] nit: naming --- tests/test_one_inch.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/test_one_inch.py b/tests/test_one_inch.py index 08d4d85..14faa1b 100644 --- a/tests/test_one_inch.py +++ b/tests/test_one_inch.py @@ -221,15 +221,13 @@ def test_one_inch_replace_calldata_with_weiroll(weiroll_vm, tuple_helper): decoded = one_inch.decode_input(tx["data"]) func_name = decoded[0] params = decoded[1] - calldata = params[2] print(func_name) - # change inputs - # amount_in + struct_layout = '(address,address,address,address,uint256,uint256,uint256,bytes)' tuple_bytes = eth_abi.encode_single(struct_layout, params[1]) - one_wei = eth_abi.encode_single("uint256", 1) + min_return = eth_abi.encode_single("uint256", 1) tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_bytes, 4, w_weth_balance, True).rawValue()) - tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_bytes, 5, one_wei, True).rawValue()) + tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_bytes, 5, min_return, True).rawValue()) tuple_description = weiroll.ReturnValue(struct_layout, tuple_description.command) w_one_inch = weiroll.WeirollContract(one_inch) From f85a394ccf04c42712be97b4f88c208f5c8c02a0 Mon Sep 17 00:00:00 2001 From: Tonkers Date: Tue, 27 Sep 2022 12:18:48 -0700 Subject: [PATCH 05/10] use real addresses --- tests/test_one_inch.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/tests/test_one_inch.py b/tests/test_one_inch.py index 14faa1b..6b919fe 100644 --- a/tests/test_one_inch.py +++ b/tests/test_one_inch.py @@ -189,23 +189,24 @@ def test_one_inch_replace_calldata_with_weiroll(weiroll_vm, tuple_helper): weth = Contract("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") crv = Contract("0xD533a949740bb3306d119CC777fa900bA034cd52") one_inch = Contract("0x1111111254fb6c44bAC0beD2854e76F90643097d") - w_tuple_helper = WeirollContract.createContract(tuple_helper) - - planner = WeirollPlanner(weiroll_vm) - - weth.approve(weiroll_vm.address, Wei("10 ether"), {"from": whale}) - weth.transfer(weiroll_vm.address, Wei("10 ether"), {"from": whale}) - w_weth_balance = planner.call(weth, "balanceOf", weiroll_vm.address) + tuple_helper = Contract("0x06706E366159cEfD3789184686da5cC3f47fB4a2") + w_tuple_helper = weiroll.WeirollContract(tuple_helper) + th = accounts.at("0xcADBA199F3AC26F67f660C89d43eB1820b7f7a3b", force=True) + planner = WeirollPlanner(th) + + weth.approve(th.address, Wei("10 ether"), {"from": whale}) + weth.transfer(th.address, Wei("10 ether"), {"from": whale}) + w_weth_balance = planner.call(weth, "balanceOf", th.address) w_weth_balance = weiroll.ReturnValue("bytes32", w_weth_balance.command) swap_url = "https://api.1inch.io/v4.0/1/swap" - print(weiroll_vm.address) + print(th.address) r = requests.get( swap_url, params={ "fromTokenAddress": weth.address, "toTokenAddress": crv.address, "amount": Wei("10 ether"), - "fromAddress": weiroll_vm.address, + "fromAddress": th.address, "slippage": 5, "disableEstimate": "true", "allowPartialFill": "false", @@ -216,7 +217,7 @@ def test_one_inch_replace_calldata_with_weiroll(weiroll_vm, tuple_helper): assert r.ok and r.status_code == 200 tx = r.json()["tx"] - weth.approve(one_inch, 2 ** 256 - 1, {"from": weiroll_vm, "gas_price": 0}) + weth.approve(one_inch, 2 ** 256 - 1, {"from": th, "gas_price": 0}) decoded = one_inch.decode_input(tx["data"]) func_name = decoded[0] @@ -227,7 +228,7 @@ def test_one_inch_replace_calldata_with_weiroll(weiroll_vm, tuple_helper): tuple_bytes = eth_abi.encode_single(struct_layout, params[1]) min_return = eth_abi.encode_single("uint256", 1) tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_bytes, 4, w_weth_balance, True).rawValue()) - tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_bytes, 5, min_return, True).rawValue()) + tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_description, 5, min_return, True).rawValue()) tuple_description = weiroll.ReturnValue(struct_layout, tuple_description.command) w_one_inch = weiroll.WeirollContract(one_inch) @@ -236,9 +237,9 @@ def test_one_inch_replace_calldata_with_weiroll(weiroll_vm, tuple_helper): planner.add(w_one_inch.swap(params[0], tuple_description, params[2]).rawValue()) cmds, state = planner.plan() - weiroll_tx = weiroll_vm.execute( + weiroll_tx = th.execute( cmds, state, {"from": whale, "gas_limit": 8_000_000, "gas_price": 0} ) - assert crv.balanceOf(weiroll_vm) > 0 - print(crv.balanceOf(weiroll_vm)) + assert crv.balanceOf(th) > 0 + print(crv.balanceOf(th)) From a85ce50a77cee81b1463ea47ecfd23a06765603d Mon Sep 17 00:00:00 2001 From: Tonkers Date: Tue, 27 Sep 2022 12:34:39 -0700 Subject: [PATCH 06/10] fix: mech exec --- tests/test_one_inch.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/test_one_inch.py b/tests/test_one_inch.py index 6b919fe..29e01b3 100644 --- a/tests/test_one_inch.py +++ b/tests/test_one_inch.py @@ -184,14 +184,15 @@ def test_one_inch_replace_calldata_amount_2(weiroll_vm): from weiroll import WeirollContract, WeirollPlanner, ReturnValue import requests -def test_one_inch_replace_calldata_with_weiroll(weiroll_vm, tuple_helper): +def test_one_inch_replace_calldata_with_weiroll(): whale = accounts.at("0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True) weth = Contract("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") crv = Contract("0xD533a949740bb3306d119CC777fa900bA034cd52") one_inch = Contract("0x1111111254fb6c44bAC0beD2854e76F90643097d") tuple_helper = Contract("0x06706E366159cEfD3789184686da5cC3f47fB4a2") w_tuple_helper = weiroll.WeirollContract(tuple_helper) - th = accounts.at("0xcADBA199F3AC26F67f660C89d43eB1820b7f7a3b", force=True) + th = Contract("0xcADBA199F3AC26F67f660C89d43eB1820b7f7a3b") + ms = accounts.at("0x2C01B4AD51a67E2d8F02208F54dF9aC4c0B778B6", force=True) planner = WeirollPlanner(th) weth.approve(th.address, Wei("10 ether"), {"from": whale}) @@ -238,7 +239,7 @@ def test_one_inch_replace_calldata_with_weiroll(weiroll_vm, tuple_helper): cmds, state = planner.plan() weiroll_tx = th.execute( - cmds, state, {"from": whale, "gas_limit": 8_000_000, "gas_price": 0} + cmds, state, {"from": ms, "gas_limit": 8_000_000, "gas_price": 0} ) assert crv.balanceOf(th) > 0 From 552704beeb51ece4415a1398fe68b93a22f0d2b9 Mon Sep 17 00:00:00 2001 From: Tonkers Date: Tue, 27 Sep 2022 13:00:51 -0700 Subject: [PATCH 07/10] wip --- tests/test_one_inch.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/tests/test_one_inch.py b/tests/test_one_inch.py index 29e01b3..a3c3b39 100644 --- a/tests/test_one_inch.py +++ b/tests/test_one_inch.py @@ -197,8 +197,8 @@ def test_one_inch_replace_calldata_with_weiroll(): weth.approve(th.address, Wei("10 ether"), {"from": whale}) weth.transfer(th.address, Wei("10 ether"), {"from": whale}) - w_weth_balance = planner.call(weth, "balanceOf", th.address) - w_weth_balance = weiroll.ReturnValue("bytes32", w_weth_balance.command) + # w_weth_balance = planner.call(weth, "balanceOf", th.address) + # w_weth_balance = weiroll.ReturnValue("bytes32", w_weth_balance.command) swap_url = "https://api.1inch.io/v4.0/1/swap" print(th.address) r = requests.get( @@ -217,25 +217,27 @@ def test_one_inch_replace_calldata_with_weiroll(): assert r.ok and r.status_code == 200 tx = r.json()["tx"] + router = tx["to"] - weth.approve(one_inch, 2 ** 256 - 1, {"from": th, "gas_price": 0}) + weth.approve(router, 0, {"from": th, "gas_price": 0}) + weth.approve(router, 2 ** 256 - 1, {"from": th, "gas_price": 0}) decoded = one_inch.decode_input(tx["data"]) func_name = decoded[0] params = decoded[1] print(func_name) - struct_layout = '(address,address,address,address,uint256,uint256,uint256,bytes)' - tuple_bytes = eth_abi.encode_single(struct_layout, params[1]) - min_return = eth_abi.encode_single("uint256", 1) - tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_bytes, 4, w_weth_balance, True).rawValue()) - tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_description, 5, min_return, True).rawValue()) - tuple_description = weiroll.ReturnValue(struct_layout, tuple_description.command) - + # struct_layout = '(address,address,address,address,uint256,uint256,uint256,bytes)' + # tuple_bytes = eth_abi.encode_single(struct_layout, params[1]) + # min_return = eth_abi.encode_single("uint256", 1000*(10**18)) + # tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_bytes, 4, w_weth_balance, True).rawValue()) + # tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_description, 5, min_return, True).rawValue()) + # tuple_description = weiroll.ReturnValue(struct_layout, tuple_description.command) + # + # params[1] = tuple_description w_one_inch = weiroll.WeirollContract(one_inch) - params[1] = tuple_description print(params) - planner.add(w_one_inch.swap(params[0], tuple_description, params[2]).rawValue()) + planner.add(w_one_inch.swap(params[0], params[1], params[2]).rawValue()) cmds, state = planner.plan() weiroll_tx = th.execute( From 7e679431a1ce5cbdc20fce59fb6c556a3b5c46a6 Mon Sep 17 00:00:00 2001 From: Tonkers Date: Tue, 27 Sep 2022 13:13:49 -0700 Subject: [PATCH 08/10] wip --- tests/test_one_inch.py | 47 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/tests/test_one_inch.py b/tests/test_one_inch.py index a3c3b39..aca05ae 100644 --- a/tests/test_one_inch.py +++ b/tests/test_one_inch.py @@ -218,7 +218,7 @@ def test_one_inch_replace_calldata_with_weiroll(): assert r.ok and r.status_code == 200 tx = r.json()["tx"] router = tx["to"] - + print(f'router: {router}') weth.approve(router, 0, {"from": th, "gas_price": 0}) weth.approve(router, 2 ** 256 - 1, {"from": th, "gas_price": 0}) @@ -246,3 +246,48 @@ def test_one_inch_replace_calldata_with_weiroll(): assert crv.balanceOf(th) > 0 print(crv.balanceOf(th)) + +def test_sanity(): + whale = accounts.at("0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True) + weth = Contract("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") + crv = Contract("0xD533a949740bb3306d119CC777fa900bA034cd52") + one_inch = Contract("0x1111111254fb6c44bAC0beD2854e76F90643097d") + th = Contract("0xcADBA199F3AC26F67f660C89d43eB1820b7f7a3b") + + weth.approve(th.address, Wei("10 ether"), {"from": whale}) + weth.transfer(th.address, Wei("10 ether"), {"from": whale}) + + swap_url = "https://api.1inch.io/v4.0/1/swap" + print(th.address) + r = requests.get( + swap_url, + params={ + "fromTokenAddress": weth.address, + "toTokenAddress": crv.address, + "amount": Wei("10 ether"), + "fromAddress": th.address, + "slippage": 5, + "disableEstimate": "true", + "allowPartialFill": "false", + "usePatching": "true" + }, + ) + + assert r.ok and r.status_code == 200 + tx = r.json()["tx"] + router = tx["to"] + print(f'router: {router}') + + weth.approve(router, 0, {"from": th, "gas_price": 0}) + weth.approve(router, 2 ** 256 - 1, {"from": th, "gas_price": 0}) + + decoded = one_inch.decode_input(tx["data"]) + func_name = decoded[0] + params = decoded[1] + print(func_name) + print(params) + + one_inch.swap(params[0], params[1], params[2], {'from': th}) + + assert crv.balanceOf(th) > 0 + print(crv.balanceOf(th)) From 5aefb3a2a4fc127aff29496fa57df5f4e6c7e60a Mon Sep 17 00:00:00 2001 From: Tonkers Date: Tue, 27 Sep 2022 13:15:15 -0700 Subject: [PATCH 09/10] Update test_one_inch.py --- tests/test_one_inch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_one_inch.py b/tests/test_one_inch.py index aca05ae..c42523a 100644 --- a/tests/test_one_inch.py +++ b/tests/test_one_inch.py @@ -287,7 +287,7 @@ def test_sanity(): print(func_name) print(params) - one_inch.swap(params[0], params[1], params[2], {'from': th}) + one_inch.swap(params[0], params[1], params[2], {"from": th, "gas_price": 0}) assert crv.balanceOf(th) > 0 print(crv.balanceOf(th)) From 80e14ddce73ddeaff36ab4be9bdda444614ced03 Mon Sep 17 00:00:00 2001 From: Tonkers Date: Thu, 29 Sep 2022 17:33:22 -0700 Subject: [PATCH 10/10] wip --- contracts/Helpers/RouterLike.sol | 32 +++++ tests/conftest.py | 4 + tests/test_one_inch.py | 221 +++++++++++++++++++------------ tests/test_swaps.py | 1 - tests/test_weiroll.py | 1 - 5 files changed, 172 insertions(+), 87 deletions(-) create mode 100644 contracts/Helpers/RouterLike.sol diff --git a/contracts/Helpers/RouterLike.sol b/contracts/Helpers/RouterLike.sol new file mode 100644 index 0000000..9d70517 --- /dev/null +++ b/contracts/Helpers/RouterLike.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.11; + + +contract RouterLike { + SwapDescription public saved; + SwapDescription public savedSimple; + struct SwapDescription { + address srcToken; + address dstToken; + address payable srcReceiver; + address payable dstReceiver; + uint256 amount; + uint256 minReturnAmount; + uint256 flags; + bytes permit; + } + + function swap( + address caller, + SwapDescription calldata desc, + bytes calldata data + ) public { + saved = desc; + } + + function swapSimple( + SwapDescription calldata desc + ) public { + savedSimple = desc; +} +} diff --git a/tests/conftest.py b/tests/conftest.py index cbbe152..3ae54b7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -96,3 +96,7 @@ def tuple_helper_yul(alice, TupleHelperYul): @pytest.fixture(scope="module") def tuple_helper_vy(alice, TupleHelperVy): yield alice.deploy(TupleHelperVy) + +@pytest.fixture(scope="module") +def router_like(alice, RouterLike): + yield alice.deploy(RouterLike) diff --git a/tests/test_one_inch.py b/tests/test_one_inch.py index c42523a..a78c918 100644 --- a/tests/test_one_inch.py +++ b/tests/test_one_inch.py @@ -2,12 +2,14 @@ from brownie.convert.datatypes import HexString import weiroll -from weiroll import WeirollContract, WeirollPlanner, ReturnValue +from weiroll import WeirollContract, WeirollPlanner, ReturnValue, CommandFlags import requests def test_one_inch(weiroll_vm): - whale = accounts.at("0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True) + whale = accounts.at( + "0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True + ) weth = Contract("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") crv = Contract("0xD533a949740bb3306d119CC777fa900bA034cd52") one_inch = Contract("0x1111111254fb6c44bAC0beD2854e76F90643097d") @@ -31,7 +33,7 @@ def test_one_inch(weiroll_vm): assert r.ok and r.status_code == 200 tx = r.json()["tx"] - weth.approve(one_inch, 2 ** 256 - 1, {"from": weiroll_vm, "gas_price": 0}) + weth.approve(one_inch, 2**256 - 1, {"from": weiroll_vm, "gas_price": 0}) decoded = one_inch.decode_input(tx["data"]) func_name = decoded[0] @@ -48,13 +50,17 @@ def test_one_inch(weiroll_vm): assert crv.balanceOf(weiroll_vm) > 0 -def test_one_inch_replace_calldata_amount(weiroll_vm): - whale = accounts.at("0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True) +def test_one_inch_replace_calldata_amount(): + whale = accounts.at( + "0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True + ) weth = Contract("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") crv = Contract("0xD533a949740bb3306d119CC777fa900bA034cd52") one_inch = Contract("0x1111111254fb6c44bAC0beD2854e76F90643097d") + th = Contract("0xcADBA199F3AC26F67f660C89d43eB1820b7f7a3b") + ms = accounts.at("0x2C01B4AD51a67E2d8F02208F54dF9aC4c0B778B6", force=True) - weth.transfer(weiroll_vm.address, Wei("10 ether"), {"from": whale}) + weth.transfer(th.address, Wei("10 ether"), {"from": whale}) swap_url = "https://api.1inch.io/v4.0/1/swap" r = requests.get( @@ -63,56 +69,52 @@ def test_one_inch_replace_calldata_amount(weiroll_vm): "fromTokenAddress": weth.address, "toTokenAddress": crv.address, "amount": Wei("10 ether"), - "fromAddress": weiroll_vm.address, + "fromAddress": th.address, "slippage": 5, "disableEstimate": "true", "allowPartialFill": "false", + "usePatching": "true", }, ) assert r.ok and r.status_code == 200 tx = r.json()["tx"] - weth.approve(one_inch, 2 ** 256 - 1, {"from": weiroll_vm, "gas_price": 0}) + weth.approve(one_inch, 2**256 - 1, {"from": th, "gas_price": 0}) decoded = one_inch.decode_input(tx["data"]) func_name = decoded[0] params = decoded[1] - calldata = params[2] # change inputs wei9 = Wei("9 ether") params[1][4] = wei9 params[1][5] = 1 - # Operations to edit decoded swap data - # convert dec to hex (0xHexDec) -> (0x00...HexDec) -> (00..HexDec) string - hex10 = HexString(hex(Wei("10 ether")), "bytes32").hex() - hex9 = HexString(hex(wei9), "bytes32").hex() - - # HexString to string - calldata_str = calldata.hex() - - # string replacement - replaced = calldata_str.replace(hex10, hex9) - - # back to hexstring - params[2] = HexString(replaced, "bytes") - - planner = WeirollPlanner(weiroll_vm) + planner = WeirollPlanner(th) + # w_one_inch = weiroll.WeirollContract(one_inch) + # print(f'{func_name}\n{params}') + # planner.add(w_one_inch.swap(params[0], params[1], params[2])) planner.call(one_inch, func_name, *params) cmds, state = planner.plan() - weiroll_tx = weiroll_vm.execute( - cmds, state, {"from": whale, "gas_limit": 8_000_000, "gas_price": 0} + print(f"cmds: {cmds}") + print(f"state: {state}") + + weiroll_tx = th.execute( + cmds, state, {"from": ms, "gas_limit": 8_000_000, "gas_price": 0} ) - assert crv.balanceOf(weiroll_vm) > 0 - print(crv.balanceOf(weiroll_vm)) + assert crv.balanceOf(th) > 0 + print(crv.balanceOf(th)) + assert weth.balanceOf(th) == 1 * 10**18 + assert False def test_one_inch_replace_calldata_amount_2(weiroll_vm): - whale = accounts.at("0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True) + whale = accounts.at( + "0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True + ) weth = Contract("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") crv = Contract("0xD533a949740bb3306d119CC777fa900bA034cd52") one_inch = Contract("0x1111111254fb6c44bAC0beD2854e76F90643097d") @@ -136,7 +138,7 @@ def test_one_inch_replace_calldata_amount_2(weiroll_vm): assert r.ok and r.status_code == 200 tx = r.json()["tx"] - weth.approve(one_inch, 2 ** 256 - 1, {"from": weiroll_vm, "gas_price": 0}) + weth.approve(one_inch, 2**256 - 1, {"from": weiroll_vm, "gas_price": 0}) decoded = one_inch.decode_input(tx["data"]) func_name = decoded[0] @@ -184,21 +186,31 @@ def test_one_inch_replace_calldata_amount_2(weiroll_vm): from weiroll import WeirollContract, WeirollPlanner, ReturnValue import requests -def test_one_inch_replace_calldata_with_weiroll(): - whale = accounts.at("0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True) +# def test_a_b(): +# cmds, staste = test_one_inch_replace_calldata_with_weiroll(True) +# cmds2, staste2 = test_one_inch_replace_calldata_with_weiroll(False) +# +# assert False + + +def test_one_inch_replace_amount_with_weiroll(router_like): + whale = accounts.at( + "0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True + ) weth = Contract("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") crv = Contract("0xD533a949740bb3306d119CC777fa900bA034cd52") one_inch = Contract("0x1111111254fb6c44bAC0beD2854e76F90643097d") tuple_helper = Contract("0x06706E366159cEfD3789184686da5cC3f47fB4a2") - w_tuple_helper = weiroll.WeirollContract(tuple_helper) + w_tuple_helper = weiroll.WeirollContract(tuple_helper, CommandFlags.CALL) th = Contract("0xcADBA199F3AC26F67f660C89d43eB1820b7f7a3b") ms = accounts.at("0x2C01B4AD51a67E2d8F02208F54dF9aC4c0B778B6", force=True) planner = WeirollPlanner(th) - weth.approve(th.address, Wei("10 ether"), {"from": whale}) - weth.transfer(th.address, Wei("10 ether"), {"from": whale}) - # w_weth_balance = planner.call(weth, "balanceOf", th.address) - # w_weth_balance = weiroll.ReturnValue("bytes32", w_weth_balance.command) + weth.approve(th.address, Wei("9 ether"), {"from": whale}) + weth.transfer(th.address, Wei("9 ether"), {"from": whale}) + + w_weth_balance = planner.call(weth, "balanceOf", th.address) + w_weth_balance = weiroll.ReturnValue("bytes32", w_weth_balance.command) swap_url = "https://api.1inch.io/v4.0/1/swap" print(th.address) r = requests.get( @@ -211,83 +223,122 @@ def test_one_inch_replace_calldata_with_weiroll(): "slippage": 5, "disableEstimate": "true", "allowPartialFill": "false", - "usePatching": "true" + "usePatching": "true", }, ) assert r.ok and r.status_code == 200 tx = r.json()["tx"] router = tx["to"] - print(f'router: {router}') + print(f"router: {router}") weth.approve(router, 0, {"from": th, "gas_price": 0}) - weth.approve(router, 2 ** 256 - 1, {"from": th, "gas_price": 0}) + weth.approve(router, 2**256 - 1, {"from": th, "gas_price": 0}) decoded = one_inch.decode_input(tx["data"]) func_name = decoded[0] params = decoded[1] - print(func_name) - - # struct_layout = '(address,address,address,address,uint256,uint256,uint256,bytes)' - # tuple_bytes = eth_abi.encode_single(struct_layout, params[1]) - # min_return = eth_abi.encode_single("uint256", 1000*(10**18)) - # tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_bytes, 4, w_weth_balance, True).rawValue()) - # tuple_description = planner.add(w_tuple_helper.replaceElement(tuple_description, 5, min_return, True).rawValue()) - # tuple_description = weiroll.ReturnValue(struct_layout, tuple_description.command) - # - # params[1] = tuple_description - w_one_inch = weiroll.WeirollContract(one_inch) + params[1][5] = 1 # minReturn + + struct_layout = ( + "(address,address,address,address,uint256,uint256,uint256,bytes)" + ) + tuple_bytes = eth_abi.encode_single(struct_layout, params[1]) + tuple_raw = planner.add( + w_tuple_helper.replaceElement( + tuple_bytes, 4, w_weth_balance, True + ).rawValue() + ) + + tuple_raw = weiroll.ReturnValue( + struct_layout, tuple_raw.command + ) + params[1] = tuple_raw + print(params) - planner.add(w_one_inch.swap(params[0], params[1], params[2]).rawValue()) + + w_router = weiroll.WeirollContract.createContract(router_like) + planner.call(router_like, "swapSimple", params[1]) + # planner.add(w_router.swap(params[0], params[1], params[2])) cmds, state = planner.plan() + weiroll_tx = th.execute( cmds, state, {"from": ms, "gas_limit": 8_000_000, "gas_price": 0} ) assert crv.balanceOf(th) > 0 print(crv.balanceOf(th)) + assert False -def test_sanity(): - whale = accounts.at("0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True) +def test_tuple_replace(): + whale = accounts.at( + "0x57757E3D981446D585Af0D9Ae4d7DF6D64647806", force=True + ) weth = Contract("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") crv = Contract("0xD533a949740bb3306d119CC777fa900bA034cd52") - one_inch = Contract("0x1111111254fb6c44bAC0beD2854e76F90643097d") + tuple_helper = Contract("0x06706E366159cEfD3789184686da5cC3f47fB4a2") + w_tuple_helper = weiroll.WeirollContract(tuple_helper) th = Contract("0xcADBA199F3AC26F67f660C89d43eB1820b7f7a3b") + ms = accounts.at("0x2C01B4AD51a67E2d8F02208F54dF9aC4c0B778B6", force=True) + planner = WeirollPlanner(th) - weth.approve(th.address, Wei("10 ether"), {"from": whale}) - weth.transfer(th.address, Wei("10 ether"), {"from": whale}) + weth_balance_whale = weth.balanceOf(whale) + + # transfer all of whale's weth to th + weth.approve(th.address, 2**256 - 1, {"from": whale}) + weth.transfer(th.address, weth.balanceOf(whale), {"from": whale}) + + # get weiroll amount + w_weth_balance = planner.call(weth, "balanceOf", th.address) + w_weth_balance = weiroll.ReturnValue("bytes32", w_weth_balance.command) + + tuple = [ + crv.address, + crv.address, + crv.address, + crv.address, + 999, + 1, + 999, + b"0x0", + ] + struct_layout = ( + "(address,address,address,address,uint256,uint256,uint256,bytes)" + ) + tuple_bytes = eth_abi.encode_single(struct_layout, tuple) - swap_url = "https://api.1inch.io/v4.0/1/swap" - print(th.address) - r = requests.get( - swap_url, - params={ - "fromTokenAddress": weth.address, - "toTokenAddress": crv.address, - "amount": Wei("10 ether"), - "fromAddress": th.address, - "slippage": 5, - "disableEstimate": "true", - "allowPartialFill": "false", - "usePatching": "true" - }, + # replace amount with w_amount + tuple_description_bytes = planner.add( + w_tuple_helper.replaceElement( + tuple_bytes, 4, w_weth_balance, True + ).rawValue() ) - assert r.ok and r.status_code == 200 - tx = r.json()["tx"] - router = tx["to"] - print(f'router: {router}') + print(tuple_description_bytes) - weth.approve(router, 0, {"from": th, "gas_price": 0}) - weth.approve(router, 2 ** 256 - 1, {"from": th, "gas_price": 0}) + tuple_description = weiroll.ReturnValue( + struct_layout, tuple_description_bytes.command + ) - decoded = one_inch.decode_input(tx["data"]) - func_name = decoded[0] - params = decoded[1] - print(func_name) - print(params) + # do some transfers in order to verify amount was correctly replaced + actual_balance = planner.add( + w_tuple_helper.getElement(tuple_description_bytes, 4) + ) + actual_minReturn = planner.add( + w_tuple_helper.getElement(tuple_description_bytes, 5) + ) + actual_balance = weiroll.ReturnValue("uint256", actual_balance.command) + actual_minReturn = weiroll.ReturnValue("uint256", actual_minReturn.command) + planner.call(weth, "transfer", ms.address, actual_balance) + planner.call(crv, "approve", ms.address, actual_minReturn) - one_inch.swap(params[0], params[1], params[2], {"from": th, "gas_price": 0}) + cmds, state = planner.plan() - assert crv.balanceOf(th) > 0 - print(crv.balanceOf(th)) + weth_balance_ms = weth.balanceOf(ms) + weiroll_tx = th.execute( + cmds, state, {"from": ms, "gas_limit": 8_000_000, "gas_price": 0} + ) + + # assert replacing amount w/ w_amount worked + assert weth.balanceOf(ms) - weth_balance_ms == weth_balance_whale + assert crv.allowance(th, ms) == 1 diff --git a/tests/test_swaps.py b/tests/test_swaps.py index a52ab8d..e61375b 100644 --- a/tests/test_swaps.py +++ b/tests/test_swaps.py @@ -83,7 +83,6 @@ def test_swaps(accounts, weiroll_vm): ) -@pytest.mark.skip("broken") def test_balancer_swap(accounts, weiroll_vm, tuple_helper): bal_whale = accounts.at("0xF977814e90dA44bFA03b6295A0616a897441aceC", force=True) diff --git a/tests/test_weiroll.py b/tests/test_weiroll.py index 8e178e0..961482f 100644 --- a/tests/test_weiroll.py +++ b/tests/test_weiroll.py @@ -52,7 +52,6 @@ def test_weiroll_planner_simple_program(alice, math): assert state[0] == eth_abi.encode_single("uint", 1) assert state[1] == eth_abi.encode_single("uint", 2) - def test_weiroll_deduplicates_identical_literals(alice, math): planner = weiroll.WeirollPlanner(alice) planner.add(math.add(1, 1))