How to Build Automated Market Maker (AMM) Logic in Solidity

Posted By : Krishan

Nov 28, 2024

Automated Market Maker (AMM) model sits at the heart of crypto exchange transformation, a fundamental innovation powering many centralized crypto exchange platforms and decentralized exchanges (DEXs). It is a protocol, integrated using crypto exchange development, that allows cryptocurrency trading without using traditional order books. Instead of matching buy and sell orders, AMMs rely on liquidity pools that use mathematical formulas to determine prices. Users can trade directly with the pool, and prices are adjusted based on supply and demand within the pool.

 

Explore | An Exhaustive Introduction to Automated Market Makers (AMM)

 

Steps to Implement AMM Logic in Solidity

 

1. Setting up the Development Environment

 

  • Install Node.js: Node.js is required for running the necessary scripts and tools.
  • Install Hardhat: Hardhat is a development framework for building and testing smart contracts. Install it by running the following command:
  • Create a Hardhat Project: Initialize a new Hardhat project by running:

     

  npx hardhat init


2. Create the Contract

 

Inside the contracts directory, create a new file named Amm.sol. This Solidity file will hold our Amm logic.

 

3. Implement the Contract

 

Program :
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

contract TokenV2SwapAmm{

address private constant UNISWAPV2ROUTER =

0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;

address private constant WETH_TOKEN = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

address private constant DAI_TOKEN = 0x6B175474E89094C44Da98b954EedeAC495271d0F;

address constant USDC_TOKEN = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;

IUniswapV2Router private myrouter = IUniswapV2Router(UNISWAPV2ROUTER);

IERC20 private weth_token = IERC20(WETH_TOKEN);

IERC20 private dai_token = IERC20(DAI_TOKEN);

// Swap WETH_TOKEN to DAI_TOKEN

function swapSingleHopExactAmountIn(uint256 amount_In, uint256 amount_OutMin)

external

returns (uint256 amountOut)

{

weth_token.transferFrom(msg.sender, address(this), amount_In);

weth_token.approve(address(myrouter), amount_In);

address[] memory route;

route = new address[](2);

route[0] = WETH_TOKEN;

route[1] = DAI_TOKEN;

uint256[] memory amounts = myrouter.swapExactTokensForTokens(

amount_In, amount_OutMin, route, msg.sender, block.timestamp

);

// amounts[0] = WETH_TOKEN amount, amounts[1] = DAI_TOKEN amount

return amounts[1];

}

// Swap DAI_TOKEN -> WETH_TOKEN -> USDC_TOKEN

function swapMultiHopExactAmountIn(uint256 amount_In, uint256 amount_OutMin)

external

returns (uint256 amountOut)

{

dai_token.transferFrom(msg.sender, address(this), amount_In);

dai_token.approve(address(myrouter), amount_In);

address[] memory route;

route = new address[](3);

route[0] = DAI_TOKEN;

route[1] = WETH_TOKEN;

route[2] = USDC_TOKEN;

uint256[] memory amounts = myrouter.swapExactTokensForTokens(

amount_In, amount_OutMin, route, msg.sender, block.timestamp

);

// amounts[0] = DAI_TOKEN amount

// amounts[1] = WETH_TOKEN amount

// amounts[2] = USDC_TOKEN amount

return amounts[2];

}

// Swap WETH_TOKEN to DAI_TOKEN

function swapSingleHopExactAmountOut(

uint256 amountOutRequired,

uint256 amounttInMaxreq

) external returns (uint256 amountOut) {

weth_token.transferFrom(msg.sender, address(this), amounttInMaxreq);

weth_token.approve(address(myrouter), amounttInMaxreq);

address[] memory route;

route = new address[](2);

route[0] = WETH_TOKEN;

route[1] = DAI_TOKEN;

uint256[] memory amounts = myrouter.swapTokensForExactTokens(

amountOutRequired, amounttInMaxreq, route, msg.sender, block.timestamp

);

// Refund WETH_TOKEN to msg.sender

if (amounts[0] < amounttInMaxreq) {

weth_token.transfer(msg.sender, amounttInMaxreq - amounts[0]);

}

return amounts[1];

}

// Swap DAI_TOKEN -> WETH_TOKEN -> USDC_TOKEN

function swapMultiHopExactAmountOut(

uint256 amountOutRequired,

uint256 amounttInMaxreq

) external returns (uint256 amountOut) {

dai_token.transferFrom(msg.sender, address(this), amounttInMaxreq);

dai_token.approve(address(myrouter), amounttInMaxreq);

address[] memory route;

route = new address[](3);

route[0] = DAI_TOKEN;

route[1] = WETH_TOKEN;

route[2] = USDC_TOKEN;

uint256[] memory amounts = myrouter.swapTokensForExactTokens(

amountOutRequired, amounttInMaxreq, route, msg.sender, block.timestamp

);

// Refund DAI_TOKEN to msg.sender

if (amounts[0] < amounttInMaxreq) {

dai_token.transfer(msg.sender, amounttInMaxreq - amounts[0]);

}

return amounts[2];

}

}


interface IUniswapV2Router {

function swapExactTokensForTokens(

uint256 amount_In,

uint256 amount_OutMin,

address[] calldata route,

address to,

uint256 deadline

) external returns (uint256[] memory amounts);


function swapTokensForExactTokens(

uint256 amountOut,

uint256 amounttInMaxreq,

address[] calldata route,

address to,

uint256 deadline

) external returns (uint256[] memory amounts);

}

interface IERC20 {

function totalSupply() external view returns (uint256);

function balanceOf(address account) external view returns (uint256);

function transfer(address recipient, uint256 amount)

external

returns (bool);

function allowance(address owner, address spender)

external

view

returns (uint256);

function approve(address spender, uint256 amount) external returns (bool);

function transferFrom(address sender, address recipient, uint256 amount)

external

returns (bool);

}

interface IWETH_TOKEN is IERC20 {

function deposit() external payable;

function withdraw(uint256 amount) external;

}

 

Create the Contract

 

Inside the contracts directory, create a new file named Amm.sol. This Solidity file will contain the AMM logic for token swaps.

 

Implement the AMM Logic in Solidity

 

The following code snippet implements the AMM logic for token swaps using Uniswap's V2 router.
 


async function main() {
  const Ammswap = await ethers.getContractFactory('TokenV2SwapAmm');
  const swap = await Ammswap.deploy();
  await swap.deployed();
  console.log('Amm logic deployed to:', swap.address);
}
main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});


Testing the Contract 

 

1. Write Tests:


  - In the test directory, create a new file for the tests.
 - Use Hardhat's testing framework to write tests for your contract.

 

2. Run Tests:

 


 npx hardhat test

 

Also, Explore | Identifying Smart Contract Orchestration Patterns in Solidity

 

Conclusion

 

Congratulations on implementing Automated Market Maker (AMM) Logic in Solidity and deploying your contract on Ethereum.

Ready to take your decentralized Amm swap system to the next level? Contact our expert blockchain developers at Oodles to transform your vision into a robust, feature-rich solution tailored to your specific needs. Let's innovate together and redefine the future of Amm swap.

 

 

Leave a

Comment

Name is required

Invalid Name

Comment is required

Recaptcha is required.

blog-detail

December 21, 2024 at 04:25 pm

Your comment is awaiting moderation.

By using this site, you allow our use of cookies. For more information on the cookies we use and how to delete or block them, please read our cookie notice.

Chat with Us
Telegram Button
Youtube Button

Contact Us

Oodles | Blockchain Development Company

Name is required

Please enter a valid Name

Please enter a valid Phone Number

Please remove URL from text