Skip to content

Commit 2bd763b

Browse files
authored
Add script to swap USDS to USDC on the OUSD Vault (#2696)
* Add script to swap USDS to USDC on the OUSD Vault * Set default strategy to address(0) * Add USDT script
1 parent b23e175 commit 2bd763b

File tree

7 files changed

+140
-38
lines changed

7 files changed

+140
-38
lines changed

brownie/addresses.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
FLUX_STRAT = '0x76bf500b6305dc4ea851384d3d5502f1c7a0ed44'
4646
MAKER_DSR_STRAT = '0x6b69B755C629590eD59618A2712d8a2957CA98FC'
47-
47+
MAKER_SSR_STRAT = '0x5Bd9AF9c2506D29B6d79cB878284A270190EaEAa'
4848
MORPHO_GAUNTLET_PRIME_USDC_STRAT = '0x2b8f37893ee713a4e9ff0ceb79f27539f20a32a1'
4949
MORPHO_GAUNTLET_PRIME_USDT_STRAT = '0xe3ae7c80a1b02ccd3fb0227773553aeb14e32f26'
5050
OUSD_CURVE_AMO_STRAT = "0x26a02ec47ACC2A3442b757F45E0A82B8e993Ce11"
@@ -153,7 +153,7 @@
153153
FRXETH = '0x5e8422345238f34275888049021821e8e08caa1f'
154154
RETH = '0xae78736Cd615f374D3085123A210448E74Fc6393'
155155
SSV = '0x9d65ff81a3c488d585bbfb0bfe3c7707c7917f54'
156-
156+
USDS = '0xdc035d45d973e3ec169d2276ddab16f1e407384f'
157157

158158
THREEPOOL_LP = '0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490'
159159
OUSD_METAPOOL = '0x87650D7bbfC3A9F10587d7778206671719d9910D'

brownie/collateralSwap.py

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# 2 = 2%
2121
MAX_PRICE_DEVIATION = 2
2222

23-
OUSD_ASSET_ADDRESSES = (DAI, USDT, USDC)
23+
OUSD_ASSET_ADDRESSES = (USDS, USDT, USDC)
2424

2525
def get_1inch_swap(
2626
from_token,
@@ -29,9 +29,11 @@ def get_1inch_swap(
2929
slippage,
3030
allowPartialFill,
3131
min_expected_amount,
32+
protocols = "",
3233
):
3334
vault_addr = VAULT_PROXY_ADDRESS if from_token in OUSD_ASSET_ADDRESSES else VAULT_OETH_PROXY_ADDRESS
3435
c_vault_core = vault_core if from_token in OUSD_ASSET_ADDRESSES else oeth_vault_core
36+
c_vault_admin = vault_admin if from_token in OUSD_ASSET_ADDRESSES else vault_oeth_admin
3537

3638
router_1inch = load_contract('router_1inch_v5', ROUTER_1INCH_V5)
3739
SWAP_SELECTOR = "0x12aa3caf" #swap(address,(address,address,address,address,uint256,uint256,uint256),bytes,bytes)
@@ -45,6 +47,7 @@ def get_1inch_swap(
4547
slippage=slippage,
4648
from_address=swapper_address.lower(),
4749
to_address=vault_addr.lower(),
50+
protocols=protocols,
4851
)
4952

5053
input_decoded = router_1inch.decode_input(result.input)
@@ -60,7 +63,7 @@ def get_1inch_swap(
6063
else:
6164
raise Exception("Unrecognized 1Inch swap selector {}".format(selector))
6265

63-
swap_collateral_data = c_vault_core.swapCollateral.encode_input(
66+
swap_collateral_data = c_vault_admin.swapCollateral.encode_input(
6467
from_token.lower(),
6568
to_token.lower(),
6669
"%.0f" % from_amount,
@@ -115,39 +118,40 @@ def get_oracle_router_quote(from_token, to_token, from_amount):
115118
# 2 = 2%
116119
# - partial_fill -> are partial fills allowed
117120
# - dry_run -> If set to True, doesn't run the tx against the active network
118-
def build_swap_tx(from_token, to_token, from_amount, max_slippage, allow_partial_fill, dry_run=True):
121+
def build_swap_tx(from_token, to_token, from_amount, max_slippage, allow_partial_fill, dry_run=True, protocols=""):
119122
if COINMARKETCAP_API_KEY is None:
120123
raise Exception("Set coinmarketcap api key by setting CMC_API_KEY variable. Free plan key will suffice: https://coinmarketcap.com/api/pricing/")
121124

122125
c_vault_core = vault_core if from_token in OUSD_ASSET_ADDRESSES else oeth_vault_core
126+
c_vault_admin = vault_admin if from_token in OUSD_ASSET_ADDRESSES else vault_oeth_admin
123127
min_slippage_amount = scale_amount(WETH, from_token, 10**18) # 1 token of from_token (like 1WETH, 1DAI or 1USDT)
124-
quote_1inch = get_1inch_quote(from_token, to_token, from_amount)
125-
quote_1inch_min_swap_amount_price = get_1inch_quote(from_token, to_token, min_slippage_amount)
128+
quote_1inch = get_1inch_quote(from_token, to_token, from_amount, protocols=protocols)
129+
quote_1inch_min_swap_amount_price = get_1inch_quote(from_token, to_token, min_slippage_amount, protocols=protocols)
126130
quote_1inch_min_swap_amount = from_amount * quote_1inch_min_swap_amount_price / min_slippage_amount
127-
quote_oracles = get_oracle_router_quote(from_token, to_token, from_amount)
128-
quote_coingecko = get_coingecko_quote(from_token, to_token, from_amount)
129-
quote_cmc = get_cmc_quote(from_token, to_token, from_amount)
131+
# quote_oracles = get_oracle_router_quote(from_token, to_token, from_amount)
132+
# quote_coingecko = get_coingecko_quote(from_token, to_token, from_amount)
133+
# quote_cmc = get_cmc_quote(from_token, to_token, from_amount)
130134

131135
# subtract the max slippage from minimum slippage query
132136
min_tokens_with_slippage = scale_amount(from_token, to_token, from_amount * quote_1inch_min_swap_amount_price * (100 - max_slippage) / 100 / min_slippage_amount)
133-
coingecko_to_1inch_diff = (quote_1inch - quote_coingecko) / quote_1inch
134-
oracle_to_1inch_diff = (quote_1inch - quote_oracles) / quote_1inch
135-
cmc_to_1inch_diff = (quote_1inch - quote_cmc) / quote_1inch
137+
# coingecko_to_1inch_diff = (quote_1inch - quote_coingecko) / quote_1inch
138+
# oracle_to_1inch_diff = (quote_1inch - quote_oracles) / quote_1inch
139+
# cmc_to_1inch_diff = (quote_1inch - quote_cmc) / quote_1inch
136140

137141
actual_slippage = (quote_1inch_min_swap_amount - quote_1inch) / quote_1inch
138142

139143
print("------ Price Quotes ------")
140144
print("1Inch expected tokens: {:.6f}".format(scale_amount(to_token, 'human', quote_1inch)))
141145
print("1Inch expected tokens (no slippage): {:.6f}".format(scale_amount(to_token, 'human', quote_1inch_min_swap_amount)))
142-
print("Oracle expected tokens: {:.6f}".format(scale_amount(to_token, 'human', quote_oracles)))
143-
print("Coingecko expected tokens: {:.6f}".format(scale_amount(to_token, 'human', quote_coingecko)))
144-
print("CoinmarketCap expected tokens: {:.6f}".format(scale_amount(to_token, 'human', quote_cmc)))
146+
# print("Oracle expected tokens: {:.6f}".format(scale_amount(to_token, 'human', quote_oracles)))
147+
# print("Coingecko expected tokens: {:.6f}".format(scale_amount(to_token, 'human', quote_coingecko)))
148+
# print("CoinmarketCap expected tokens: {:.6f}".format(scale_amount(to_token, 'human', quote_cmc)))
145149
print("Tokens expected (with {:.2f}% slippage) {:.6f}".format(max_slippage, scale_amount(to_token, 'human', min_tokens_with_slippage)))
146-
print("")
147-
print("------ Price Diffs -------")
148-
print("1Inch to Oracle Difference: {:.6f}%".format(oracle_to_1inch_diff * 100))
149-
print("1Inch to Coingecko Difference: {:.6f}%".format(coingecko_to_1inch_diff * 100))
150-
print("1Inch to CoinmarketCap Difference: {:.6f}%".format(cmc_to_1inch_diff * 100))
150+
# print("")
151+
# print("------ Price Diffs -------")
152+
# print("1Inch to Oracle Difference: {:.6f}%".format(oracle_to_1inch_diff * 100))
153+
# print("1Inch to Coingecko Difference: {:.6f}%".format(coingecko_to_1inch_diff * 100))
154+
# print("1Inch to CoinmarketCap Difference: {:.6f}%".format(cmc_to_1inch_diff * 100))
151155
print("")
152156
print("-------- Slippage --------")
153157
print("Current market Slippage: {:.6f}%".format(actual_slippage * 100))
@@ -160,23 +164,23 @@ def build_swap_tx(from_token, to_token, from_amount, max_slippage, allow_partial
160164
print(console_colors["FAIL"] + error + console_colors["ENDC"])
161165
raise Exception(error)
162166

163-
for protocol, price_diff in {
164-
"Oracle": oracle_to_1inch_diff,
165-
"Coingecko": coingecko_to_1inch_diff,
166-
"CoinmarketCap": cmc_to_1inch_diff
167-
}.items():
168-
if (abs(price_diff * 100) > MAX_PRICE_DEVIATION):
169-
error = "1Inch and {} have too large price deviation: {:.6f}%".format(protocol, price_diff * 100)
170-
print(console_colors["FAIL"] + error + console_colors["ENDC"])
171-
raise Exception(error)
167+
# for protocol, price_diff in {
168+
# "Oracle": oracle_to_1inch_diff,
169+
# "Coingecko": coingecko_to_1inch_diff,
170+
# "CoinmarketCap": cmc_to_1inch_diff
171+
# }.items():
172+
# if (abs(price_diff * 100) > MAX_PRICE_DEVIATION):
173+
# error = "1Inch and {} have too large price deviation: {:.6f}%".format(protocol, price_diff * 100)
174+
# print(console_colors["FAIL"] + error + console_colors["ENDC"])
175+
# raise Exception(error)
172176

173-
to, data = get_1inch_swap(from_token, to_token, from_amount, max_slippage, allow_partial_fill, min_tokens_with_slippage)
177+
to, data = get_1inch_swap(from_token, to_token, from_amount, max_slippage, allow_partial_fill, min_tokens_with_slippage, protocols="USDS_MIGRATOR,LITEPSM_USDC")
174178

175179
if dry_run == True:
176180
return to, data
177181

178-
decoded_input = vault_core.swapCollateral.decode_input(data)
179-
return c_vault_core.swapCollateral(*decoded_input, {'from':STRATEGIST})
182+
decoded_input = vault_admin.swapCollateral.decode_input(data)
183+
return c_vault_admin.swapCollateral(*decoded_input, {'from':STRATEGIST})
180184

181185

182186
# from_token, to_token, from_token_amount, slippage, allow_partial_fill, dry_run

brownie/oneinch.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from prices import decimalsMap
99

1010
ONEINCH_API_KEY = os.getenv('ONEINCH_API_KEY')
11+
ONEINCH_SWAP_VERSION = "5.2"
1112

1213
def get_1inch_price(from_token, to_token, retry_on_ratelimit=True):
1314
if len(ONEINCH_API_KEY) <= 0:
@@ -41,13 +42,13 @@ def get_1inch_quote(from_token, to_token, from_amount, protocols = "", retry_on_
4142
params = {
4243
'src': from_token,
4344
'dst': to_token,
44-
'amount': "%.0f" % (from_amount)
45+
'amount': "%.0f" % (from_amount),
4546
}
4647

4748
if protocols != "":
4849
params['protocols'] = protocols
4950

50-
res = requests.get('https://api.1inch.dev/swap/v5.2/1/quote', params=params, headers={
51+
res = requests.get('https://api.1inch.dev/swap/v{}/1/quote'.format(ONEINCH_SWAP_VERSION), params=params, headers={
5152
'accept': 'application/json',
5253
'Authorization': 'Bearer {}'.format(ONEINCH_API_KEY)
5354
})
@@ -61,7 +62,9 @@ def get_1inch_quote(from_token, to_token, from_amount, protocols = "", retry_on_
6162

6263
result = json.loads(res.text)
6364

64-
return int(result['toAmount'])
65+
print(result)
66+
67+
return int(result['dstAmount'] if 'dstAmount' in result else result['toAmount'])
6568

6669
def get_1inch_swap_data(from_token, to_token, swap_amount, slippage, from_address=STRATEGIST, to_address=STRATEGIST, protocols = "", retry_on_ratelimit=True):
6770
if len(ONEINCH_API_KEY) <= 0:
@@ -75,13 +78,14 @@ def get_1inch_swap_data(from_token, to_token, swap_amount, slippage, from_addres
7578
'amount': "%.0f" % (swap_amount),
7679
'allowPartialFill': True,
7780
'disableEstimate': 'true',
78-
'slippage': slippage
81+
'slippage': slippage,
82+
'includeProtocols': True,
7983
}
8084

8185
if protocols != "":
8286
params['protocols'] = protocols
8387

84-
res = requests.get('https://api.1inch.dev/swap/v5.2/1/swap', params=params, headers={
88+
res = requests.get('https://api.1inch.dev/swap/v{}/1/swap'.format(ONEINCH_SWAP_VERSION), params=params, headers={
8589
'accept': 'application/json',
8690
'Authorization': 'Bearer {}'.format(ONEINCH_API_KEY)
8791
})
@@ -95,4 +99,6 @@ def get_1inch_swap_data(from_token, to_token, swap_amount, slippage, from_addres
9599

96100
result = json.loads(res.text)
97101

102+
print(result)
103+
98104
return SimpleNamespace(receiver = result['tx']['to'], input = result['tx']['data'])

brownie/prices.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
DAI: 18,
1616
USDT: 6,
1717
USDC: 6,
18+
USDS: 18,
1819

1920
CVX: 18,
2021
OGV: 18,
@@ -48,6 +49,7 @@ def get_cmc_quote(from_token, to_token, from_amount):
4849
DAI: 4943,
4950
USDT: 825,
5051
USDC: 3408,
52+
USDS: 39926,
5153

5254
OGV: 20949,
5355
OGN: 5117,
@@ -88,6 +90,7 @@ def get_coingecko_quote(from_token, to_token, from_amount):
8890
DAI: ['dai', 'usd'],
8991
USDT: ['tether', 'usd'],
9092
USDC: ['usd-coin', 'usd'],
93+
USDS: ['usds', 'usd'],
9194

9295
OGV: ['origin-dollar-governance', 'usd'],
9396
OGN: ['origin-protocol', 'usd'],

brownie/scripts/usds_swap.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
from collateralSwap import *
3+
4+
def main():
5+
with TemporaryForkForReallocations() as txs:
6+
txs.append(vault_core.rebase({'from':MULTICHAIN_STRATEGIST}))
7+
txs.append(vault_value_checker.takeSnapshot({'from':MULTICHAIN_STRATEGIST}))
8+
9+
txs.append(
10+
vault_admin.setAssetDefaultStrategy(USDS, "0x0000000000000000000000000000000000000000", {'from': MULTICHAIN_STRATEGIST})
11+
)
12+
13+
txs.append(
14+
vault_admin.withdrawAllFromStrategy(
15+
MAKER_SSR_STRAT,
16+
{'from': MULTICHAIN_STRATEGIST}
17+
)
18+
)
19+
20+
usds_balance = usds.balanceOf(VAULT_PROXY_ADDRESS)
21+
22+
print("USDS balance: ", usds_balance)
23+
24+
txs.append(
25+
build_swap_tx(
26+
USDS,
27+
USDC,
28+
usds_balance,
29+
0.5,
30+
False,
31+
False
32+
)
33+
)
34+
35+
vault_change = vault_core.totalValue() - vault_value_checker.snapshots(MULTICHAIN_STRATEGIST)[0]
36+
supply_change = ousd.totalSupply() - vault_value_checker.snapshots(MULTICHAIN_STRATEGIST)[1]
37+
profit = vault_change - supply_change
38+
txs.append(vault_value_checker.checkDelta(profit, (500 * 10**18), vault_change, (500 * 10**18), {'from': MULTICHAIN_STRATEGIST}))
39+
40+
print("Schedule the following transactions on Gnosis Safe")
41+
for idx, item in enumerate(txs):
42+
print("Transaction ", idx)
43+
print("To: ", item.receiver)
44+
print("Data (Hex encoded): ", item.input, "\n")

brownie/scripts/usdt_swap.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
from collateralSwap import *
3+
4+
def main():
5+
with TemporaryForkForReallocations() as txs:
6+
txs.append(vault_core.rebase({'from':MULTICHAIN_STRATEGIST}))
7+
txs.append(vault_value_checker.takeSnapshot({'from':MULTICHAIN_STRATEGIST}))
8+
9+
txs.append(
10+
vault_admin.setAssetDefaultStrategy(USDT, "0x0000000000000000000000000000000000000000", {'from': MULTICHAIN_STRATEGIST})
11+
)
12+
13+
txs.append(
14+
vault_admin.withdrawAllFromStrategy(
15+
MORPHO_GAUNTLET_PRIME_USDT_STRAT,
16+
{'from': MULTICHAIN_STRATEGIST}
17+
)
18+
)
19+
20+
usdt_balance = usdt.balanceOf(VAULT_PROXY_ADDRESS)
21+
22+
print("USDT balance: ", usdt_balance)
23+
24+
txs.append(
25+
build_swap_tx(
26+
USDT,
27+
USDC,
28+
usdt_balance,
29+
0.5,
30+
False,
31+
False
32+
)
33+
)
34+
35+
vault_change = vault_core.totalValue() - vault_value_checker.snapshots(MULTICHAIN_STRATEGIST)[0]
36+
supply_change = ousd.totalSupply() - vault_value_checker.snapshots(MULTICHAIN_STRATEGIST)[1]
37+
profit = vault_change - supply_change
38+
txs.append(vault_value_checker.checkDelta(profit, (500 * 10**18), vault_change, (500 * 10**18), {'from': MULTICHAIN_STRATEGIST}))
39+
40+
print("Schedule the following transactions on Gnosis Safe")
41+
for idx, item in enumerate(txs):
42+
print("Transaction ", idx)
43+
print("To: ", item.receiver)
44+
print("Data (Hex encoded): ", item.input, "\n")

brownie/world.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
usdt = load_contract('usdt', USDT)
2424
usdc = load_contract('usdc', USDC)
2525
dai = load_contract('dai', DAI)
26+
usds = load_contract('dai', USDS)
2627
steth = load_contract('ERC20', STETH)
2728
wsteth = load_contract('wsteth', WSTETH)
2829
sfrxeth = load_contract('ERC20', SFRXETH)

0 commit comments

Comments
 (0)