Skip to content

Commit 17d7505

Browse files
authored
Merge pull request #14 from kirilradkov14/fix/unit-testing
Fix/unit testing
2 parents 90de27b + 53b7f5f commit 17d7505

File tree

4 files changed

+38
-39
lines changed

4 files changed

+38
-39
lines changed

README.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
### 📈 Exponential Bonding Curve
2828
- **Instant Liquidity**: No pre-locking required - liquidity forms as users buy
2929
- **Fair Price Discovery**: Algorithmic price adjustment based on market activity
30-
- **Anti-Dump Protection**: Progressive sell penalties protect early adopters
3130

3231
### 🔄 Automated Liquidity Migration
3332
- **Seamless Uniswap Transition**: Migrates liquidity to Uniswap V2 at threshold
@@ -42,7 +41,7 @@ graph TD;
4241
A[Factory Contract] -->|Deploys| B[Proxy Contract];
4342
B -->|References| C[Logic Contract];
4443
C -->|Interacts With| D[Bonding Curve];
45-
D -->|Feeds Data To| E[Uniswap Migrator];
44+
D -->|Migrates LP| E[UniswapV2Router];
4645
4746
```
4847

@@ -58,7 +57,7 @@ S: Current ETH supply (contract balance)
5857

5958
E: ETH amount sent
6059

61-
k: Curve steepness parameter (configurable)
60+
k: Curve steepness parameter
6261

6362
P₀: Initial price per token
6463

@@ -85,7 +84,7 @@ T_in: Tokens being sold
8584
### Installation
8685
```bash
8786
# Clone repository
88-
git clone https://github.com/yourusername/launchpad-contracts.git
87+
git clone https://github.com/kirilradkov14/launchpad-contracts.git
8988
cd launchpad-contracts
9089

9190
# Install dependencies
@@ -125,16 +124,16 @@ forge test --match-contract LaunchpadTests
125124

126125
### Testnet
127126
```bash
128-
./deploy.sh goerli
127+
./deploy.sh holesky
129128
```
130129

131130
### Local Development
132131
```bash
133132
# Start local node
134133
anvil
135134

136-
# In separate terminal
137-
./deploy.sh local
135+
# In anvil terminal
136+
forge script script/LaunchpadFactory.s.sol:LaunchpadDeployerScript --rpc-url http://localhost:8545 --broadcast
138137
```
139138

140139
## 📊 Test Coverage

src/Launchpad.sol

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.s
55
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
66
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
77
import {ReentrancyGuardTransient} from "@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol";
8-
import {Formula} from "./libraries/Formula.sol";
8+
import {BondingCurve} from "./libraries/BondingCurve.sol";
99
import {ILaunchpad} from "./interfaces/launchpad/ILaunchpad.sol";
1010
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
1111
import {IWETH} from "./interfaces/IWETH.sol";
@@ -106,7 +106,7 @@ contract Launchpad is Initializable, ReentrancyGuardTransient, ILaunchpad {
106106
return amountOut;
107107
}
108108

109-
amountOut = Formula.calculatePurchaseReturn(ethSupply, ethAmount);
109+
amountOut = BondingCurve.calculatePurchaseReturn(ethSupply, ethAmount);
110110
if (amountOut > tokenSupply) revert LaunchpadInsufficientLiquidity();
111111
if (amountOut < amountOutMin) revert LaunchpadInsufficientOutputAmount();
112112

@@ -135,7 +135,7 @@ contract Launchpad is Initializable, ReentrancyGuardTransient, ILaunchpad {
135135
{
136136
if (amountIn == 0) revert LaunchpadInsufficientInputAmount();
137137

138-
uint256 ethReturn = Formula.calculateSellReturn(ethSupply, amountIn);
138+
uint256 ethReturn = BondingCurve.calculateSellReturn(ethSupply, amountIn);
139139
if (ethReturn < amountOutMin) revert LaunchpadInsufficientOutputAmount();
140140
if (ethReturn > ethSupply) revert LaunchpadInsufficientLiquidity();
141141

@@ -158,7 +158,7 @@ contract Launchpad is Initializable, ReentrancyGuardTransient, ILaunchpad {
158158
* @return amountOut The amount of ETH that would be received.
159159
*/
160160
function getEthersOutAtCurrentSupply(uint256 amountIn) public view returns (uint256 amountOut) {
161-
amountOut = Formula.calculateSellReturn(ethSupply, amountIn);
161+
amountOut = BondingCurve.calculateSellReturn(ethSupply, amountIn);
162162
}
163163

164164
/**
@@ -167,7 +167,7 @@ contract Launchpad is Initializable, ReentrancyGuardTransient, ILaunchpad {
167167
* @return amountOut The amount of tokens that would be received.
168168
*/
169169
function getTokensOutAtCurrentSupply(uint256 amountIn) public view returns (uint256 amountOut) {
170-
amountOut = Formula.calculatePurchaseReturn(ethSupply, amountIn);
170+
amountOut = BondingCurve.calculatePurchaseReturn(ethSupply, amountIn);
171171
}
172172

173173
/**
@@ -180,7 +180,7 @@ contract Launchpad is Initializable, ReentrancyGuardTransient, ILaunchpad {
180180

181181
if (excess > 0) {
182182
payable(msg.sender).sendValue(excess);
183-
amountOut = Formula.calculatePurchaseReturn(ethSupply, contribution);
183+
amountOut = BondingCurve.calculatePurchaseReturn(ethSupply, contribution);
184184
if (amountOut > tokenSupply) revert LaunchpadInsufficientLiquidity();
185185
ethSupply += contribution;
186186
tokenSupply -= amountOut;

src/libraries/Formula.sol renamed to src/libraries/BondingCurve.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ pragma solidity ^0.8.28;
44
import "./Math64x64.sol";
55

66
/**
7-
* @title Formula
7+
* @title BondingCurve
88
* @dev Implements an exponential bonding curve for token pricing using the Math64x64 library.
99
*/
10-
library Formula {
10+
library BondingCurve {
1111
using Math64x64 for int128;
1212

1313
/**

test/Formula.t.sol renamed to test/BondingCurve.t.sol

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
pragma solidity ^0.8.28;
33

44
import "forge-std/Test.sol";
5-
import "../src/libraries/Formula.sol";
5+
import "../src/libraries/BondingCurve.sol";
66

7-
contract FormulaTest is Test {
8-
// Constants from the Formula library
7+
contract BondingCurveTest is Test {
8+
// Constants from the BondingCurve library
99
uint256 constant BASE_PRICE = 30_677_636_300;
1010
uint256 constant EXP_FACTOR = 4_000_000;
1111
uint256 constant SCALING_FACTOR = 1e18;
@@ -15,12 +15,12 @@ contract FormulaTest is Test {
1515
function testPurchaseBaseCases() public pure {
1616
// Test purchase with 0 ETH supply and 1 ETH input
1717
// Should return some tokens
18-
uint256 tokensOut = Formula.calculatePurchaseReturn(0, 1 ether);
18+
uint256 tokensOut = BondingCurve.calculatePurchaseReturn(0, 1 ether);
1919
assert(tokensOut > 0);
2020

2121
// Test purchase with 0 ETH input
2222
// Should return 0
23-
uint256 zeroOut = Formula.calculatePurchaseReturn(1 ether, 0);
23+
uint256 zeroOut = BondingCurve.calculatePurchaseReturn(1 ether, 0);
2424
assert(zeroOut == 0);
2525
}
2626

@@ -30,8 +30,8 @@ contract FormulaTest is Test {
3030
uint256 supply1 = 10 ether;
3131
uint256 supply2 = 20 ether;
3232

33-
uint256 tokens1 = Formula.calculatePurchaseReturn(supply1, ethIn);
34-
uint256 tokens2 = Formula.calculatePurchaseReturn(supply2, ethIn);
33+
uint256 tokens1 = BondingCurve.calculatePurchaseReturn(supply1, ethIn);
34+
uint256 tokens2 = BondingCurve.calculatePurchaseReturn(supply2, ethIn);
3535

3636
assertTrue(tokens2 < tokens1, "Price should increase with supply");
3737

@@ -43,7 +43,7 @@ contract FormulaTest is Test {
4343

4444
function testSellBaseCases() public {
4545
// Test sell with 0 token input
46-
uint256 ethOut = Formula.calculateSellReturn(1 ether, 0);
46+
uint256 ethOut = BondingCurve.calculateSellReturn(1 ether, 0);
4747
assertEq(ethOut, 0, "Should return 0 ETH for 0 tokens");
4848
}
4949

@@ -54,8 +54,8 @@ contract FormulaTest is Test {
5454
// Test selling different amounts
5555
uint256 sellAmount1 = 1000 ether;
5656

57-
uint256 ethOut1 = Formula.calculateSellReturn(initialEthSupply, sellAmount1);
58-
uint256 ethOut2 = Formula.calculateSellReturn(initialEthSupply - ethOut1, sellAmount1);
57+
uint256 ethOut1 = BondingCurve.calculateSellReturn(initialEthSupply, sellAmount1);
58+
uint256 ethOut2 = BondingCurve.calculateSellReturn(initialEthSupply - ethOut1, sellAmount1);
5959

6060
assertTrue(ethOut2 < ethOut1, "Price should decrease after selling");
6161
}
@@ -65,10 +65,10 @@ contract FormulaTest is Test {
6565
uint256 ethIn = 1 ether;
6666

6767
// Buy tokens
68-
uint256 tokensReceived = Formula.calculatePurchaseReturn(ethSupply, ethIn);
68+
uint256 tokensReceived = BondingCurve.calculatePurchaseReturn(ethSupply, ethIn);
6969

7070
// Sell the same amount of tokens
71-
uint256 ethOut = Formula.calculateSellReturn(ethSupply + ethIn, tokensReceived);
71+
uint256 ethOut = BondingCurve.calculateSellReturn(ethSupply + ethIn, tokensReceived);
7272

7373
// Should get slightly less ETH due to the curve mechanics
7474
assertTrue(ethOut < ethIn, "Should have some slippage");
@@ -78,18 +78,18 @@ contract FormulaTest is Test {
7878
function testExtremeValues() public {
7979
// Test with very small amounts
8080
uint256 tinyEth = 1 wei;
81-
uint256 tokensForTiny = Formula.calculatePurchaseReturn(0, tinyEth);
81+
uint256 tokensForTiny = BondingCurve.calculatePurchaseReturn(0, tinyEth);
8282
// Due to precision limitations with fixed-point math, very small amounts might return 0
8383
assertEq(tokensForTiny, 0, "Tiny amounts should return 0 due to precision limits");
8484

8585
// Test with more reasonable minimum amount (0.0001 ether)
8686
uint256 smallEth = 1e14; // 0.0001 ether
87-
uint256 tokensForSmall = Formula.calculatePurchaseReturn(0, smallEth);
87+
uint256 tokensForSmall = BondingCurve.calculatePurchaseReturn(0, smallEth);
8888
assertTrue(tokensForSmall > 0, "Should handle small amounts");
8989

9090
// Test with large amounts
9191
uint256 largeEth = 1000000 ether;
92-
uint256 tokensForLarge = Formula.calculatePurchaseReturn(0, largeEth);
92+
uint256 tokensForLarge = BondingCurve.calculatePurchaseReturn(0, largeEth);
9393
assertTrue(tokensForLarge > 0, "Should handle large amounts");
9494

9595
// Test progression of amounts
@@ -100,9 +100,9 @@ contract FormulaTest is Test {
100100
uint256 ethSupply = 10 ether;
101101

102102
// Try to sell more tokens than possible
103-
uint256 maxTokens = Formula.calculatePurchaseReturn(0, ethSupply);
104-
vm.expectRevert(abi.encodeWithSignature("FormulaInvalidTokenAmount()"));
105-
Formula.calculateSellReturn(ethSupply, maxTokens * 2);
103+
uint256 maxTokens = BondingCurve.calculatePurchaseReturn(0, ethSupply);
104+
vm.expectRevert();
105+
BondingCurve.calculateSellReturn(ethSupply, maxTokens * 2);
106106
}
107107

108108
function testPriceProgression() public {
@@ -112,7 +112,7 @@ contract FormulaTest is Test {
112112

113113
// Test price progression over multiple purchases
114114
for (uint256 i = 0; i < 10; i++) {
115-
uint256 tokenAmount = Formula.calculatePurchaseReturn(ethSupply, ethIncrement);
115+
uint256 tokenAmount = BondingCurve.calculatePurchaseReturn(ethSupply, ethIncrement);
116116
assertTrue(tokenAmount < lastTokenAmount, "Price must increase monotonically");
117117
assertTrue(tokenAmount > 0, "Should always return some tokens");
118118

@@ -123,7 +123,7 @@ contract FormulaTest is Test {
123123

124124
function testCurveParameters() public {
125125
// Test that the curve parameters produce expected behavior
126-
uint256 initialPurchase = Formula.calculatePurchaseReturn(0, 1 ether);
126+
uint256 initialPurchase = BondingCurve.calculatePurchaseReturn(0, 1 ether);
127127

128128
// Log values for analysis
129129
console.log("Initial purchase tokens:", initialPurchase);
@@ -135,13 +135,13 @@ contract FormulaTest is Test {
135135
assertTrue(initialPurchase > 0, "Should return tokens");
136136

137137
// 2. Verify curve steepness
138-
uint256 laterPurchase = Formula.calculatePurchaseReturn(50 ether, 1 ether);
138+
uint256 laterPurchase = BondingCurve.calculatePurchaseReturn(50 ether, 1 ether);
139139
assertTrue(laterPurchase < initialPurchase / 2, "Curve should be sufficiently steep");
140140

141141
// 3. Verify the exponential nature
142-
uint256 purchase1 = Formula.calculatePurchaseReturn(0, 1 ether);
143-
uint256 purchase2 = Formula.calculatePurchaseReturn(1 ether, 1 ether);
144-
uint256 purchase3 = Formula.calculatePurchaseReturn(2 ether, 1 ether);
142+
uint256 purchase1 = BondingCurve.calculatePurchaseReturn(0, 1 ether);
143+
uint256 purchase2 = BondingCurve.calculatePurchaseReturn(1 ether, 1 ether);
144+
uint256 purchase3 = BondingCurve.calculatePurchaseReturn(2 ether, 1 ether);
145145

146146
assertTrue(purchase1 > purchase2, "Price should increase");
147147
assertTrue(purchase2 > purchase3, "Price should increase");

0 commit comments

Comments
 (0)