Skip to content

Commit

Permalink
Merge pull request #19 from NilFoundation/demo-router
Browse files Browse the repository at this point in the history
Router: demo task & contract
  • Loading branch information
Rolaman authored Sep 26, 2024
2 parents 29b3ceb + c4540ee commit 2dbfaaf
Show file tree
Hide file tree
Showing 4 changed files with 441 additions and 67 deletions.
82 changes: 30 additions & 52 deletions contracts/UniswapV2Router01.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ import "./interfaces/IUniswapV2Pair.sol";
contract UniswapV2Router01 is IUniswapV2Router01, NilCurrencyBase {
address public immutable factory;

modifier ensure(uint deadline) {
require(deadline >= block.timestamp, 'UniswapV2Router: EXPIRED');
_;
}

constructor(address _factory) public {
// Revert if the factory address is the zero address or an empty string
Expand All @@ -24,59 +20,37 @@ contract UniswapV2Router01 is IUniswapV2Router01, NilCurrencyBase {
}

function addLiquidity(
address tokenA,
address tokenB,
address to,
uint deadline,
uint salt
) external override ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) {
if (IUniswapV2Factory(factory).getTokenPair(tokenA, tokenB) == address(0)) {
IUniswapV2Factory(factory).createPair(tokenA, tokenB, 1, salt);
}
address pair = IUniswapV2Factory(factory).getTokenPair(tokenA, tokenB);
uint tokenAId = NilCurrencyBase(tokenA).getCurrencyId();
uint tokenBId = NilCurrencyBase(tokenB).getCurrencyId();

address pair,
address to
) public override {
Nil.Token[] memory tokens = Nil.msgTokens();
if (tokens.length != 2) {
revert("Send only 2 tokens to add liquidity");
}
assert(tokenAId == tokens[0].id);
assert(tokenBId == tokens[1].id);

if (tokens.length != 2) {
revert("UniswapV2Router: Expect 2 tokens to add liquidity");
}
sendCurrencyInternal(pair, tokenAId, tokens[0].amount);
sendCurrencyInternal(pair, tokenBId, tokens[1].amount);
liquidity = IUniswapV2Pair(pair).mint(to);
amountA = tokens[0].amount;
amountB = tokens[1].amount;
smartCall(pair, tokens, abi.encodeWithSignature("mint(address)", to));
}

// **** REMOVE LIQUIDITY ****
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) public override ensure(deadline) returns (uint amountA, uint amountB) {
address pair = IUniswapV2Factory(factory).getTokenPair(tokenA, tokenB);
(address token0,) = UniswapV2Library.sortTokens(tokenA, tokenB);
(uint amount0, uint amount1) = IUniswapV2Pair(pair).burn(to);
(amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0);
require(amountA >= amountAMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT');
require(amountB >= amountBMin, 'UniswapV2Router: INSUFFICIENT_B_AMOUNT');
address pair,
address to
) public override {
Nil.Token[] memory tokens = Nil.msgTokens();
if (tokens.length != 1) {
revert("UniswapV2Router: should contains only pair token");
}
smartCall(pair, tokens, abi.encodeWithSignature("burn(address)", to));
}

function swap(address to, address pair, uint amount0Out, uint amount1Out) public override {
Nil.Token[] memory tokens = Nil.msgTokens();
if (tokens.length != 1) {
revert("UniswapV2Router: should contains only pair token");
}
sendCurrencyInternal(pair, tokens[0].id, tokens[0].amount); // send liquidity to pair
smartCall(pair, tokens, abi.encodeWithSignature("swap(uint256,uint256,address)", amount0Out, amount1Out, to));
}

// TODO: This method are used for swapping via multiple pairs. Not supported in nil for now
// **** SWAP ****
// requires the initial amount to have already been sent to the first pair
function _swap(uint[] memory amounts, address[] memory path, address _to) private {
Expand All @@ -91,13 +65,14 @@ contract UniswapV2Router01 is IUniswapV2Router01, NilCurrencyBase {
}
}

// TODO: This method are used for swapping via multiple pairs. Not supported in nil for now
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external override ensure(deadline) returns (uint[] memory amounts) {
) external override returns (uint[] memory amounts) {
amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
address pair = IUniswapV2Factory(factory).getTokenPair(path[0], path[1]);
Expand All @@ -106,13 +81,14 @@ contract UniswapV2Router01 is IUniswapV2Router01, NilCurrencyBase {
_swap(amounts, path, to);
}

// TODO: This method are used for swapping via multiple pairs. Not supported in nil for now
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external override ensure(deadline) returns (uint[] memory amounts) {
) external override returns (uint[] memory amounts) {
amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= amountInMax, 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT');
address pair = IUniswapV2Factory(factory).getTokenPair(path[0], path[1]);
Expand All @@ -133,14 +109,16 @@ contract UniswapV2Router01 is IUniswapV2Router01, NilCurrencyBase {
return UniswapV2Library.getAmountOut(amountOut, reserveIn, reserveOut);
}

function getAmountsOut(uint amountIn, address[] memory path) public view override returns (uint[] memory amounts) {
return UniswapV2Library.getAmountsOut(factory, amountIn, path);
}

function getAmountsIn(uint amountOut, address[] memory path) public view override returns (uint[] memory amounts) {
return UniswapV2Library.getAmountsIn(factory, amountOut, path);
receive() external payable {
}

receive() external payable {
function smartCall(address dst, Nil.Token[] memory tokens, bytes memory callData) private returns (bool) {
if (Nil.getShardId(dst) == Nil.getShardId(address(this))) {
(bool success,) = Nil.syncCall(dst, gasleft(), 0, tokens, callData);
return success;
} else {
Nil.asyncCall(dst, address(0), address(0), 0, Nil.FORWARD_REMAINING, false, 0, tokens, callData);
return true;
}
}
}
27 changes: 12 additions & 15 deletions contracts/interfaces/IUniswapV2Router01.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,20 @@ pragma solidity ^0.8.0;
interface IUniswapV2Router01 {

function addLiquidity(
address tokenA,
address tokenB,
address to,
uint deadline,
uint salt
) external returns (uint amountA, uint amountB, uint liquidity);
address pair,
address to
) external;
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address pair,
address to
) external;
function swap(
address to,
uint deadline
) external returns (uint amountA, uint amountB);
address pair,
uint amount0Out,
uint amount1Out
) external;

function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
Expand All @@ -38,6 +37,4 @@ interface IUniswapV2Router01 {
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
1 change: 1 addition & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import "./tasks/core/factory/create-pair";

// Demo Tasks
import "./tasks/core/demo";
import "./tasks/core/demo-router";

dotenv.config();

Expand Down
Loading

0 comments on commit 2dbfaaf

Please sign in to comment.