Write Your First Uniswap Contract
This guide will walk you through the process of creating and deploying a simple Uniswap-like decentralized exchange (DEX) contract on the Pharos blockchain. By the end of this guide, you will have a basic understanding of how automated market makers (AMMs) work and how to implement a simple DEX.
Prerequisites
Before you begin, ensure you have the following:
Git: Used for code management and obtain examples.
Node.js: Install it from nodejs.org.
Pharos Devnet/Testnet Access: Access to a Pharos node (local or remote) for interacting with the blockchain.
Setup 1: Install Foundry
Setup 2: Set Up the Project
Clone the example repo:
git clone https://github.com/PharosNetwork/examples
cd examples/uniswap/foundry/contract
Install OpenZeppelin Contracts:
Foundry uses forge to manage dependencies. Install OpenZeppelin contracts:
forge install OpenZeppelin/openzeppelin-contracts --no-git --no-commit
Step 3: Write the Uniswap Contract
Create a New Solidity File:
Create a new file for your uniswap contract:
touch src/Uniswap.sol
Write the uniswap Contract:
Open
src/Uniswap.sol
in your favorite text editor and add the following code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
contract Uniswap {
address public tokenA;
address public tokenB;
uint256 public reserveA;
uint256 public reserveB;
constructor(address _tokenA, address _tokenB) {
tokenA = _tokenA;
tokenB = _tokenB;
}
function addLiquidity(uint256 amountA, uint256 amountB) external {
require(IERC20(tokenA).transferFrom(msg.sender, address(this), amountA), "Transfer failed");
require(IERC20(tokenB).transferFrom(msg.sender, address(this), amountB), "Transfer failed");
reserveA += amountA;
reserveB += amountB;
}
function removeLiquidity(uint256 amountA, uint256 amountB) external {
require(reserveA >= amountA && reserveB >= amountB, "Insufficient reserves");
reserveA -= amountA;
reserveB -= amountB;
require(IERC20(tokenA).transfer(msg.sender, amountA), "Transfer failed");
require(IERC20(tokenB).transfer(msg.sender, amountB), "Transfer failed");
}
function swapAToB(uint256 amountA) external {
uint256 amountB = (amountA * reserveB) / reserveA;
require(IERC20(tokenA).transferFrom(msg.sender, address(this), amountA), "Transfer failed");
require(IERC20(tokenB).transfer(msg.sender, amountB), "Transfer failed");
reserveA += amountA;
reserveB -= amountB;
}
function swapBToA(uint256 amountB) external {
uint256 amountA = (amountB * reserveA) / reserveB;
require(IERC20(tokenB).transferFrom(msg.sender, address(this), amountB), "Transfer failed");
require(IERC20(tokenA).transfer(msg.sender, amountA), "Transfer failed");
reserveB += amountB;
reserveA -= amountA;
}
}
Compile the Smart Contract:
Use forge to compile the contract:
forge build
Test the Smart Contract
Use forge to test the contract:
forge test
Step 4: Deploy the Uniswap Contract
Create a Deployment Script:
Create a new file for the deployment script:
touch script/DeployUniswap.s.sol
Write the Deployment Script:
Open script/DeployUniswap.s.sol and add the following code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "forge-std/Script.sol";
import "../src/Uniswap.sol";
contract DeployUniswap is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
address tokenA = address(0xAA); // Replace with the address of token A
address tokenB = address(0xBB); // Replace with the address of token B
Uniswap uniswap = new Uniswap(tokenA, tokenB);
vm.stopBroadcast();
}
}
Set the private key:
export PRIVATE_KEY=<your private key>
Deploy the Contract:
Use forge to deploy the contract to the Pharos Testnet:
forge script script/DeployUniswap.s.sol --rpc-url <PHAROS_RPC_URL> --broadcast
Step 5: Interact with the Uniswap Contract
Open script/InteractUniswap.s.sol
and add the following code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "forge-std/Script.sol";
import "../src/Uniswap.sol";
import "../test/Uniswap.t.sol";
contract DeployUniswap is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
MockERC20 tokenA = new MockERC20("TokenA", "TKA");
MockERC20 tokenB = new MockERC20("TokenB", "TKB");
Uniswap uniswap = new Uniswap(address(tokenA), address(tokenB));
console.log("TokenA deployed at:", address(tokenA));
console.log("TokenB deployed at:", address(tokenB));
console.log("Uniswap deployed at:", address(uniswap));
vm.stopBroadcast();
}
}
Execute the script using forge:
forge script script/InteractUniswap.s.sol --rpc-url <PHAROS_RPC_URL> --broadcast
Troubleshooting
Contract Deployment Fails: Ensure you have enough testnet tokens to cover the deployment cost.
Interaction Issues: Verify that the contract address and ABI are correct.
Test Failures: Check the test output for detailed error messages and adjust the tests accordingly.
Conclusion
This guide provides a comprehensive introduction to creating and deploying a Uniswap-like contract on the Pharos blockchain using Foundry. If you encounter any issues, refer to the Foundry documentation or the troubleshooting section. Happy building! 🚀
Last updated