@@ -45,6 +45,16 @@ class Uniswap:
45
45
Wrapper around Uniswap contracts.
46
46
"""
47
47
48
+ address : AddressLike
49
+ version : int
50
+
51
+ w3 : Web3
52
+ netid : int
53
+ netname : str
54
+
55
+ default_slippage : float
56
+ use_estimate_gas : bool
57
+
48
58
def __init__ (
49
59
self ,
50
60
address : Union [AddressLike , str , None ],
@@ -53,6 +63,8 @@ def __init__(
53
63
web3 : Web3 = None ,
54
64
version : int = 1 ,
55
65
default_slippage : float = 0.01 ,
66
+ use_estimate_gas : bool = True ,
67
+ # use_eip1559: bool = True,
56
68
factory_contract_addr : str = None ,
57
69
router_contract_addr : str = None ,
58
70
) -> None :
@@ -66,7 +78,7 @@ def __init__(
66
78
:param factory_contract_addr: Can be optionally set to override the address of the factory contract.
67
79
:param router_contract_addr: Can be optionally set to override the address of the router contract (v2 only).
68
80
"""
69
- self .address : AddressLike = _str_to_addr (
81
+ self .address = _str_to_addr (
70
82
address or "0x0000000000000000000000000000000000000000"
71
83
)
72
84
self .private_key = (
@@ -78,22 +90,23 @@ def __init__(
78
90
79
91
# TODO: Write tests for slippage
80
92
self .default_slippage = default_slippage
93
+ self .use_estimate_gas = use_estimate_gas
81
94
82
95
if web3 :
83
96
self .w3 = web3
84
97
else :
85
98
# Initialize web3. Extra provider for testing.
86
- self . provider = provider or os . environ [ "PROVIDER" ]
87
- self . w3 = Web3 (
88
- Web3 .HTTPProvider (self . provider , request_kwargs = {"timeout" : 60 })
89
- )
90
-
91
- netid = int (self .w3 .net .version )
92
- if netid in _netid_to_name :
93
- self .network = _netid_to_name [netid ]
99
+ if not provider :
100
+ provider = os . environ [ "PROVIDER" ]
101
+ self . w3 = Web3 ( Web3 .HTTPProvider (provider , request_kwargs = {"timeout" : 60 }) )
102
+
103
+ # Cache netid to avoid extra RPC calls
104
+ self . netid = int (self .w3 .net .version )
105
+ if self . netid in _netid_to_name :
106
+ self .netname = _netid_to_name [self . netid ]
94
107
else :
95
- raise Exception (f"Unknown netid: { netid } " )
96
- logger .info (f"Using { self .w3 } ('{ self .network } ' )" )
108
+ raise Exception (f"Unknown netid: { self . netid } " )
109
+ logger .info (f"Using { self .w3 } ('{ self .netname } ', netid: { self . netid } )" )
97
110
98
111
self .last_nonce : Nonce = self .w3 .eth .get_transaction_count (self .address )
99
112
@@ -102,14 +115,14 @@ def __init__(
102
115
# max_approval_check checks that current approval is above a reasonable number
103
116
# The program cannot check for max_approval each time because it decreases
104
117
# with each trade.
105
- self . max_approval_hex = f"0x{ 64 * 'f' } "
106
- self .max_approval_int = int (self . max_approval_hex , 16 )
107
- self . max_approval_check_hex = f"0x{ 15 * '0' } { 49 * 'f' } "
108
- self .max_approval_check_int = int (self . max_approval_check_hex , 16 )
118
+ max_approval_hex = f"0x{ 64 * 'f' } "
119
+ self .max_approval_int = int (max_approval_hex , 16 )
120
+ max_approval_check_hex = f"0x{ 15 * '0' } { 49 * 'f' } "
121
+ self .max_approval_check_int = int (max_approval_check_hex , 16 )
109
122
110
123
if self .version == 1 :
111
124
if factory_contract_addr is None :
112
- factory_contract_addr = _factory_contract_addresses_v1 [self .network ]
125
+ factory_contract_addr = _factory_contract_addresses_v1 [self .netname ]
113
126
114
127
self .factory_contract = _load_contract (
115
128
self .w3 ,
@@ -118,11 +131,11 @@ def __init__(
118
131
)
119
132
elif self .version == 2 :
120
133
if router_contract_addr is None :
121
- router_contract_addr = _router_contract_addresses_v2 [self .network ]
134
+ router_contract_addr = _router_contract_addresses_v2 [self .netname ]
122
135
self .router_address : AddressLike = _str_to_addr (router_contract_addr )
123
136
124
137
if factory_contract_addr is None :
125
- factory_contract_addr = _factory_contract_addresses_v2 [self .network ]
138
+ factory_contract_addr = _factory_contract_addresses_v2 [self .netname ]
126
139
self .factory_contract = _load_contract (
127
140
self .w3 ,
128
141
abi_name = "uniswap-v2/factory" ,
@@ -1085,8 +1098,19 @@ def _build_and_send_tx(
1085
1098
if not tx_params :
1086
1099
tx_params = self ._get_tx_params ()
1087
1100
transaction = function .buildTransaction (tx_params )
1088
- # Uniswap3 uses 20% margin for transactions
1089
- transaction ["gas" ] = Wei (int (self .w3 .eth .estimate_gas (transaction ) * 1.2 ))
1101
+
1102
+ if "gas" not in tx_params :
1103
+ # `use_estimate_gas` needs to be True for networks like Arbitrum (can't assume 250000 gas),
1104
+ # but it breaks tests for unknown reasons because estimateGas takes forever on some tx's.
1105
+ # Maybe an issue with ganache? (got GC warnings once...)
1106
+ if self .use_estimate_gas :
1107
+ # The Uniswap V3 UI uses 20% margin for transactions
1108
+ transaction ["gas" ] = Wei (
1109
+ int (self .w3 .eth .estimate_gas (transaction ) * 1.2 )
1110
+ )
1111
+ else :
1112
+ transaction ["gas" ] = Wei (250000 )
1113
+
1090
1114
signed_txn = self .w3 .eth .account .sign_transaction (
1091
1115
transaction , private_key = self .private_key
1092
1116
)
@@ -1098,15 +1122,18 @@ def _build_and_send_tx(
1098
1122
logger .debug (f"nonce: { tx_params ['nonce' ]} " )
1099
1123
self .last_nonce = Nonce (tx_params ["nonce" ] + 1 )
1100
1124
1101
- def _get_tx_params (self , value : Wei = Wei (0 )) -> TxParams :
1125
+ def _get_tx_params (self , value : Wei = Wei (0 ), gas : Wei = None ) -> TxParams :
1102
1126
"""Get generic transaction parameters."""
1103
- return {
1127
+ params : TxParams = {
1104
1128
"from" : _addr_to_str (self .address ),
1105
1129
"value" : value ,
1106
1130
"nonce" : max (
1107
1131
self .last_nonce , self .w3 .eth .get_transaction_count (self .address )
1108
1132
),
1109
1133
}
1134
+ if gas :
1135
+ params ["gas" ] = gas
1136
+ return params
1110
1137
1111
1138
# ------ Price Calculation Utils ---------------------------------------------------
1112
1139
def _calculate_max_input_token (
@@ -1255,14 +1282,12 @@ def _get_token_addresses(self) -> Dict[str, ChecksumAddress]:
1255
1282
Returns a dict with addresses for tokens for the current net.
1256
1283
Used in testing.
1257
1284
"""
1258
- netid = int (self .w3 .net .version )
1259
- netname = _netid_to_name [netid ]
1260
- if netname == "mainnet" :
1285
+ if self .netname == "mainnet" :
1261
1286
return tokens
1262
- elif netname == "rinkeby" :
1287
+ elif self . netname == "rinkeby" :
1263
1288
return tokens_rinkeby
1264
1289
else :
1265
- raise Exception (f"Unknown net '{ netname } '" )
1290
+ raise Exception (f"Unknown net '{ self . netname } '" )
1266
1291
1267
1292
# ---- Old v1 utils ----
1268
1293
0 commit comments