Skip to content

Commit

Permalink
Merge branch 'main' into current-function
Browse files Browse the repository at this point in the history
  • Loading branch information
mariaKt authored Sep 18, 2024
2 parents 62a7003 + 95f5df6 commit 8cfaab6
Show file tree
Hide file tree
Showing 9 changed files with 113,453 additions and 3,044 deletions.
165 changes: 164 additions & 1 deletion test/examples/swaps/UniswapV2Swap.sol
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,82 @@ contract UniswapV2Router02 {
_swap(amounts, path, to);
}

function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to
) external returns (uint[] memory amounts_liq) {
amounts_liq = new uint[](3);

uint[] memory amounts = _addLiquidity(
tokenA,
tokenB,
amountADesired,
amountBDesired,
amountAMin,
amountBMin
);

amounts_liq[0] = amounts[0];
amounts_liq[1] = amounts[1];

address pair = uniswapV2Library_pairFor(tokenA, tokenB);
IERC20(tokenA).transferFrom(msg.sender, pair, amounts[0]);
IERC20(tokenB).transferFrom(msg.sender, pair, amounts[1]);
amounts_liq[2] = UniswapV2Pair(pair).mint(to);
}

function _addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin
) internal returns (uint[] memory amounts) {
amounts = new uint[](2);

require(get_local_pair(tokenA, tokenB) != address(0));

uint[] memory reserves = uniswapV2Library_getReserves(tokenA, tokenB);
if (reserves[0] == 0 && reserves[1] == 0) {
amounts[0] = amountADesired;
amounts[1] = amountBDesired;
} else {
uint amountBOptimal = uniswapV2Library_quote(
amountADesired,
reserves[0],
reserves[1]
);
if (amountBOptimal <= amountBDesired) {
require(
amountBOptimal >= amountBMin,
"UniswapV2Router: INSUFFICIENT_B_AMOUNT"
);
amounts[0] = amountADesired;
amounts[1] = amountBOptimal;
} else {
uint amountAOptimal = uniswapV2Library_quote(
amountBDesired,
reserves[1],
reserves[0]
);
assert(amountAOptimal <= amountADesired);
require(
amountAOptimal >= amountAMin,
"UniswapV2Router: INSUFFICIENT_A_AMOUNT"
);
amounts[0] = amountAOptimal;
amounts[1] = amountBDesired;
}
}
}


function set_local_pair(address tokenA, address tokenB) public{
address[] memory tokens = uniswapV2Library_sortTokens(tokenA, tokenB);
local_pairs[tokens[0]][tokens[1]] = address(new UniswapV2Pair(address(tokens[0]), address(tokens[1])));
Expand Down Expand Up @@ -221,6 +297,19 @@ contract UniswapV2Router02 {
uint denominator = (reserveOut-amountOut)*997;
amountIn = denominator != 0 ? (numerator / denominator) + 1 : 1;
}

function uniswapV2Library_quote(
uint amountA,
uint reserveA,
uint reserveB
) internal returns (uint amountB) {
require(amountA > 0, "UniswapV2Library: INSUFFICIENT_AMOUNT");
require(
reserveA > 0 && reserveB > 0,
"UniswapV2Library: INSUFFICIENT_LIQUIDITY"
);
amountB = (amountA * reserveB) / reserveA;
}
}

contract UniswapV2Pair{
Expand Down Expand Up @@ -251,6 +340,7 @@ contract UniswapV2Pair{
uint amount1Out,
address indexed to
);
event Mint(address indexed sender, uint amount0, uint amount1);

constructor(address _token0, address _token1) {
token0 = _token0;
Expand Down Expand Up @@ -286,6 +376,34 @@ contract UniswapV2Pair{
emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
}

function mint(address to) external returns (uint liquidity) {
uint112[] memory pair_reserves = getReserves();
uint balance0 = IERC20(token0).balanceOf(address(this));
uint balance1 = IERC20(token1).balanceOf(address(this));
uint amount0 = balance0 - pair_reserves[0];
uint amount1 = balance1 - pair_reserves[1];

//bool feeOn = _mintFee(pair_reserves[0], pair_reserves[1]);
uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
if (_totalSupply == 0) {
liquidity = math_sqrt(amount0 * amount1) - MINIMUM_LIQUIDITY;
totalSupply = totalSupply + MINIMUM_LIQUIDITY;
balanceOf[address(0)] = balanceOf[address(0)] + MINIMUM_LIQUIDITY;
} else {
liquidity = math_min(
(amount0 * _totalSupply) / pair_reserves[0],
(amount1 * _totalSupply) / pair_reserves[1]
);
}
require(liquidity > 0, "UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED");
totalSupply = totalSupply + liquidity;
balanceOf[to] = balanceOf[to] + liquidity;

_update(balance0, balance1, pair_reserves[0], pair_reserves[1]);
//if (feeOn) kLast = uint(reserve0) * reserve1; // reserve0 and reserve1 are up-to-date
emit Mint(msg.sender, amount0, amount1);
}

function sync() external {
_update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1);
}
Expand All @@ -297,6 +415,23 @@ contract UniswapV2Pair{
reserves[2] = blockTimestampLast;
}

function math_min(uint x, uint y) internal returns (uint z) {
z = x < y ? x : y;
}

function math_sqrt(uint y) internal returns (uint z) {
if (y > 3) {
z = y;
uint x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}

function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {
require(balance0 <= UINT112_MAX && balance1 <= UINT112_MAX, "UniswapV2: OVERFLOW");
uint32 blockTimestamp = uint32(block.timestamp % 2**32);
Expand Down Expand Up @@ -554,6 +689,7 @@ contract USDCMock {
contract UniswapV2SwapTest {

UniswapV2Swap private _uni;
UniswapV2Router02 private _router;
WETHMock private _weth;
DAIMock private _dai;
USDCMock private _usdc;
Expand Down Expand Up @@ -667,4 +803,31 @@ contract UniswapV2SwapTest {

assert(amountOut == amountOutDesired);
}
}

function testRouterAddLiquidity() public {
uint256 testAmount = 131072; // Hex: 0x20000
uint desiredA = 10000;
uint desiredB = 10000;
uint minA = 0;
uint minB = 0;

_router = new UniswapV2Router02();

_router.set_local_pair(address(_weth), address(_dai));
_router.set_local_pair(address(_weth), address(_usdc));
_router.set_local_pair(address(_usdc), address(_dai));

_dai.mint(address(this), testAmount);
_dai.approve(address(_router), testAmount);
_usdc.mint(address(this), testAmount);
_usdc.approve(address(_router), testAmount);

_router.addLiquidity(address(_dai), address(_usdc), desiredA, desiredB, minA, minB, address(this));

assert(_dai.balanceOf(address(this)) == 121072);
assert(_usdc.balanceOf(address(this)) == 121072);
assert(_dai.balanceOf(_router.get_local_pair(address(_dai), address(_usdc))) == 10000);
assert(_usdc.balanceOf(_router.get_local_pair(address(_dai), address(_usdc))) == 10000);
assert(UniswapV2Pair(_router.get_local_pair(address(_dai), address(_usdc))).balanceOf(address(this)) == 9000);
}
}
Loading

0 comments on commit 8cfaab6

Please sign in to comment.