feat(blockchain): 部署 eUSDT 和 fUSDT 代币合约
新增两个 ERC-20 代币合约,部署在 KAVA 主网: ## eUSDT (Energy USDT) - 合约地址: 0x7C3275D808eFbAE90C06C7E3A9AfDdcAa8563931 - 总供应量: 100.02亿 (10,002,000,000) - 交易哈希: 0x5bebaa4a35378438ba5c891972024a1766935d2e01397a33502aa99e956a6b19 ## fUSDT (Future USDT) - 合约地址: 0x14dc4f7d3E4197438d058C3D156dd9826A161134 - 总供应量: 1万亿 (1,000,000,000,000) - 交易哈希: 0x071f535971bc3a134dd26c182b6f05c53f0c3783e91fe6ef471d6c914e4cdb06 ## 共同特性 - 固定供应量,不可增发 - 6位小数精度(与USDT一致) - 标准ERC-20接口 - 部署者: 0x4F7E78d6B7C5FC502Ec7039848690f08c8970F1E ## 文件结构 - eUSDT/: 合约源码、编译脚本、部署脚本、README - fUSDT/: 合约源码、编译脚本、部署脚本、README - contracts/README.md: 补充dUSDT说明文档 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
8619b0bf26
commit
07498271d3
|
|
@ -0,0 +1,78 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.19;
|
||||
|
||||
/**
|
||||
* @title EnergyUSDT
|
||||
* @dev Fixed supply ERC-20 token - NO MINTING CAPABILITY
|
||||
* Total Supply: 10,002,000,000 (100.02 Billion) tokens with 6 decimals (matching USDT)
|
||||
*
|
||||
* IMPORTANT: This contract has NO mint function and NO way to increase supply.
|
||||
* All tokens are minted to the deployer at construction time.
|
||||
*/
|
||||
contract EnergyUSDT {
|
||||
string public constant name = "Energy USDT";
|
||||
string public constant symbol = "eUSDT";
|
||||
uint8 public constant decimals = 6;
|
||||
|
||||
// Fixed total supply: 100.02 billion tokens (10,002,000,000 * 10^6)
|
||||
uint256 public constant totalSupply = 10_002_000_000 * 10**6;
|
||||
|
||||
mapping(address => uint256) private _balances;
|
||||
mapping(address => mapping(address => uint256)) private _allowances;
|
||||
|
||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||
|
||||
/**
|
||||
* @dev Constructor - mints entire fixed supply to deployer
|
||||
* No mint function exists - supply is permanently fixed
|
||||
*/
|
||||
constructor() {
|
||||
_balances[msg.sender] = totalSupply;
|
||||
emit Transfer(address(0), msg.sender, totalSupply);
|
||||
}
|
||||
|
||||
function balanceOf(address account) public view returns (uint256) {
|
||||
return _balances[account];
|
||||
}
|
||||
|
||||
function transfer(address to, uint256 amount) public returns (bool) {
|
||||
require(to != address(0), "Transfer to zero address");
|
||||
require(_balances[msg.sender] >= amount, "Insufficient balance");
|
||||
|
||||
unchecked {
|
||||
_balances[msg.sender] -= amount;
|
||||
_balances[to] += amount;
|
||||
}
|
||||
|
||||
emit Transfer(msg.sender, to, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function allowance(address owner, address spender) public view returns (uint256) {
|
||||
return _allowances[owner][spender];
|
||||
}
|
||||
|
||||
function approve(address spender, uint256 amount) public returns (bool) {
|
||||
require(spender != address(0), "Approve to zero address");
|
||||
_allowances[msg.sender][spender] = amount;
|
||||
emit Approval(msg.sender, spender, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function transferFrom(address from, address to, uint256 amount) public returns (bool) {
|
||||
require(from != address(0), "Transfer from zero address");
|
||||
require(to != address(0), "Transfer to zero address");
|
||||
require(_balances[from] >= amount, "Insufficient balance");
|
||||
require(_allowances[from][msg.sender] >= amount, "Insufficient allowance");
|
||||
|
||||
unchecked {
|
||||
_balances[from] -= amount;
|
||||
_balances[to] += amount;
|
||||
_allowances[from][msg.sender] -= amount;
|
||||
}
|
||||
|
||||
emit Transfer(from, to, amount);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
# eUSDT (Energy USDT)
|
||||
|
||||
## 代币信息
|
||||
|
||||
| 属性 | 值 |
|
||||
|------|-----|
|
||||
| 名称 | Energy USDT |
|
||||
| 符号 | eUSDT |
|
||||
| 精度 | 6 decimals |
|
||||
| 总供应量 | 10,002,000,000 (100.02亿) |
|
||||
| 标准 | ERC-20 |
|
||||
| 部署链 | KAVA Mainnet (Chain ID: 2222) |
|
||||
|
||||
## 合约特性
|
||||
|
||||
- **固定供应量**:100.02亿代币,部署时全部铸造给部署者
|
||||
- **不可增发**:合约中没有 mint 函数,供应量永久固定
|
||||
- **不可销毁**:合约层面无销毁功能
|
||||
- **不可升级**:合约逻辑永久固定
|
||||
- **标准ERC-20**:完全兼容所有主流钱包和DEX
|
||||
|
||||
## 部署步骤
|
||||
|
||||
### 1. 安装依赖
|
||||
|
||||
```bash
|
||||
cd backend/services/blockchain-service/contracts/eUSDT
|
||||
npm install
|
||||
```
|
||||
|
||||
### 2. 编译合约
|
||||
|
||||
```bash
|
||||
node compile.mjs
|
||||
```
|
||||
|
||||
编译后会在 `build/` 目录生成:
|
||||
- `EnergyUSDT.abi` - 合约ABI
|
||||
- `EnergyUSDT.bin` - 合约字节码
|
||||
|
||||
### 3. 部署合约
|
||||
|
||||
确保部署账户有足够的 KAVA 支付 gas 费(约 0.02 KAVA)。
|
||||
|
||||
```bash
|
||||
node deploy.mjs
|
||||
```
|
||||
|
||||
## 合约函数
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `name()` | 返回 "Energy USDT" |
|
||||
| `symbol()` | 返回 "eUSDT" |
|
||||
| `decimals()` | 返回 6 |
|
||||
| `totalSupply()` | 返回 10,002,000,000 * 10^6 |
|
||||
| `balanceOf(address)` | 查询账户余额 |
|
||||
| `transfer(address, uint256)` | 转账 |
|
||||
| `approve(address, uint256)` | 授权额度 |
|
||||
| `transferFrom(address, address, uint256)` | 代理转账 |
|
||||
| `allowance(address, address)` | 查询授权额度 |
|
||||
|
||||
## 事件
|
||||
|
||||
| 事件 | 说明 |
|
||||
|------|------|
|
||||
| `Transfer(from, to, value)` | 转账事件 |
|
||||
| `Approval(owner, spender, value)` | 授权事件 |
|
||||
|
||||
## 部署信息
|
||||
|
||||
| 网络 | 合约地址 | 区块浏览器 |
|
||||
|------|---------|-----------|
|
||||
| KAVA Mainnet | `0x7C3275D808eFbAE90C06C7E3A9AfDdcAa8563931` | https://kavascan.com/address/0x7C3275D808eFbAE90C06C7E3A9AfDdcAa8563931 |
|
||||
|
||||
**部署详情:**
|
||||
- 部署者/代币拥有者:`0x4F7E78d6B7C5FC502Ec7039848690f08c8970F1E`
|
||||
- 私钥:`0x886ea4cffe76c386fecf3ff321ac9ae913737c46c17bc6ce2413752144668a2a`
|
||||
- 初始持有量:10,002,000,000 eUSDT(全部代币)
|
||||
- 交易哈希:`0x5bebaa4a35378438ba5c891972024a1766935d2e01397a33502aa99e956a6b19`
|
||||
- 部署时间:2026-01-19
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import solc from 'solc';
|
||||
import fs from 'fs';
|
||||
|
||||
const source = fs.readFileSync('EnergyUSDT.sol', 'utf8');
|
||||
|
||||
const input = {
|
||||
language: 'Solidity',
|
||||
sources: {
|
||||
'EnergyUSDT.sol': {
|
||||
content: source
|
||||
}
|
||||
},
|
||||
settings: {
|
||||
optimizer: {
|
||||
enabled: true,
|
||||
runs: 200
|
||||
},
|
||||
evmVersion: 'paris', // Use paris to avoid PUSH0
|
||||
outputSelection: {
|
||||
'*': {
|
||||
'*': ['abi', 'evm.bytecode']
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const output = JSON.parse(solc.compile(JSON.stringify(input)));
|
||||
|
||||
if (output.errors) {
|
||||
output.errors.forEach(err => {
|
||||
console.log(err.formattedMessage);
|
||||
});
|
||||
|
||||
// Check for actual errors (not just warnings)
|
||||
const hasErrors = output.errors.some(err => err.severity === 'error');
|
||||
if (hasErrors) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const contract = output.contracts['EnergyUSDT.sol']['EnergyUSDT'];
|
||||
const bytecode = contract.evm.bytecode.object;
|
||||
const abi = contract.abi;
|
||||
|
||||
fs.mkdirSync('build', { recursive: true });
|
||||
fs.writeFileSync('build/EnergyUSDT.bin', bytecode);
|
||||
fs.writeFileSync('build/EnergyUSDT.abi', JSON.stringify(abi, null, 2));
|
||||
|
||||
console.log('Compiled successfully!');
|
||||
console.log('Bytecode length:', bytecode.length);
|
||||
console.log('ABI functions:', abi.filter(x => x.type === 'function').map(x => x.name).join(', '));
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
import { ethers } from 'ethers';
|
||||
import fs from 'fs';
|
||||
|
||||
// Same deployer account as dUSDT
|
||||
const PRIVATE_KEY = '0x886ea4cffe76c386fecf3ff321ac9ae913737c46c17bc6ce2413752144668a2a';
|
||||
const RPC_URL = 'https://evm.kava.io';
|
||||
|
||||
// Contract bytecode
|
||||
const BYTECODE = '0x' + fs.readFileSync('build/EnergyUSDT.bin', 'utf8');
|
||||
const ABI = JSON.parse(fs.readFileSync('build/EnergyUSDT.abi', 'utf8'));
|
||||
|
||||
async function deploy() {
|
||||
// Connect to Kava mainnet
|
||||
const provider = new ethers.JsonRpcProvider(RPC_URL);
|
||||
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
|
||||
|
||||
console.log('Deployer address:', wallet.address);
|
||||
|
||||
// Check balance
|
||||
const balance = await provider.getBalance(wallet.address);
|
||||
console.log('Balance:', ethers.formatEther(balance), 'KAVA');
|
||||
|
||||
if (parseFloat(ethers.formatEther(balance)) < 0.01) {
|
||||
console.error('Insufficient KAVA balance for deployment!');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Get network info
|
||||
const network = await provider.getNetwork();
|
||||
console.log('Chain ID:', network.chainId.toString());
|
||||
|
||||
// Create contract factory
|
||||
const factory = new ethers.ContractFactory(ABI, BYTECODE, wallet);
|
||||
|
||||
console.log('Deploying EnergyUSDT (eUSDT) contract...');
|
||||
|
||||
// Deploy
|
||||
const contract = await factory.deploy();
|
||||
console.log('Transaction hash:', contract.deploymentTransaction().hash);
|
||||
|
||||
// Wait for deployment
|
||||
console.log('Waiting for confirmation...');
|
||||
await contract.waitForDeployment();
|
||||
|
||||
const contractAddress = await contract.getAddress();
|
||||
console.log('Contract deployed at:', contractAddress);
|
||||
|
||||
// Verify deployment
|
||||
console.log('\nVerifying deployment...');
|
||||
const name = await contract.name();
|
||||
const symbol = await contract.symbol();
|
||||
const decimals = await contract.decimals();
|
||||
const totalSupply = await contract.totalSupply();
|
||||
const ownerBalance = await contract.balanceOf(wallet.address);
|
||||
|
||||
console.log('Token name:', name);
|
||||
console.log('Token symbol:', symbol);
|
||||
console.log('Decimals:', decimals.toString());
|
||||
console.log('Total supply:', ethers.formatUnits(totalSupply, 6), 'eUSDT');
|
||||
console.log('Owner balance:', ethers.formatUnits(ownerBalance, 6), 'eUSDT');
|
||||
|
||||
console.log('\n=== DEPLOYMENT COMPLETE ===');
|
||||
console.log('Contract Address:', contractAddress);
|
||||
console.log('Explorer:', `https://kavascan.com/address/${contractAddress}`);
|
||||
|
||||
// Save deployment info
|
||||
const deploymentInfo = {
|
||||
network: 'KAVA Mainnet',
|
||||
chainId: 2222,
|
||||
contractAddress,
|
||||
deployer: wallet.address,
|
||||
transactionHash: contract.deploymentTransaction().hash,
|
||||
deployedAt: new Date().toISOString(),
|
||||
token: {
|
||||
name,
|
||||
symbol,
|
||||
decimals: decimals.toString(),
|
||||
totalSupply: totalSupply.toString()
|
||||
}
|
||||
};
|
||||
|
||||
fs.writeFileSync('deployment.json', JSON.stringify(deploymentInfo, null, 2));
|
||||
console.log('\nDeployment info saved to deployment.json');
|
||||
}
|
||||
|
||||
deploy().catch(console.error);
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"network": "KAVA Mainnet",
|
||||
"chainId": 2222,
|
||||
"contractAddress": "0x7C3275D808eFbAE90C06C7E3A9AfDdcAa8563931",
|
||||
"deployer": "0x4F7E78d6B7C5FC502Ec7039848690f08c8970F1E",
|
||||
"transactionHash": "0x5bebaa4a35378438ba5c891972024a1766935d2e01397a33502aa99e956a6b19",
|
||||
"deployedAt": "2026-01-19T13:25:28.071Z",
|
||||
"token": {
|
||||
"name": "Energy USDT",
|
||||
"symbol": "eUSDT",
|
||||
"decimals": "6",
|
||||
"totalSupply": "10002000000000000"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
{
|
||||
"name": "eusdt-contract",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "eusdt-contract",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"ethers": "^6.9.0",
|
||||
"solc": "^0.8.19"
|
||||
}
|
||||
},
|
||||
"node_modules/@adraffy/ens-normalize": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz",
|
||||
"integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@noble/curves": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
|
||||
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "1.3.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@noble/hashes": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
|
||||
"integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.2"
|
||||
}
|
||||
},
|
||||
"node_modules/aes-js": {
|
||||
"version": "4.0.0-beta.5",
|
||||
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz",
|
||||
"integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/command-exists": {
|
||||
"version": "1.2.9",
|
||||
"resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz",
|
||||
"integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/ethers": {
|
||||
"version": "6.16.0",
|
||||
"resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz",
|
||||
"integrity": "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/ethers-io/"
|
||||
},
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://www.buymeacoffee.com/ricmoo"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@adraffy/ens-normalize": "1.10.1",
|
||||
"@noble/curves": "1.2.0",
|
||||
"@noble/hashes": "1.3.2",
|
||||
"@types/node": "22.7.5",
|
||||
"aes-js": "4.0.0-beta.5",
|
||||
"tslib": "2.7.0",
|
||||
"ws": "8.17.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.11",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/js-sha3": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
|
||||
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/memorystream": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
|
||||
"integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
},
|
||||
"node_modules/solc": {
|
||||
"version": "0.8.19",
|
||||
"resolved": "https://registry.npmjs.org/solc/-/solc-0.8.19.tgz",
|
||||
"integrity": "sha512-yqurS3wzC4LdEvmMobODXqprV4MYJcVtinuxgrp61ac8K2zz40vXA0eSAskSHPgv8dQo7Nux39i3QBsHx4pqyA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"command-exists": "^1.2.8",
|
||||
"commander": "^8.1.0",
|
||||
"follow-redirects": "^1.12.1",
|
||||
"js-sha3": "0.8.0",
|
||||
"memorystream": "^0.3.1",
|
||||
"semver": "^5.5.0",
|
||||
"tmp": "0.0.33"
|
||||
},
|
||||
"bin": {
|
||||
"solcjs": "solc.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"os-tmpdir": "~1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
|
||||
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "eusdt-contract",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"description": "Energy USDT (eUSDT) ERC-20 Token Contract",
|
||||
"scripts": {
|
||||
"compile": "node compile.mjs",
|
||||
"deploy": "node deploy.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"ethers": "^6.9.0",
|
||||
"solc": "^0.8.19"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.19;
|
||||
|
||||
/**
|
||||
* @title FutureUSDT
|
||||
* @dev Fixed supply ERC-20 token - NO MINTING CAPABILITY
|
||||
* Total Supply: 1,000,000,000,000 (1 Trillion) tokens with 6 decimals (matching USDT)
|
||||
*
|
||||
* IMPORTANT: This contract has NO mint function and NO way to increase supply.
|
||||
* All tokens are minted to the deployer at construction time.
|
||||
*/
|
||||
contract FutureUSDT {
|
||||
string public constant name = "Future USDT";
|
||||
string public constant symbol = "fUSDT";
|
||||
uint8 public constant decimals = 6;
|
||||
|
||||
// Fixed total supply: 1 trillion tokens (1,000,000,000,000 * 10^6)
|
||||
uint256 public constant totalSupply = 1_000_000_000_000 * 10**6;
|
||||
|
||||
mapping(address => uint256) private _balances;
|
||||
mapping(address => mapping(address => uint256)) private _allowances;
|
||||
|
||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||
|
||||
/**
|
||||
* @dev Constructor - mints entire fixed supply to deployer
|
||||
* No mint function exists - supply is permanently fixed
|
||||
*/
|
||||
constructor() {
|
||||
_balances[msg.sender] = totalSupply;
|
||||
emit Transfer(address(0), msg.sender, totalSupply);
|
||||
}
|
||||
|
||||
function balanceOf(address account) public view returns (uint256) {
|
||||
return _balances[account];
|
||||
}
|
||||
|
||||
function transfer(address to, uint256 amount) public returns (bool) {
|
||||
require(to != address(0), "Transfer to zero address");
|
||||
require(_balances[msg.sender] >= amount, "Insufficient balance");
|
||||
|
||||
unchecked {
|
||||
_balances[msg.sender] -= amount;
|
||||
_balances[to] += amount;
|
||||
}
|
||||
|
||||
emit Transfer(msg.sender, to, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function allowance(address owner, address spender) public view returns (uint256) {
|
||||
return _allowances[owner][spender];
|
||||
}
|
||||
|
||||
function approve(address spender, uint256 amount) public returns (bool) {
|
||||
require(spender != address(0), "Approve to zero address");
|
||||
_allowances[msg.sender][spender] = amount;
|
||||
emit Approval(msg.sender, spender, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function transferFrom(address from, address to, uint256 amount) public returns (bool) {
|
||||
require(from != address(0), "Transfer from zero address");
|
||||
require(to != address(0), "Transfer to zero address");
|
||||
require(_balances[from] >= amount, "Insufficient balance");
|
||||
require(_allowances[from][msg.sender] >= amount, "Insufficient allowance");
|
||||
|
||||
unchecked {
|
||||
_balances[from] -= amount;
|
||||
_balances[to] += amount;
|
||||
_allowances[from][msg.sender] -= amount;
|
||||
}
|
||||
|
||||
emit Transfer(from, to, amount);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
# fUSDT (Future USDT)
|
||||
|
||||
## 代币信息
|
||||
|
||||
| 属性 | 值 |
|
||||
|------|-----|
|
||||
| 名称 | Future USDT |
|
||||
| 符号 | fUSDT |
|
||||
| 精度 | 6 decimals |
|
||||
| 总供应量 | 1,000,000,000,000 (1万亿) |
|
||||
| 标准 | ERC-20 |
|
||||
| 部署链 | KAVA Mainnet (Chain ID: 2222) |
|
||||
|
||||
## 合约特性
|
||||
|
||||
- **固定供应量**:1万亿代币,部署时全部铸造给部署者
|
||||
- **不可增发**:合约中没有 mint 函数,供应量永久固定
|
||||
- **不可销毁**:合约层面无销毁功能
|
||||
- **不可升级**:合约逻辑永久固定
|
||||
- **标准ERC-20**:完全兼容所有主流钱包和DEX
|
||||
|
||||
## 部署步骤
|
||||
|
||||
### 1. 安装依赖
|
||||
|
||||
```bash
|
||||
cd backend/services/blockchain-service/contracts/fUSDT
|
||||
npm install
|
||||
```
|
||||
|
||||
### 2. 编译合约
|
||||
|
||||
```bash
|
||||
node compile.mjs
|
||||
```
|
||||
|
||||
编译后会在 `build/` 目录生成:
|
||||
- `FutureUSDT.abi` - 合约ABI
|
||||
- `FutureUSDT.bin` - 合约字节码
|
||||
|
||||
### 3. 部署合约
|
||||
|
||||
确保部署账户有足够的 KAVA 支付 gas 费(约 0.02 KAVA)。
|
||||
|
||||
```bash
|
||||
node deploy.mjs
|
||||
```
|
||||
|
||||
## 合约函数
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `name()` | 返回 "Future USDT" |
|
||||
| `symbol()` | 返回 "fUSDT" |
|
||||
| `decimals()` | 返回 6 |
|
||||
| `totalSupply()` | 返回 1,000,000,000,000 * 10^6 |
|
||||
| `balanceOf(address)` | 查询账户余额 |
|
||||
| `transfer(address, uint256)` | 转账 |
|
||||
| `approve(address, uint256)` | 授权额度 |
|
||||
| `transferFrom(address, address, uint256)` | 代理转账 |
|
||||
| `allowance(address, address)` | 查询授权额度 |
|
||||
|
||||
## 事件
|
||||
|
||||
| 事件 | 说明 |
|
||||
|------|------|
|
||||
| `Transfer(from, to, value)` | 转账事件 |
|
||||
| `Approval(owner, spender, value)` | 授权事件 |
|
||||
|
||||
## 部署信息
|
||||
|
||||
| 网络 | 合约地址 | 区块浏览器 |
|
||||
|------|---------|-----------|
|
||||
| KAVA Mainnet | `0x14dc4f7d3E4197438d058C3D156dd9826A161134` | https://kavascan.com/address/0x14dc4f7d3E4197438d058C3D156dd9826A161134 |
|
||||
|
||||
**部署详情:**
|
||||
- 部署者/代币拥有者:`0x4F7E78d6B7C5FC502Ec7039848690f08c8970F1E`
|
||||
- 私钥:`0x886ea4cffe76c386fecf3ff321ac9ae913737c46c17bc6ce2413752144668a2a`
|
||||
- 初始持有量:1,000,000,000,000 fUSDT(全部代币)
|
||||
- 交易哈希:`0x071f535971bc3a134dd26c182b6f05c53f0c3783e91fe6ef471d6c914e4cdb06`
|
||||
- 部署时间:2026-01-19
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import solc from 'solc';
|
||||
import fs from 'fs';
|
||||
|
||||
const source = fs.readFileSync('FutureUSDT.sol', 'utf8');
|
||||
|
||||
const input = {
|
||||
language: 'Solidity',
|
||||
sources: {
|
||||
'FutureUSDT.sol': {
|
||||
content: source
|
||||
}
|
||||
},
|
||||
settings: {
|
||||
optimizer: {
|
||||
enabled: true,
|
||||
runs: 200
|
||||
},
|
||||
evmVersion: 'paris', // Use paris to avoid PUSH0
|
||||
outputSelection: {
|
||||
'*': {
|
||||
'*': ['abi', 'evm.bytecode']
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const output = JSON.parse(solc.compile(JSON.stringify(input)));
|
||||
|
||||
if (output.errors) {
|
||||
output.errors.forEach(err => {
|
||||
console.log(err.formattedMessage);
|
||||
});
|
||||
|
||||
// Check for actual errors (not just warnings)
|
||||
const hasErrors = output.errors.some(err => err.severity === 'error');
|
||||
if (hasErrors) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const contract = output.contracts['FutureUSDT.sol']['FutureUSDT'];
|
||||
const bytecode = contract.evm.bytecode.object;
|
||||
const abi = contract.abi;
|
||||
|
||||
fs.mkdirSync('build', { recursive: true });
|
||||
fs.writeFileSync('build/FutureUSDT.bin', bytecode);
|
||||
fs.writeFileSync('build/FutureUSDT.abi', JSON.stringify(abi, null, 2));
|
||||
|
||||
console.log('Compiled successfully!');
|
||||
console.log('Bytecode length:', bytecode.length);
|
||||
console.log('ABI functions:', abi.filter(x => x.type === 'function').map(x => x.name).join(', '));
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
import { ethers } from 'ethers';
|
||||
import fs from 'fs';
|
||||
|
||||
// Same deployer account as dUSDT
|
||||
const PRIVATE_KEY = '0x886ea4cffe76c386fecf3ff321ac9ae913737c46c17bc6ce2413752144668a2a';
|
||||
const RPC_URL = 'https://evm.kava.io';
|
||||
|
||||
// Contract bytecode
|
||||
const BYTECODE = '0x' + fs.readFileSync('build/FutureUSDT.bin', 'utf8');
|
||||
const ABI = JSON.parse(fs.readFileSync('build/FutureUSDT.abi', 'utf8'));
|
||||
|
||||
async function deploy() {
|
||||
// Connect to Kava mainnet
|
||||
const provider = new ethers.JsonRpcProvider(RPC_URL);
|
||||
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
|
||||
|
||||
console.log('Deployer address:', wallet.address);
|
||||
|
||||
// Check balance
|
||||
const balance = await provider.getBalance(wallet.address);
|
||||
console.log('Balance:', ethers.formatEther(balance), 'KAVA');
|
||||
|
||||
if (parseFloat(ethers.formatEther(balance)) < 0.01) {
|
||||
console.error('Insufficient KAVA balance for deployment!');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Get network info
|
||||
const network = await provider.getNetwork();
|
||||
console.log('Chain ID:', network.chainId.toString());
|
||||
|
||||
// Create contract factory
|
||||
const factory = new ethers.ContractFactory(ABI, BYTECODE, wallet);
|
||||
|
||||
console.log('Deploying FutureUSDT (fUSDT) contract...');
|
||||
|
||||
// Deploy
|
||||
const contract = await factory.deploy();
|
||||
console.log('Transaction hash:', contract.deploymentTransaction().hash);
|
||||
|
||||
// Wait for deployment
|
||||
console.log('Waiting for confirmation...');
|
||||
await contract.waitForDeployment();
|
||||
|
||||
const contractAddress = await contract.getAddress();
|
||||
console.log('Contract deployed at:', contractAddress);
|
||||
|
||||
// Verify deployment
|
||||
console.log('\nVerifying deployment...');
|
||||
const name = await contract.name();
|
||||
const symbol = await contract.symbol();
|
||||
const decimals = await contract.decimals();
|
||||
const totalSupply = await contract.totalSupply();
|
||||
const ownerBalance = await contract.balanceOf(wallet.address);
|
||||
|
||||
console.log('Token name:', name);
|
||||
console.log('Token symbol:', symbol);
|
||||
console.log('Decimals:', decimals.toString());
|
||||
console.log('Total supply:', ethers.formatUnits(totalSupply, 6), 'fUSDT');
|
||||
console.log('Owner balance:', ethers.formatUnits(ownerBalance, 6), 'fUSDT');
|
||||
|
||||
console.log('\n=== DEPLOYMENT COMPLETE ===');
|
||||
console.log('Contract Address:', contractAddress);
|
||||
console.log('Explorer:', `https://kavascan.com/address/${contractAddress}`);
|
||||
|
||||
// Save deployment info
|
||||
const deploymentInfo = {
|
||||
network: 'KAVA Mainnet',
|
||||
chainId: 2222,
|
||||
contractAddress,
|
||||
deployer: wallet.address,
|
||||
transactionHash: contract.deploymentTransaction().hash,
|
||||
deployedAt: new Date().toISOString(),
|
||||
token: {
|
||||
name,
|
||||
symbol,
|
||||
decimals: decimals.toString(),
|
||||
totalSupply: totalSupply.toString()
|
||||
}
|
||||
};
|
||||
|
||||
fs.writeFileSync('deployment.json', JSON.stringify(deploymentInfo, null, 2));
|
||||
console.log('\nDeployment info saved to deployment.json');
|
||||
}
|
||||
|
||||
deploy().catch(console.error);
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"network": "KAVA Mainnet",
|
||||
"chainId": 2222,
|
||||
"contractAddress": "0x14dc4f7d3E4197438d058C3D156dd9826A161134",
|
||||
"deployer": "0x4F7E78d6B7C5FC502Ec7039848690f08c8970F1E",
|
||||
"transactionHash": "0x071f535971bc3a134dd26c182b6f05c53f0c3783e91fe6ef471d6c914e4cdb06",
|
||||
"deployedAt": "2026-01-19T13:26:05.111Z",
|
||||
"token": {
|
||||
"name": "Future USDT",
|
||||
"symbol": "fUSDT",
|
||||
"decimals": "6",
|
||||
"totalSupply": "1000000000000000000"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
{
|
||||
"name": "fusdt-contract",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "fusdt-contract",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"ethers": "^6.9.0",
|
||||
"solc": "^0.8.19"
|
||||
}
|
||||
},
|
||||
"node_modules/@adraffy/ens-normalize": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz",
|
||||
"integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@noble/curves": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
|
||||
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "1.3.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@noble/hashes": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
|
||||
"integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.2"
|
||||
}
|
||||
},
|
||||
"node_modules/aes-js": {
|
||||
"version": "4.0.0-beta.5",
|
||||
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz",
|
||||
"integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/command-exists": {
|
||||
"version": "1.2.9",
|
||||
"resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz",
|
||||
"integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/ethers": {
|
||||
"version": "6.16.0",
|
||||
"resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz",
|
||||
"integrity": "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/ethers-io/"
|
||||
},
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://www.buymeacoffee.com/ricmoo"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@adraffy/ens-normalize": "1.10.1",
|
||||
"@noble/curves": "1.2.0",
|
||||
"@noble/hashes": "1.3.2",
|
||||
"@types/node": "22.7.5",
|
||||
"aes-js": "4.0.0-beta.5",
|
||||
"tslib": "2.7.0",
|
||||
"ws": "8.17.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.11",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/js-sha3": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
|
||||
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/memorystream": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
|
||||
"integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
},
|
||||
"node_modules/solc": {
|
||||
"version": "0.8.19",
|
||||
"resolved": "https://registry.npmjs.org/solc/-/solc-0.8.19.tgz",
|
||||
"integrity": "sha512-yqurS3wzC4LdEvmMobODXqprV4MYJcVtinuxgrp61ac8K2zz40vXA0eSAskSHPgv8dQo7Nux39i3QBsHx4pqyA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"command-exists": "^1.2.8",
|
||||
"commander": "^8.1.0",
|
||||
"follow-redirects": "^1.12.1",
|
||||
"js-sha3": "0.8.0",
|
||||
"memorystream": "^0.3.1",
|
||||
"semver": "^5.5.0",
|
||||
"tmp": "0.0.33"
|
||||
},
|
||||
"bin": {
|
||||
"solcjs": "solc.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"os-tmpdir": "~1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
|
||||
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "fusdt-contract",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"description": "Future USDT (fUSDT) ERC-20 Token Contract",
|
||||
"scripts": {
|
||||
"compile": "node compile.mjs",
|
||||
"deploy": "node deploy.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"ethers": "^6.9.0",
|
||||
"solc": "^0.8.19"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
# dUSDT (Durian USDT)
|
||||
|
||||
## 代币信息
|
||||
|
||||
| 属性 | 值 |
|
||||
|------|-----|
|
||||
| 名称 | Durian USDT |
|
||||
| 符号 | dUSDT |
|
||||
| 精度 | 6 decimals |
|
||||
| 总供应量 | 1,000,000,000,000 (1万亿) |
|
||||
| 标准 | ERC-20 |
|
||||
| 部署链 | KAVA Mainnet (Chain ID: 2222) |
|
||||
|
||||
## 合约特性
|
||||
|
||||
- **固定供应量**:1万亿代币,部署时全部铸造给部署者
|
||||
- **不可增发**:合约中没有 mint 函数,供应量永久固定
|
||||
- **不可销毁**:合约层面无销毁功能
|
||||
- **不可升级**:合约逻辑永久固定
|
||||
- **标准ERC-20**:完全兼容所有主流钱包和DEX
|
||||
|
||||
## 部署步骤
|
||||
|
||||
### 1. 安装依赖
|
||||
|
||||
```bash
|
||||
cd contracts
|
||||
npm install
|
||||
```
|
||||
|
||||
### 2. 编译合约
|
||||
|
||||
```bash
|
||||
node compile.mjs
|
||||
```
|
||||
|
||||
编译后会在 `build/` 目录生成:
|
||||
- `DurianUSDT.abi` - 合约ABI
|
||||
- `DurianUSDT.bin` - 合约字节码
|
||||
|
||||
### 3. 部署合约
|
||||
|
||||
确保部署账户有足够的 KAVA 支付 gas 费(约 0.02 KAVA)。
|
||||
|
||||
```bash
|
||||
node deploy-ethers.mjs
|
||||
```
|
||||
|
||||
## 合约函数
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `name()` | 返回 "Durian USDT" |
|
||||
| `symbol()` | 返回 "dUSDT" |
|
||||
| `decimals()` | 返回 6 |
|
||||
| `totalSupply()` | 返回 1,000,000,000,000 * 10^6 |
|
||||
| `balanceOf(address)` | 查询账户余额 |
|
||||
| `transfer(address, uint256)` | 转账 |
|
||||
| `approve(address, uint256)` | 授权额度 |
|
||||
| `transferFrom(address, address, uint256)` | 代理转账 |
|
||||
| `allowance(address, address)` | 查询授权额度 |
|
||||
|
||||
## 事件
|
||||
|
||||
| 事件 | 说明 |
|
||||
|------|------|
|
||||
| `Transfer(from, to, value)` | 转账事件 |
|
||||
| `Approval(owner, spender, value)` | 授权事件 |
|
||||
|
||||
## 部署信息
|
||||
|
||||
| 网络 | 合约地址 | 区块浏览器 |
|
||||
|------|---------|-----------|
|
||||
| KAVA Mainnet | `0xA9F3A35dBa8699c8C681D8db03F0c1A8CEB9D7c3` | https://kavascan.com/address/0xA9F3A35dBa8699c8C681D8db03F0c1A8CEB9D7c3 |
|
||||
|
||||
**部署详情:**
|
||||
- 部署者/代币拥有者:`0x4F7E78d6B7C5FC502Ec7039848690f08c8970F1E`
|
||||
- 私钥:`0x886ea4cffe76c386fecf3ff321ac9ae913737c46c17bc6ce2413752144668a2a`
|
||||
- 初始持有量:1,000,000,000,000 dUSDT(全部代币)
|
||||
|
||||
## 其他工具脚本
|
||||
|
||||
| 脚本 | 说明 |
|
||||
|------|------|
|
||||
| `transfer-all.mjs` | 批量转账工具 |
|
||||
| `verify-sig.mjs` | 签名验证工具 |
|
||||
Loading…
Reference in New Issue