qvtx-developer-kit 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +108 -0
- package/README.md +0 -0
- package/abis/QVTXBridge.json +273 -0
- package/abis/QVTXDirectPurchase.json +621 -0
- package/abis/QVTXGovernance.json +267 -0
- package/abis/QVTXNFT.json +370 -0
- package/abis/QVTXRewards.json +155 -0
- package/abis/QVTXToken.json +311 -0
- package/abis/QVTXVesting.json +216 -0
- package/abis/index.js +16 -0
- package/bin/qvtx-developer-cli.js +99 -0
- package/config/index.js +108 -0
- package/config/networks.js +247 -0
- package/examples/basic-usage.js +39 -0
- package/examples/bridge-example.js +123 -0
- package/examples/direct-purchase.js +300 -0
- package/examples/governance-example.js +140 -0
- package/examples/nft-example.js +141 -0
- package/examples/staking-example.js +96 -0
- package/index.js +145 -0
- package/languages/blockchain_ai_sdk.js +0 -0
- package/languages/node_sdk.js +0 -0
- package/languages/solana_sdk.js +383 -0
- package/package.json +30 -3
- package/purchase/index.js +567 -0
- package/rewards/index.js +71 -0
- package/smart-contracts/QVTXBridge.sol +305 -0
- package/smart-contracts/QVTXDirectPurchase.sol +543 -0
- package/smart-contracts/QVTXGovernance.sol +325 -0
- package/smart-contracts/QVTXNFT.sol +338 -0
- package/smart-contracts/QVTXRewards.sol +102 -0
- package/smart-contracts/QVTXToken.sol +227 -0
- package/smart-contracts/QVTXVesting.sol +411 -0
- package/smart-contracts/interfaces/IERC20.sol +14 -0
- package/smart-contracts/interfaces/IERC20Metadata.sol +8 -0
- package/smart-contracts/interfaces/IERC721.sol +18 -0
- package/smart-contracts/interfaces/IERC721Metadata.sol +8 -0
- package/smart-contracts/interfaces/IERC721Receiver.sol +11 -0
- package/storage/index.js +112 -0
- package/templates/contract/ERC20Token.sol +116 -0
- package/templates/dapp/index.html +93 -0
- package/test/index.js +182 -0
- package/tools/build-tool.js +63 -0
- package/tools/create-template.js +116 -0
- package/tools/deploy-tool.js +55 -0
- package/tools/generate-docs.js +149 -0
- package/tools/init-project.js +138 -0
- package/tools/run-tests.js +64 -0
- package/types/index.d.ts +386 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.19;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @title QVTX Bridge
|
|
6
|
+
* @dev Cross-chain bridge for QVTX token transfers
|
|
7
|
+
* @author QuantVestrix Tech Team (07-Tech)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface IQVTXToken {
|
|
11
|
+
function bridgeMint(address to, uint256 amount, uint256 sourceChain) external;
|
|
12
|
+
function bridgeBurn(address from, uint256 amount, uint256 targetChain) external;
|
|
13
|
+
function balanceOf(address account) external view returns (uint256);
|
|
14
|
+
function transferFrom(address from, address to, uint256 amount) external returns (bool);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
contract QVTXBridge {
|
|
18
|
+
// Bridge configuration
|
|
19
|
+
IQVTXToken public qvtxToken;
|
|
20
|
+
address public owner;
|
|
21
|
+
address public validator;
|
|
22
|
+
|
|
23
|
+
uint256 public currentChainId;
|
|
24
|
+
uint256 public nonce;
|
|
25
|
+
uint256 public bridgeFee = 0.001 ether; // Fee for bridging
|
|
26
|
+
uint256 public minBridgeAmount = 100 * 10**18; // Minimum 100 QVTX
|
|
27
|
+
uint256 public maxBridgeAmount = 10_000_000 * 10**18; // Maximum 10M QVTX
|
|
28
|
+
|
|
29
|
+
bool public paused;
|
|
30
|
+
|
|
31
|
+
// Supported chains
|
|
32
|
+
mapping(uint256 => bool) public supportedChains;
|
|
33
|
+
mapping(uint256 => address) public chainBridges; // chainId => bridge contract on that chain
|
|
34
|
+
|
|
35
|
+
// Bridge requests
|
|
36
|
+
struct BridgeRequest {
|
|
37
|
+
uint256 id;
|
|
38
|
+
address sender;
|
|
39
|
+
address recipient;
|
|
40
|
+
uint256 amount;
|
|
41
|
+
uint256 sourceChain;
|
|
42
|
+
uint256 targetChain;
|
|
43
|
+
uint256 timestamp;
|
|
44
|
+
bytes32 txHash;
|
|
45
|
+
BridgeStatus status;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
enum BridgeStatus {
|
|
49
|
+
Pending,
|
|
50
|
+
Completed,
|
|
51
|
+
Refunded,
|
|
52
|
+
Failed
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
mapping(uint256 => BridgeRequest) public bridgeRequests;
|
|
56
|
+
mapping(bytes32 => bool) public processedHashes;
|
|
57
|
+
mapping(address => uint256[]) public userBridgeRequests;
|
|
58
|
+
|
|
59
|
+
// Daily limits
|
|
60
|
+
mapping(uint256 => uint256) public dailyVolume; // day => volume
|
|
61
|
+
uint256 public dailyLimit = 100_000_000 * 10**18; // 100M QVTX daily
|
|
62
|
+
|
|
63
|
+
// Events
|
|
64
|
+
event BridgeInitiated(
|
|
65
|
+
uint256 indexed requestId,
|
|
66
|
+
address indexed sender,
|
|
67
|
+
address indexed recipient,
|
|
68
|
+
uint256 amount,
|
|
69
|
+
uint256 sourceChain,
|
|
70
|
+
uint256 targetChain
|
|
71
|
+
);
|
|
72
|
+
event BridgeCompleted(
|
|
73
|
+
uint256 indexed requestId,
|
|
74
|
+
address indexed recipient,
|
|
75
|
+
uint256 amount,
|
|
76
|
+
uint256 sourceChain,
|
|
77
|
+
bytes32 sourceTxHash
|
|
78
|
+
);
|
|
79
|
+
event BridgeRefunded(uint256 indexed requestId, address indexed sender, uint256 amount);
|
|
80
|
+
event ChainAdded(uint256 indexed chainId, address bridgeContract);
|
|
81
|
+
event ChainRemoved(uint256 indexed chainId);
|
|
82
|
+
event ValidatorUpdated(address indexed newValidator);
|
|
83
|
+
event FeesWithdrawn(address indexed to, uint256 amount);
|
|
84
|
+
event Paused(bool status);
|
|
85
|
+
|
|
86
|
+
modifier onlyOwner() {
|
|
87
|
+
require(msg.sender == owner, "Bridge: not owner");
|
|
88
|
+
_;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
modifier onlyValidator() {
|
|
92
|
+
require(msg.sender == validator || msg.sender == owner, "Bridge: not validator");
|
|
93
|
+
_;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
modifier whenNotPaused() {
|
|
97
|
+
require(!paused, "Bridge: paused");
|
|
98
|
+
_;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
constructor(address _qvtxToken, uint256 _chainId) {
|
|
102
|
+
qvtxToken = IQVTXToken(_qvtxToken);
|
|
103
|
+
currentChainId = _chainId;
|
|
104
|
+
owner = msg.sender;
|
|
105
|
+
validator = msg.sender;
|
|
106
|
+
|
|
107
|
+
// Add default supported chains
|
|
108
|
+
_addChain(1, address(0)); // Ethereum
|
|
109
|
+
_addChain(56, address(0)); // BSC
|
|
110
|
+
_addChain(137, address(0)); // Polygon
|
|
111
|
+
_addChain(42161, address(0)); // Arbitrum
|
|
112
|
+
_addChain(43114, address(0)); // Avalanche
|
|
113
|
+
_addChain(10, address(0)); // Optimism
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Initiate bridge transfer
|
|
117
|
+
function bridge(
|
|
118
|
+
address recipient,
|
|
119
|
+
uint256 amount,
|
|
120
|
+
uint256 targetChain
|
|
121
|
+
) external payable whenNotPaused returns (uint256) {
|
|
122
|
+
require(supportedChains[targetChain], "Bridge: unsupported chain");
|
|
123
|
+
require(targetChain != currentChainId, "Bridge: same chain");
|
|
124
|
+
require(amount >= minBridgeAmount, "Bridge: below minimum");
|
|
125
|
+
require(amount <= maxBridgeAmount, "Bridge: exceeds maximum");
|
|
126
|
+
require(msg.value >= bridgeFee, "Bridge: insufficient fee");
|
|
127
|
+
require(recipient != address(0), "Bridge: zero recipient");
|
|
128
|
+
|
|
129
|
+
// Check daily limit
|
|
130
|
+
uint256 today = block.timestamp / 1 days;
|
|
131
|
+
require(dailyVolume[today] + amount <= dailyLimit, "Bridge: daily limit exceeded");
|
|
132
|
+
dailyVolume[today] += amount;
|
|
133
|
+
|
|
134
|
+
// Lock/burn tokens
|
|
135
|
+
qvtxToken.bridgeBurn(msg.sender, amount, targetChain);
|
|
136
|
+
|
|
137
|
+
// Create bridge request
|
|
138
|
+
nonce++;
|
|
139
|
+
uint256 requestId = nonce;
|
|
140
|
+
|
|
141
|
+
bridgeRequests[requestId] = BridgeRequest({
|
|
142
|
+
id: requestId,
|
|
143
|
+
sender: msg.sender,
|
|
144
|
+
recipient: recipient,
|
|
145
|
+
amount: amount,
|
|
146
|
+
sourceChain: currentChainId,
|
|
147
|
+
targetChain: targetChain,
|
|
148
|
+
timestamp: block.timestamp,
|
|
149
|
+
txHash: bytes32(0),
|
|
150
|
+
status: BridgeStatus.Pending
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
userBridgeRequests[msg.sender].push(requestId);
|
|
154
|
+
|
|
155
|
+
emit BridgeInitiated(requestId, msg.sender, recipient, amount, currentChainId, targetChain);
|
|
156
|
+
|
|
157
|
+
// Refund excess fee
|
|
158
|
+
if (msg.value > bridgeFee) {
|
|
159
|
+
payable(msg.sender).transfer(msg.value - bridgeFee);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return requestId;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Complete bridge (called by validator on destination chain)
|
|
166
|
+
function completeBridge(
|
|
167
|
+
address recipient,
|
|
168
|
+
uint256 amount,
|
|
169
|
+
uint256 sourceChain,
|
|
170
|
+
bytes32 sourceTxHash,
|
|
171
|
+
bytes calldata signature
|
|
172
|
+
) external onlyValidator whenNotPaused {
|
|
173
|
+
require(!processedHashes[sourceTxHash], "Bridge: already processed");
|
|
174
|
+
require(supportedChains[sourceChain], "Bridge: unsupported source chain");
|
|
175
|
+
|
|
176
|
+
// Verify signature
|
|
177
|
+
bytes32 messageHash = keccak256(abi.encodePacked(
|
|
178
|
+
recipient,
|
|
179
|
+
amount,
|
|
180
|
+
sourceChain,
|
|
181
|
+
currentChainId,
|
|
182
|
+
sourceTxHash
|
|
183
|
+
));
|
|
184
|
+
require(_verifySignature(messageHash, signature), "Bridge: invalid signature");
|
|
185
|
+
|
|
186
|
+
processedHashes[sourceTxHash] = true;
|
|
187
|
+
|
|
188
|
+
// Mint tokens to recipient
|
|
189
|
+
qvtxToken.bridgeMint(recipient, amount, sourceChain);
|
|
190
|
+
|
|
191
|
+
// Create completion record
|
|
192
|
+
nonce++;
|
|
193
|
+
bridgeRequests[nonce] = BridgeRequest({
|
|
194
|
+
id: nonce,
|
|
195
|
+
sender: address(0),
|
|
196
|
+
recipient: recipient,
|
|
197
|
+
amount: amount,
|
|
198
|
+
sourceChain: sourceChain,
|
|
199
|
+
targetChain: currentChainId,
|
|
200
|
+
timestamp: block.timestamp,
|
|
201
|
+
txHash: sourceTxHash,
|
|
202
|
+
status: BridgeStatus.Completed
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
emit BridgeCompleted(nonce, recipient, amount, sourceChain, sourceTxHash);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Refund failed bridge
|
|
209
|
+
function refund(uint256 requestId) external onlyValidator {
|
|
210
|
+
BridgeRequest storage request = bridgeRequests[requestId];
|
|
211
|
+
require(request.status == BridgeStatus.Pending, "Bridge: not pending");
|
|
212
|
+
require(request.sourceChain == currentChainId, "Bridge: wrong chain");
|
|
213
|
+
|
|
214
|
+
request.status = BridgeStatus.Refunded;
|
|
215
|
+
|
|
216
|
+
// Mint back to sender
|
|
217
|
+
qvtxToken.bridgeMint(request.sender, request.amount, currentChainId);
|
|
218
|
+
|
|
219
|
+
emit BridgeRefunded(requestId, request.sender, request.amount);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Verify validator signature
|
|
223
|
+
function _verifySignature(bytes32 messageHash, bytes calldata signature) internal view returns (bool) {
|
|
224
|
+
bytes32 ethSignedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", messageHash));
|
|
225
|
+
(bytes32 r, bytes32 s, uint8 v) = _splitSignature(signature);
|
|
226
|
+
address signer = ecrecover(ethSignedHash, v, r, s);
|
|
227
|
+
return signer == validator;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function _splitSignature(bytes calldata sig) internal pure returns (bytes32 r, bytes32 s, uint8 v) {
|
|
231
|
+
require(sig.length == 65, "Bridge: invalid signature length");
|
|
232
|
+
assembly {
|
|
233
|
+
r := calldataload(sig.offset)
|
|
234
|
+
s := calldataload(add(sig.offset, 32))
|
|
235
|
+
v := byte(0, calldataload(add(sig.offset, 64)))
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Get user bridge history
|
|
240
|
+
function getUserBridgeRequests(address user) external view returns (uint256[] memory) {
|
|
241
|
+
return userBridgeRequests[user];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Get bridge request details
|
|
245
|
+
function getBridgeRequest(uint256 requestId) external view returns (BridgeRequest memory) {
|
|
246
|
+
return bridgeRequests[requestId];
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Check if chain is supported
|
|
250
|
+
function isChainSupported(uint256 chainId) external view returns (bool) {
|
|
251
|
+
return supportedChains[chainId];
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Admin functions
|
|
255
|
+
function addChain(uint256 chainId, address bridgeContract) external onlyOwner {
|
|
256
|
+
_addChain(chainId, bridgeContract);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function _addChain(uint256 chainId, address bridgeContract) internal {
|
|
260
|
+
supportedChains[chainId] = true;
|
|
261
|
+
chainBridges[chainId] = bridgeContract;
|
|
262
|
+
emit ChainAdded(chainId, bridgeContract);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function removeChain(uint256 chainId) external onlyOwner {
|
|
266
|
+
supportedChains[chainId] = false;
|
|
267
|
+
chainBridges[chainId] = address(0);
|
|
268
|
+
emit ChainRemoved(chainId);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function setValidator(address _validator) external onlyOwner {
|
|
272
|
+
require(_validator != address(0), "Bridge: zero address");
|
|
273
|
+
validator = _validator;
|
|
274
|
+
emit ValidatorUpdated(_validator);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function setBridgeFee(uint256 _fee) external onlyOwner {
|
|
278
|
+
bridgeFee = _fee;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function setLimits(uint256 _min, uint256 _max, uint256 _daily) external onlyOwner {
|
|
282
|
+
minBridgeAmount = _min;
|
|
283
|
+
maxBridgeAmount = _max;
|
|
284
|
+
dailyLimit = _daily;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function setPaused(bool _paused) external onlyOwner {
|
|
288
|
+
paused = _paused;
|
|
289
|
+
emit Paused(_paused);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function withdrawFees(address payable to) external onlyOwner {
|
|
293
|
+
uint256 balance = address(this).balance;
|
|
294
|
+
require(balance > 0, "Bridge: no fees");
|
|
295
|
+
to.transfer(balance);
|
|
296
|
+
emit FeesWithdrawn(to, balance);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function transferOwnership(address newOwner) external onlyOwner {
|
|
300
|
+
require(newOwner != address(0), "Bridge: zero address");
|
|
301
|
+
owner = newOwner;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
receive() external payable {}
|
|
305
|
+
}
|