Skip to content

Commit 9d781ca

Browse files
committed
initial version for LiquidityManager
1 parent 5f9407f commit 9d781ca

File tree

1 file changed

+199
-0
lines changed

1 file changed

+199
-0
lines changed

contracts/LiquidityManager.sol

+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
// SPDX-License-Identifier: BCOM
2+
3+
pragma solidity ^0.8.19;
4+
5+
import "./IERC20.sol";
6+
import "./ISwapsPair.sol";
7+
import "./ISwapsRouter.sol";
8+
import "./ISwapsFactory.sol";
9+
10+
contract LiquidityManager {
11+
12+
ISwapsFactory immutable FACTORY;
13+
ISwapsRouter immutable ROUTER;
14+
15+
address immutable ROUTER_ADDRESS;
16+
address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
17+
18+
constructor(
19+
ISwapsFactory _factory,
20+
ISwapsRouter _router
21+
) {
22+
FACTORY = _factory;
23+
ROUTER = _router;
24+
25+
ROUTER_ADDRESS = address(
26+
_router
27+
);
28+
}
29+
30+
/**
31+
* @dev
32+
* Optimal one-sided supply
33+
* 1. Swaps optimal amount from token A to token B
34+
* 2. Adds liquidity for token A and token B pair
35+
*/
36+
function makeLiquidity(
37+
address _tokenA,
38+
address _tokenB,
39+
uint256 _amountA,
40+
uint256 _minExpected
41+
)
42+
external
43+
returns (uint256 swapAmount)
44+
{
45+
IERC20(_tokenA).transferFrom(
46+
msg.sender,
47+
address(this),
48+
_amountA
49+
);
50+
51+
ISwapsPair pair = _getPair(
52+
_tokenA,
53+
_tokenB
54+
);
55+
56+
(
57+
uint256 reserve0,
58+
uint256 reserve1,
59+
) = pair.getReserves();
60+
61+
swapAmount = pair.token0() == _tokenA
62+
? getSwapAmount(reserve0, _amountA)
63+
: getSwapAmount(reserve1, _amountA);
64+
65+
_swap(
66+
_tokenA,
67+
_tokenB,
68+
swapAmount,
69+
_minExpected
70+
);
71+
72+
_addLiquidity(
73+
_tokenA,
74+
_tokenB
75+
);
76+
}
77+
78+
function _swap(
79+
address _fromToken,
80+
address _toToken,
81+
uint256 _swapAmount,
82+
uint256 _minExpected
83+
)
84+
internal
85+
{
86+
IERC20(_fromToken).approve(
87+
ROUTER_ADDRESS,
88+
_swapAmount
89+
);
90+
91+
address[] memory path = new address[](2);
92+
path = new address[](2);
93+
94+
path[0] = _fromToken;
95+
path[1] = _toToken;
96+
97+
ROUTER.swapExactTokensForTokens(
98+
_swapAmount,
99+
_minExpected,
100+
path,
101+
address(this),
102+
block.timestamp
103+
);
104+
}
105+
106+
function _addLiquidity(
107+
address _tokenA,
108+
address _tokenB
109+
)
110+
internal
111+
{
112+
uint256 balanceA = IERC20(_tokenA).balanceOf(
113+
address(this)
114+
);
115+
116+
uint256 balanceB = IERC20(_tokenB).balanceOf(
117+
address(this)
118+
);
119+
120+
IERC20(_tokenA).approve(
121+
ROUTER_ADDRESS,
122+
balanceA
123+
);
124+
125+
IERC20(_tokenB).approve(
126+
ROUTER_ADDRESS,
127+
balanceB
128+
);
129+
130+
ROUTER.addLiquidity(
131+
_tokenA,
132+
_tokenB,
133+
balanceA,
134+
balanceB,
135+
0,
136+
0,
137+
address(this),
138+
block.timestamp
139+
);
140+
}
141+
142+
function _getPair(
143+
address _tokenA,
144+
address _tokenB
145+
)
146+
internal
147+
view
148+
returns (ISwapsPair)
149+
{
150+
return ISwapsPair(
151+
FACTORY.getPair(
152+
_tokenA,
153+
_tokenB
154+
)
155+
);
156+
}
157+
158+
/**
159+
* @dev
160+
* s = optimal swap amount
161+
* r = amount of reserve for token a
162+
* a = amount of token a the user currently has (not added to reserve yet)
163+
* f = swap fee percent
164+
* s = (sqrt(((2 - f)r)^2 + 4(1 - f)ar) - (2 - f)r) / (2(1 - f))
165+
*/
166+
function getSwapAmount(
167+
uint256 _r,
168+
uint256 _a
169+
)
170+
public
171+
pure
172+
returns (uint256)
173+
{
174+
return (sqrt(_r * (_r * 3988009 + _a * 3988000)) - _r * 1997) / 1994;
175+
}
176+
177+
/**
178+
* @dev
179+
*
180+
*/
181+
function sqrt(
182+
uint256 _y
183+
)
184+
private
185+
pure
186+
returns (uint256 z)
187+
{
188+
if (_y > 3) {
189+
z = _y;
190+
uint256 x = _y / 2 + 1;
191+
while (x < z) {
192+
z = x;
193+
x = (_y / x + x) / 2;
194+
}
195+
} else if (_y != 0) {
196+
z = 1;
197+
}
198+
}
199+
}

0 commit comments

Comments
 (0)