Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2df147d

Browse files
committed
feat: wip work on custom routes for v2 and v3
1 parent42900d1 commit2df147d

File tree

2 files changed

+94
-70
lines changed

2 files changed

+94
-70
lines changed

‎tests/test_uniswap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def client(request, web3: Web3, ganache: GanacheInstance):
4343
ganache.eth_privkey,
4444
web3=web3,
4545
version=request.param,
46-
use_estimate_gas=False,# see note in _build_and_send_tx
46+
use_estimate_gas=True,# see note in _build_and_send_tx
4747
)
4848

4949

‎uniswap/uniswap.py

Lines changed: 93 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def get_price_input(
182182
token1:AddressLike,# output token
183183
qty:int,
184184
fee:int=None,
185-
route:Optional[List[AddressLike]]=None,
185+
route:List[AddressLike]=None,
186186
)->int:
187187
"""Given `qty` amount of the input `token0`, returns the maximum output amount of output `token1`."""
188188
iffeeisNone:
@@ -203,7 +203,7 @@ def get_price_output(
203203
token1:AddressLike,
204204
qty:int,
205205
fee:int=None,
206-
route:Optional[List[AddressLike]]=None,
206+
route:List[AddressLike]=None,
207207
)->int:
208208
"""Returns the minimum amount of `token0` required to buy `qty` amount of `token1`."""
209209
iffeeisNone:
@@ -264,7 +264,7 @@ def _get_token_token_input_price(
264264
token1:AddressLike,# output token
265265
qty:int,
266266
fee:int,
267-
route:Optional[List[AddressLike]]=None,
267+
route:List[AddressLike]=None,
268268
)->int:
269269
"""
270270
Public price (i.e. amount of output token received) for token to token trades with an exact input.
@@ -581,68 +581,93 @@ def _token_to_eth_swap_input(
581581
function=token_funcs.tokenToEthTransferInput(*func_params)
582582
returnself._build_and_send_tx(function)
583583
elifself.version==2:
584-
ifrecipientisNone:
585-
recipient=self.address
586-
amount_out_min=int(
587-
(1-slippage)*self._get_token_eth_input_price(input_token,qty,fee)
588-
)
589-
iffee_on_transfer:
590-
func= (
591-
self.router.functions.swapExactTokensForETHSupportingFeeOnTransferTokens
592-
)
593-
else:
594-
func=self.router.functions.swapExactTokensForETH
595-
returnself._build_and_send_tx(
596-
func(
597-
qty,
598-
amount_out_min,
599-
[input_token,self.get_weth_address()],
600-
recipient,
601-
self._deadline(),
602-
),
584+
returnself._token_to_eth_swap_input_v2(
585+
input_token,qty,recipient,fee,slippage,fee_on_transfer
603586
)
604587
elifself.version==3:
605-
ifrecipientisNone:
606-
recipient=self.address
607-
608588
iffee_on_transfer:
609589
raiseException("fee on transfer not supported by Uniswap v3")
610590

611-
output_token=self.get_weth_address()
612-
min_tokens_bought=int(
613-
(1-slippage)
614-
*self._get_token_eth_input_price(input_token,qty,fee=fee)
591+
returnself._token_to_eth_swap_input_v3(
592+
input_token,qty,recipient,fee,slippage
615593
)
616-
sqrtPriceLimitX96=0
594+
else:
595+
raiseValueError
617596

618-
swap_data=self.router.encodeABI(
619-
fn_name="exactInputSingle",
620-
args=[
621-
(
622-
input_token,
623-
output_token,
624-
fee,
625-
ETH_ADDRESS,
626-
self._deadline(),
627-
qty,
628-
min_tokens_bought,
629-
sqrtPriceLimitX96,
630-
)
631-
],
597+
def_token_to_eth_swap_input_v2(
598+
self,
599+
input_token:AddressLike,
600+
qty:int,
601+
recipient:Optional[AddressLike],
602+
fee:int,
603+
slippage:float,
604+
fee_on_transfer:bool,
605+
)->HexBytes:
606+
ifrecipientisNone:
607+
recipient=self.address
608+
amount_out_min=int(
609+
(1-slippage)*self._get_token_eth_input_price(input_token,qty,fee)
610+
)
611+
iffee_on_transfer:
612+
func= (
613+
self.router.functions.swapExactTokensForETHSupportingFeeOnTransferTokens
632614
)
615+
else:
616+
func=self.router.functions.swapExactTokensForETH
617+
returnself._build_and_send_tx(
618+
func(
619+
qty,
620+
amount_out_min,
621+
[input_token,self.get_weth_address()],
622+
recipient,
623+
self._deadline(),
624+
),
625+
)
633626

634-
unwrap_data=self.router.encodeABI(
635-
fn_name="unwrapWETH9",args=[min_tokens_bought,recipient]
636-
)
627+
def_token_to_eth_swap_input_v3(
628+
self,
629+
input_token:AddressLike,
630+
qty:int,
631+
recipient:Optional[AddressLike],
632+
fee:int,
633+
slippage:float,
634+
)->HexBytes:
635+
"""NOTE: Should always be called via the dispatcher `_token_to_eth_swap_input`"""
636+
ifrecipientisNone:
637+
recipient=self.address
637638

638-
# Multicall
639-
returnself._build_and_send_tx(
640-
self.router.functions.multicall([swap_data,unwrap_data]),
641-
self._get_tx_params(),
642-
)
639+
output_token=self.get_weth_address()
640+
min_tokens_bought=int(
641+
(1-slippage)*self._get_token_eth_input_price(input_token,qty,fee=fee)
642+
)
643+
sqrtPriceLimitX96=0
644+
645+
swap_data=self.router.encodeABI(
646+
fn_name="exactInputSingle",
647+
args=[
648+
(
649+
input_token,
650+
output_token,
651+
fee,
652+
ETH_ADDRESS,
653+
self._deadline(),
654+
qty,
655+
min_tokens_bought,
656+
sqrtPriceLimitX96,
657+
)
658+
],
659+
)
643660

644-
else:
645-
raiseValueError
661+
# NOTE: This will probably lead to dust WETH accumulation
662+
unwrap_data=self.router.encodeABI(
663+
fn_name="unwrapWETH9",args=[min_tokens_bought,recipient]
664+
)
665+
666+
# Multicall
667+
returnself._build_and_send_tx(
668+
self.router.functions.multicall([swap_data,unwrap_data]),
669+
self._get_tx_params(),
670+
)
646671

647672
def_token_to_token_swap_input(
648673
self,
@@ -1111,13 +1136,17 @@ def _build_and_send_tx(
11111136
# `use_estimate_gas` needs to be True for networks like Arbitrum (can't assume 250000 gas),
11121137
# but it breaks tests for unknown reasons because estimateGas takes forever on some tx's.
11131138
# Maybe an issue with ganache? (got GC warnings once...)
1139+
1140+
# In case gas estimation is disabled.
1141+
# Without this set before gas estimation, it can lead to ganache stack overflow.
1142+
# See: https://github.com/trufflesuite/ganache/issues/985#issuecomment-998937085
1143+
transaction["gas"]=Wei(250000)
1144+
11141145
ifself.use_estimate_gas:
11151146
# The Uniswap V3 UI uses 20% margin for transactions
11161147
transaction["gas"]=Wei(
11171148
int(self.w3.eth.estimate_gas(transaction)*1.2)
11181149
)
1119-
else:
1120-
transaction["gas"]=Wei(250000)
11211150

11221151
signed_txn=self.w3.eth.account.sign_transaction(
11231152
transaction,private_key=self.private_key
@@ -1225,11 +1254,11 @@ def get_token(self, address: AddressLike, abi_name: str = "erc20") -> ERC20Token
12251254
raiseInvalidToken(address)
12261255
try:
12271256
name=_name.decode()
1228-
except:
1257+
exceptException:# FIXME: Be more precise about exception to catch
12291258
name=_name
12301259
try:
12311260
symbol=_symbol.decode()
1232-
except:
1261+
exceptException:# FIXME: Be more precise about exception to catch
12331262
symbol=_symbol
12341263
returnERC20Token(symbol,address,name,decimals)
12351264

@@ -1256,11 +1285,11 @@ def get_raw_price(
12561285
iftoken_out==ETH_ADDRESS:
12571286
token_out=self.get_weth_address()
12581287

1288+
params:Tuple[ChecksumAddress,ChecksumAddress]= (
1289+
self.w3.toChecksumAddress(token_in),
1290+
self.w3.toChecksumAddress(token_out),
1291+
)
12591292
ifself.version==2:
1260-
params:Iterable[Union[ChecksumAddress,Optional[int]]]= [
1261-
self.w3.toChecksumAddress(token_in),
1262-
self.w3.toChecksumAddress(token_out),
1263-
]
12641293
pair_token=self.factory_contract.functions.getPair(*params).call()
12651294
token_in_erc20=_load_contract_erc20(
12661295
self.w3,self.w3.toChecksumAddress(token_in)
@@ -1286,12 +1315,7 @@ def get_raw_price(
12861315

12871316
raw_price=token_out_balance/token_in_balance
12881317
else:
1289-
params= [
1290-
self.w3.toChecksumAddress(token_in),
1291-
self.w3.toChecksumAddress(token_out),
1292-
fee,
1293-
]
1294-
pool_address=self.factory_contract.functions.getPool(*params).call()
1318+
pool_address=self.factory_contract.functions.getPool(*params,fee).call()
12951319
pool_contract=_load_contract(
12961320
self.w3,abi_name="uniswap-v3/pool",address=pool_address
12971321
)
@@ -1317,7 +1341,7 @@ def estimate_price_impact(
13171341
token_out:AddressLike,
13181342
amount_in:int,
13191343
fee:int=None,
1320-
route:Optional[List[AddressLike]]=None,
1344+
route:List[AddressLike]=None,
13211345
)->float:
13221346
"""
13231347
Returns the estimated price impact as a positive float (0.01 = 1%).

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp