Created
December 13, 2023 17:48
-
-
Save hackingbeauty/15a8d96792d156501c0dece843f60d75 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { expect } = require("chai"); | |
const { loadFixture } = require("@nomicfoundation/hardhat-network-helpers"); | |
const { ethers, network } = require("hardhat"); | |
describe("TradingPairExchange contract", ()=> { | |
async function deployTradingPairExchangeFixture() { | |
await network.provider.send("hardhat_reset"); | |
/* AAVE/DAI, 1 AAVE = $56 USD, 1 DAI = $1 USD */ | |
const amountADesired = ethers.utils.parseUnits('1', 18); //AAVE | |
const amountBDesired = ethers.utils.parseUnits('56', 18); //DAI | |
const [deployer, liquidityProvider, exchangeDev] = await ethers.getSigners(); | |
const FactoryContract = await ethers.getContractFactory("Factory"); | |
const factory = await FactoryContract.deploy(deployer.address); | |
await factory.deployed(); | |
const AaveTokenContract = await ethers.getContractFactory("ERC20Basic"); | |
const aaveToken = await AaveTokenContract.deploy( | |
"Aave Stablecoin", | |
"AAVE", | |
18, | |
deployer.address | |
); | |
await aaveToken.deployed(); | |
const DaiTokenContract = await ethers.getContractFactory("ERC20Basic"); | |
const daiToken = await DaiTokenContract.deploy( | |
"Dai Stablecoin", | |
"DAI", | |
18, | |
deployer.address | |
); | |
await daiToken.deployed(); | |
/* Mint tokens for Liquidity Provider's account */ | |
await aaveToken.mint( | |
liquidityProvider.address, | |
ethers.utils.parseUnits('130', 18) | |
); | |
await daiToken.mint( | |
liquidityProvider.address, | |
ethers.utils.parseUnits('130', 18) | |
); | |
/* Liquidity Provider approves Router to transfer tokens */ | |
await aaveToken.connect(liquidityProvider).approve( | |
deployer.address, | |
ethers.utils.parseUnits('130', 18) | |
); | |
await daiToken.connect(liquidityProvider).approve( | |
deployer.address, | |
ethers.utils.parseUnits('130', 18) | |
); | |
const tradingPairExchangeContract = await factory.createTradingPair( | |
aaveToken.address, | |
daiToken.address | |
); | |
const receipt = await tradingPairExchangeContract.wait(); | |
const tradingPairExchangeAddress = receipt.events[0].args[2]; | |
const tradingPairExchange = await ethers.getContractAt( | |
"TradingPairExchange", | |
tradingPairExchangeAddress, | |
deployer | |
); | |
return { | |
aaveToken, | |
daiToken, | |
amountADesired, | |
amountBDesired, | |
liquidityProvider, | |
factory, | |
exchangeDev, | |
tradingPairExchange | |
} | |
} | |
describe("Minting Liquidity Tokens", () =>{ | |
it("should remit payment of the protocol fee to the exchange developer account", async() =>{ | |
const { | |
aaveToken, | |
daiToken, | |
amountADesired, | |
amountBDesired, | |
liquidityProvider, | |
exchangeDev, | |
factory, | |
tradingPairExchange | |
} = await loadFixture(deployTradingPairExchangeFixture); | |
await factory.setFeeTo(exchangeDev.address); | |
await aaveToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
amountADesired | |
); | |
await daiToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
amountBDesired | |
); | |
await tradingPairExchange.mint(liquidityProvider.address); | |
await aaveToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
ethers.utils.parseUnits('.25', 18) | |
); | |
await daiToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
ethers.utils.parseUnits('14', 18) | |
); | |
await tradingPairExchange.mint(liquidityProvider.address); | |
await aaveToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
ethers.utils.parseUnits('.25', 18) | |
); | |
await daiToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
ethers.utils.parseUnits('14', 18) | |
); | |
await tradingPairExchange.mint(liquidityProvider.address); | |
const exchangeDevAccountBalance = await tradingPairExchange.balanceOf(exchangeDev.address); | |
const formattedExchangeDevAccountBalance = ethers.utils.formatUnits(exchangeDevAccountBalance); | |
expect(formattedExchangeDevAccountBalance).to.equal("0.322556671273615636"); | |
}); | |
it("should update a Liquidity Provider's account after a deposit into a new pool", async() =>{ | |
const { | |
aaveToken, | |
daiToken, | |
amountADesired, | |
amountBDesired, | |
liquidityProvider, | |
tradingPairExchange | |
} = await loadFixture(deployTradingPairExchangeFixture); | |
await aaveToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
amountADesired | |
); | |
await daiToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
amountBDesired | |
); | |
await tradingPairExchange.mint(liquidityProvider.address); | |
const liquidityProviderAccountBalance = await tradingPairExchange.balanceOf(liquidityProvider.address); | |
const formattedLiquidityProviderAccountBalance = ethers.utils.formatUnits(liquidityProviderAccountBalance); | |
expect(formattedLiquidityProviderAccountBalance).to.equal("7.483314773547881771"); | |
}); | |
it("should update a Liquidity Provider's account after a deposit into an existing pool", async() =>{ | |
const { | |
aaveToken, | |
daiToken, | |
amountADesired, | |
amountBDesired, | |
liquidityProvider, | |
tradingPairExchange | |
} = await loadFixture(deployTradingPairExchangeFixture); | |
await aaveToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
amountADesired | |
); | |
await daiToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
amountBDesired | |
); | |
await tradingPairExchange.mint(liquidityProvider.address); | |
/* Transfer tokens from Liquidity Provider account to AAVE/DAI pool */ | |
await aaveToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
ethers.utils.parseUnits('.25', 18) | |
); | |
await daiToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
ethers.utils.parseUnits('14', 18) | |
); | |
/* Mint Liquidity Tokens for the Liquidity Provider */ | |
await tradingPairExchange.mint(liquidityProvider.address); | |
const liquidityProviderAccountBalance = await tradingPairExchange.balanceOf(liquidityProvider.address); | |
const formattedLiquidityProviderAccountBalance = ethers.utils.formatUnits(liquidityProviderAccountBalance); | |
expect(formattedLiquidityProviderAccountBalance).to.equal("9.354143466934852463"); | |
}); | |
}); | |
describe("Burning Liquidity Tokens", () => { | |
async function deploySecondaryTradingPairExchangeFixture() { | |
await network.provider.send("hardhat_reset"); | |
/* AAVE/DAI, 1 AAVE = $56 USD, 1 DAI = $1 USD */ | |
const amountADesired = ethers.utils.parseUnits('1', 18); //AAVE | |
const amountBDesired = ethers.utils.parseUnits('56', 18); //DAI | |
const [deployer, liquidityProvider, exchangeDev] = await ethers.getSigners(); | |
const FactoryContract = await ethers.getContractFactory("Factory"); | |
const factory = await FactoryContract.deploy(deployer.address); | |
await factory.deployed(); | |
const AaveTokenContract = await ethers.getContractFactory("ERC20Basic"); | |
const aaveToken = await AaveTokenContract.deploy( | |
"Aave Stablecoin", | |
"AAVE", | |
18, | |
deployer.address | |
); | |
await aaveToken.deployed(); | |
const DaiTokenContract = await ethers.getContractFactory("ERC20Basic"); | |
const daiToken = await DaiTokenContract.deploy( | |
"Dai Stablecoin", | |
"DAI", | |
18, | |
deployer.address | |
); | |
await daiToken.deployed(); | |
/* Mint tokens for Liquidity Provider's account */ | |
await aaveToken.mint( | |
liquidityProvider.address, | |
ethers.utils.parseUnits('130', 18) | |
); | |
await daiToken.mint( | |
liquidityProvider.address, | |
ethers.utils.parseUnits('130', 18) | |
); | |
/* Liquidity Provider approves Router to transfer tokens */ | |
await aaveToken.connect(liquidityProvider).approve( | |
deployer.address, | |
ethers.utils.parseUnits('130', 18) | |
); | |
await daiToken.connect(liquidityProvider).approve( | |
deployer.address, | |
ethers.utils.parseUnits('130', 18) | |
); | |
const tradingPairExchangeContract = await factory.createTradingPair( | |
aaveToken.address, | |
daiToken.address | |
); | |
const receipt = await tradingPairExchangeContract.wait(); | |
const tradingPairExchangeAddress = receipt.events[0].args[2]; | |
const tradingPairExchange = await ethers.getContractAt( | |
"TradingPairExchange", | |
tradingPairExchangeAddress, | |
deployer | |
); | |
/* First depositing of liquidity */ | |
await aaveToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
amountADesired | |
); | |
await daiToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
amountBDesired | |
); | |
await tradingPairExchange.mint(liquidityProvider.address); | |
return { | |
aaveToken, | |
daiToken, | |
amountADesired, | |
amountBDesired, | |
deployer, | |
liquidityProvider, | |
factory, | |
exchangeDev, | |
tradingPairExchange | |
} | |
} | |
it("should debit a Liquidity Provider's account", async() => { | |
const { | |
deployer, | |
tradingPairExchange, | |
liquidityProvider | |
} = await loadFixture(deploySecondaryTradingPairExchangeFixture); | |
/* Liquidity Provider approve Deployer to transfer Liquidity Tokens */ | |
await tradingPairExchange.connect(liquidityProvider).approve( | |
deployer.address, | |
ethers.utils.parseUnits('5', 18) | |
); | |
/* Transfer Liquidity Tokens to TradingPairExchange */ | |
await tradingPairExchange.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
ethers.utils.parseUnits('4', 18) | |
); | |
/* Burn Liquidity Tokens */ | |
await tradingPairExchange.burn(liquidityProvider.address); | |
/* Format Liquidity token balances */ | |
const liquidityProviderBalance = await tradingPairExchange.balanceOf(liquidityProvider.address); | |
const formattedLiquidityProviderBalance = ethers.utils.formatUnits(liquidityProviderBalance); | |
const liquidityTokenTotalSupply = await tradingPairExchange.totalSupply(); | |
const formattedLiquidityTokenTotalSupply = ethers.utils.formatUnits(liquidityTokenTotalSupply); | |
/* Expect correct debitted amount of Liquidity Tokens */ | |
expect(formattedLiquidityProviderBalance).to.equal("3.483314773547881771"); | |
expect(formattedLiquidityTokenTotalSupply).to.equal("3.483314773547882771"); | |
}); | |
it("should send to Liquidity Provider ERC20 tokens proportional to amount of Liquidity Tokens burned", async() => { | |
const { | |
aaveToken, | |
daiToken, | |
deployer, | |
tradingPairExchange, | |
liquidityProvider | |
} = await loadFixture(deploySecondaryTradingPairExchangeFixture); | |
/* Liquidity Provider approve Deployer to transfer Liquidity Tokens */ | |
await tradingPairExchange.connect(liquidityProvider).approve( | |
deployer.address, | |
ethers.utils.parseUnits('7.483314773547881771', 18) | |
); | |
/* Transfer Liquidity Tokens to TradingPairExchange */ | |
await tradingPairExchange.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
ethers.utils.parseUnits('7.483314773547881771', 18) | |
); | |
/* Burn Liquidity Tokens */ | |
await tradingPairExchange.burn(liquidityProvider.address); | |
/* Formatted ERC20 Token balance */ | |
const amountAReturned = await aaveToken.balanceOf(liquidityProvider.address); | |
const amountBReturned = await daiToken.balanceOf(liquidityProvider.address); | |
const formattedAaveTokensCredited = ethers.utils.formatUnits(amountAReturned); | |
const formattedDaiTokensCredited = ethers.utils.formatUnits(amountBReturned); | |
/* Expect Liquidity Provider to now have additional AAVE and DAI tokens in their accounts */ | |
expect(formattedAaveTokensCredited).to.equal("129.999999999999999866"); | |
expect(formattedDaiTokensCredited).to.equal("129.999999999999992516"); | |
}); | |
it("should remit payment of the Protocol Fee to the Exchange Developer account", async() => { | |
const { | |
aaveToken, | |
daiToken, | |
deployer, | |
exchangeDev, | |
factory, | |
tradingPairExchange, | |
liquidityProvider | |
} = await loadFixture(deploySecondaryTradingPairExchangeFixture); | |
/* Set Protocol Fee recipient to DEX Developer account */ | |
await factory.setFeeTo(exchangeDev.address); | |
/* Second deposit of liquidity into AAVE/DAI pool */ | |
await aaveToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
ethers.utils.parseUnits('.25', 18) | |
); | |
await daiToken.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
ethers.utils.parseUnits('14', 18) | |
); | |
/* Mint relevant amount of Liquidity Tokens */ | |
await tradingPairExchange.mint(liquidityProvider.address); | |
/* Liquidity Provider approve Deployer to transfer Liquidity Tokens */ | |
await tradingPairExchange.connect(liquidityProvider).approve( | |
deployer.address, | |
ethers.utils.parseUnits('5', 18) | |
); | |
/* Transfer Liquidity Tokens to TradingPairExchange */ | |
await tradingPairExchange.transferFrom( | |
liquidityProvider.address, | |
tradingPairExchange.address, | |
ethers.utils.parseUnits('4', 18) | |
); | |
/* Burn Liquidity Tokens */ | |
await tradingPairExchange.burn(liquidityProvider.address); | |
/* Expectation */ | |
const dexDeveloperAccountBalance = await tradingPairExchange.balanceOf(exchangeDev.address); | |
const formattedDexDeveloperAccountBalance = ethers.utils.formatUnits(dexDeveloperAccountBalance); | |
expect(formattedDexDeveloperAccountBalance).to.equal("0.322556671273615636"); | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment