Skip to content

Commit 00a00fb

Browse files
Copilotsonnyquinn24
andcommitted
Implement PR #24 review suggestions: fix test calculations and set-prices validation
Co-authored-by: sonnyquinn24 <[email protected]>
1 parent 9f1c15e commit 00a00fb

File tree

6 files changed

+407
-3
lines changed

6 files changed

+407
-3
lines changed

contracts/MockERC20.sol

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.24;
3+
4+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
5+
6+
contract MockERC20 is ERC20 {
7+
uint8 private _decimals;
8+
9+
constructor(
10+
string memory name,
11+
string memory symbol,
12+
uint8 decimals_
13+
) ERC20(name, symbol) {
14+
_decimals = decimals_;
15+
_mint(msg.sender, 1000000 * 10**decimals_); // Mint 1M tokens to deployer
16+
}
17+
18+
function decimals() public view virtual override returns (uint8) {
19+
return _decimals;
20+
}
21+
22+
function mint(address to, uint256 amount) public {
23+
_mint(to, amount);
24+
}
25+
}

contracts/SEQICO.sol

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ contract SEQICO is Ownable {
1414
uint256 public pricePerTokenUSDC;
1515

1616
event TokensPurchased(address indexed buyer, uint256 amount, string payment);
17+
event PriceUpdated(string indexed paymentMethod, uint256 newPrice);
18+
19+
// Minimum price constants (representing $3 minimum)
20+
uint256 public constant MIN_PRICE_USD_STABLECOINS = 3_000_000; // $3 with 6 decimals
21+
uint256 public constant MIN_PRICE_ETH = 0.001 ether; // 0.001 ETH minimum (assuming ETH > $3000)
1722

1823
constructor(
1924
address _seqToken,
@@ -26,6 +31,12 @@ contract SEQICO is Ownable {
2631
seqToken = IERC20(_seqToken);
2732
usdt = IERC20(_usdt);
2833
usdc = IERC20(_usdc);
34+
35+
// Validate minimum prices
36+
require(_pricePerTokenETH >= MIN_PRICE_ETH, "ETH price below $3 minimum");
37+
require(_pricePerTokenUSDT >= MIN_PRICE_USD_STABLECOINS, "USDT price below $3 minimum");
38+
require(_pricePerTokenUSDC >= MIN_PRICE_USD_STABLECOINS, "USDC price below $3 minimum");
39+
2940
pricePerTokenETH = _pricePerTokenETH;
3041
pricePerTokenUSDT = _pricePerTokenUSDT;
3142
pricePerTokenUSDC = _pricePerTokenUSDC;
@@ -35,6 +46,36 @@ contract SEQICO is Ownable {
3546
seqToken = IERC20(_seqToken);
3647
}
3748

49+
/**
50+
* @dev Set the price per token for ETH purchases
51+
* @param _pricePerTokenETH New price in wei per token (must be >= $3 minimum)
52+
*/
53+
function setPriceETH(uint256 _pricePerTokenETH) external onlyOwner {
54+
require(_pricePerTokenETH >= MIN_PRICE_ETH, "ETH price below $3 minimum");
55+
pricePerTokenETH = _pricePerTokenETH;
56+
emit PriceUpdated("ETH", _pricePerTokenETH);
57+
}
58+
59+
/**
60+
* @dev Set the price per token for USDT purchases
61+
* @param _pricePerTokenUSDT New price with 6 decimals (must be >= $3)
62+
*/
63+
function setPriceUSDT(uint256 _pricePerTokenUSDT) external onlyOwner {
64+
require(_pricePerTokenUSDT >= MIN_PRICE_USD_STABLECOINS, "USDT price below $3 minimum");
65+
pricePerTokenUSDT = _pricePerTokenUSDT;
66+
emit PriceUpdated("USDT", _pricePerTokenUSDT);
67+
}
68+
69+
/**
70+
* @dev Set the price per token for USDC purchases
71+
* @param _pricePerTokenUSDC New price with 6 decimals (must be >= $3)
72+
*/
73+
function setPriceUSDC(uint256 _pricePerTokenUSDC) external onlyOwner {
74+
require(_pricePerTokenUSDC >= MIN_PRICE_USD_STABLECOINS, "USDC price below $3 minimum");
75+
pricePerTokenUSDC = _pricePerTokenUSDC;
76+
emit PriceUpdated("USDC", _pricePerTokenUSDC);
77+
}
78+
3879
function buyWithETH(uint256 tokenAmount) external payable {
3980
require(tokenAmount > 0, "Amount must be greater than 0");
4081
uint256 requiredETH = pricePerTokenETH * tokenAmount;

hardhat.config.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,25 @@ const config = {
33
solidity: "0.8.24",
44
networks: {
55
hardhat: {
6-
chainId: 31337
6+
type: "edr-simulated"
77
},
88
sepolia: {
9+
type: "http",
910
url: process.env.SEPOLIA_RPC_URL || `https://sepolia.infura.io/v3/${process.env.INFURA_API_KEY}`,
1011
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
1112
},
1213
mainnet: {
14+
type: "http",
1315
url: process.env.MAINNET_RPC_URL || `https://mainnet.infura.io/v3/${process.env.INFURA_API_KEY}`,
1416
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
1517
},
1618
polygon: {
19+
type: "http",
1720
url: process.env.POLYGON_RPC_URL || `https://polygon-mainnet.infura.io/v3/${process.env.INFURA_API_KEY}`,
1821
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
1922
},
2023
bsc: {
24+
type: "http",
2125
url: process.env.BSC_RPC_URL || "https://bsc-dataseed1.binance.org",
2226
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
2327
},

package.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
"description": "Deployment",
55
"main": "index.js",
66
"scripts": {
7-
"test": "echo \"Error: no test specified\" && exit 1"
7+
"test": "hardhat test",
8+
"compile": "hardhat compile",
9+
"deploy": "hardhat run scripts/deploy.js"
810
},
911
"keywords": [],
1012
"author": "",
@@ -14,5 +16,9 @@
1416
"@openzeppelin/contracts": "^5.4.0",
1517
"hardhat": "^3.0.3"
1618
},
17-
"type": "module"
19+
"type": "module",
20+
"dependencies": {
21+
"@nomicfoundation/hardhat-chai-matchers": "^2.1.0",
22+
"solc": "^0.8.30"
23+
}
1824
}

scripts/set-prices.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { ethers } from "hardhat";
2+
3+
async function main() {
4+
// Configuration - update these addresses with your deployed contracts
5+
const SEQICO_ADDRESS = "YOUR_DEPLOYED_SEQICO_ADDRESS_HERE"; // <-- Replace with your deployed SEQICO address
6+
if (
7+
!SEQICO_ADDRESS ||
8+
SEQICO_ADDRESS === "YOUR_DEPLOYED_SEQICO_ADDRESS_HERE" ||
9+
SEQICO_ADDRESS === "0x..." ||
10+
!/^0x[a-fA-F0-9]{40}$/.test(SEQICO_ADDRESS)
11+
) {
12+
throw new Error("❌ Please set SEQICO_ADDRESS to your deployed SEQICO contract address before running this script.");
13+
}
14+
15+
// New prices to set (must be >= $3 minimum)
16+
const newPriceETH = ethers.parseEther("0.015"); // 0.015 ETH per token
17+
const newPriceUSDT = 5_000_000; // $5 USDT (6 decimals)
18+
const newPriceUSDC = 4_500_000; // $4.5 USDC (6 decimals)
19+
20+
console.log("Setting new prices for SEQICO contract...");
21+
console.log("Contract address:", SEQICO_ADDRESS);
22+
23+
// Get the contract instance
24+
const SEQICO = await ethers.getContractFactory("SEQICO");
25+
const seqICO = SEQICO.attach(SEQICO_ADDRESS);
26+
27+
// Verify minimum price constants
28+
const minPriceETH = await seqICO.MIN_PRICE_ETH();
29+
const minPriceUSD = await seqICO.MIN_PRICE_USD_STABLECOINS();
30+
31+
console.log("Minimum price ETH:", ethers.formatEther(minPriceETH), "ETH");
32+
console.log("Minimum price USD stablecoins:", minPriceUSD.toString(), "(representing $3)");
33+
34+
// Check current prices
35+
console.log("\nCurrent prices:");
36+
console.log("ETH:", ethers.formatEther(await seqICO.pricePerTokenETH()), "ETH per token");
37+
console.log("USDT:", (await seqICO.pricePerTokenUSDT()).toString(), "(6 decimals)");
38+
console.log("USDC:", (await seqICO.pricePerTokenUSDC()).toString(), "(6 decimals)");
39+
40+
// Validate new prices meet minimum requirements
41+
if (newPriceETH < minPriceETH) {
42+
console.error("Error: New ETH price is below minimum!");
43+
return;
44+
}
45+
if (newPriceUSDT < minPriceUSD) {
46+
console.error("Error: New USDT price is below $3 minimum!");
47+
return;
48+
}
49+
if (newPriceUSDC < minPriceUSD) {
50+
console.error("Error: New USDC price is below $3 minimum!");
51+
return;
52+
}
53+
54+
try {
55+
// Set new ETH price
56+
console.log("\nSetting new ETH price...");
57+
const tx1 = await seqICO.setPriceETH(newPriceETH);
58+
await tx1.wait();
59+
console.log("✅ ETH price updated to:", ethers.formatEther(newPriceETH), "ETH per token");
60+
61+
// Set new USDT price
62+
console.log("Setting new USDT price...");
63+
const tx2 = await seqICO.setPriceUSDT(newPriceUSDT);
64+
await tx2.wait();
65+
console.log("✅ USDT price updated to:", newPriceUSDT.toString(), "($" + (newPriceUSDT / 1_000_000).toFixed(2) + ")");
66+
67+
// Set new USDC price
68+
console.log("Setting new USDC price...");
69+
const tx3 = await seqICO.setPriceUSDC(newPriceUSDC);
70+
await tx3.wait();
71+
console.log("✅ USDC price updated to:", newPriceUSDC.toString(), "($" + (newPriceUSDC / 1_000_000).toFixed(2) + ")");
72+
73+
console.log("\n🎉 All prices updated successfully!");
74+
75+
// Verify the updates
76+
console.log("\nUpdated prices:");
77+
console.log("ETH:", ethers.formatEther(await seqICO.pricePerTokenETH()), "ETH per token");
78+
console.log("USDT:", (await seqICO.pricePerTokenUSDT()).toString(), "(6 decimals)");
79+
console.log("USDC:", (await seqICO.pricePerTokenUSDC()).toString(), "(6 decimals)");
80+
81+
} catch (error) {
82+
console.error("Error setting prices:", error.message);
83+
if (error.message.includes("price below $3 minimum")) {
84+
console.error("Make sure all prices meet the $3 minimum requirement!");
85+
}
86+
if (error.message.includes("OwnableUnauthorizedAccount")) {
87+
console.error("Only the contract owner can set prices!");
88+
}
89+
}
90+
}
91+
92+
main().catch((error) => {
93+
console.error(error);
94+
process.exitCode = 1;
95+
});

0 commit comments

Comments
 (0)