Commit fb799d56 authored by vicotor's avatar vicotor

update contract

parent 82f35570
...@@ -74,6 +74,9 @@ contract Bridge is Ownable { ...@@ -74,6 +74,9 @@ contract Bridge is Ownable {
/// @dev 金库地址 /// @dev 金库地址
address public treasury; address public treasury;
/// @dev 手续费接收地址
address public feeReceiver;
/** /**
* @dev 代币金库配置结构体 * @dev 代币金库配置结构体
* @param minReserve 最小保留金额(合约必须保留的最少数量) * @param minReserve 最小保留金额(合约必须保留的最少数量)
...@@ -234,6 +237,9 @@ contract Bridge is Ownable { ...@@ -234,6 +237,9 @@ contract Bridge is Ownable {
/// @dev 金库地址变更事件 /// @dev 金库地址变更事件
event TreasuryChanged(address indexed oldTreasury, address indexed newTreasury); event TreasuryChanged(address indexed oldTreasury, address indexed newTreasury);
/// @dev feeRecevier地址变更事件
event FeeReceiverChanged(address indexed oldReceiver, address indexed newReceiver);
/// @dev 金库配置变更事件 /// @dev 金库配置变更事件
event TreasuryConfigChanged(address indexed token, uint256 minReserve, uint256 reserveRatio, bool enabled); event TreasuryConfigChanged(address indexed token, uint256 minReserve, uint256 reserveRatio, bool enabled);
...@@ -388,6 +394,13 @@ contract Bridge is Ownable { ...@@ -388,6 +394,13 @@ contract Bridge is Ownable {
emit TreasuryChanged(oldTreasury, newTreasury); emit TreasuryChanged(oldTreasury, newTreasury);
} }
function setFeeReceiver(address newReceiver) external onlyOwner {
require(newReceiver != address(0), "treasury cannot be zero address");
address oldReceiver = feeReceiver;
feeReceiver = newReceiver;
emit FeeReceiverChanged(oldReceiver, newReceiver);
}
/** /**
* @dev 设置代币的金库配置 * @dev 设置代币的金库配置
* @param token 代币地址 * @param token 代币地址
...@@ -598,6 +611,7 @@ contract Bridge is Ownable { ...@@ -598,6 +611,7 @@ contract Bridge is Ownable {
// 验证签名 // 验证签名
bytes32 _signature = keccak256(abi.encode(params.outId, params.fromChainID, params.sender, params.sendToken, params.sendAmount, params.toChainID, params.receiver, params.token)); bytes32 _signature = keccak256(abi.encode(params.outId, params.fromChainID, params.sender, params.sendToken, params.sendAmount, params.toChainID, params.receiver, params.token));
require(params.signature == _signature, "signature not equal"); require(params.signature == _signature, "signature not equal");
require(params.sendAmount >= params.amount, "invalid amounts");
// 检查是否已存在对应的转入记录 // 检查是否已存在对应的转入记录
uint256 inId = getInId[params.fromChainID][params.outId]; uint256 inId = getInId[params.fromChainID][params.outId];
...@@ -607,6 +621,7 @@ contract Bridge is Ownable { ...@@ -607,6 +621,7 @@ contract Bridge is Ownable {
inId = _inID; inId = _inID;
InInfo storage info = inTransfers[inId]; InInfo storage info = inTransfers[inId];
info.inId = inId; info.inId = inId;
info.fee = params.sendAmount - params.amount;
info.token = params.token; info.token = params.token;
info.receiver = params.receiver; info.receiver = params.receiver;
info.amount = params.amount; info.amount = params.amount;
...@@ -635,6 +650,7 @@ contract Bridge is Ownable { ...@@ -635,6 +650,7 @@ contract Bridge is Ownable {
* @notice 验证者可以单独确认已提交的转入操作 * @notice 验证者可以单独确认已提交的转入操作
*/ */
function confirmInTransfer(uint256 inId) public onlyValidator { function confirmInTransfer(uint256 inId) public onlyValidator {
require(inTransfers[inId].token != address(0), "inId not exist");
_confirm(inId); _confirm(inId);
} }
...@@ -695,6 +711,11 @@ contract Bridge is Ownable { ...@@ -695,6 +711,11 @@ contract Bridge is Ownable {
// 执行代币转账 // 执行代币转账
require(IERC20(token).transfer(receiver, amount), "transfer err"); require(IERC20(token).transfer(receiver, amount), "transfer err");
// 转移手续费
if (inTransfers[inId].fee > 0 && feeReceiver != address(0)) {
require(IERC20(token).transfer(feeReceiver, inTransfers[inId].fee), "fee transfer err");
}
// 更新转入总量 // 更新转入总量
inTotal[token] = inTotal[token] + amount; inTotal[token] = inTotal[token] + amount;
......
...@@ -47,6 +47,8 @@ module.exports = { ...@@ -47,6 +47,8 @@ module.exports = {
etherscan: { etherscan: {
apiKey: { apiKey: {
'achain': 'empty', 'achain': 'empty',
'movadev': 'empty',
'hole': 'empty',
'mova': 'empty', 'mova': 'empty',
'bsc':'AVZIFYCHUFHPG9FDKNMHEWJ1VAW1H5U66T' 'bsc':'AVZIFYCHUFHPG9FDKNMHEWJ1VAW1H5U66T'
}, },
...@@ -59,6 +61,22 @@ module.exports = { ...@@ -59,6 +61,22 @@ module.exports = {
browserURL: "https://scan.cmp20.bitheart.org" browserURL: "https://scan.cmp20.bitheart.org"
} }
}, },
{
network: "hole",
chainId: 6174,
urls: {
apiURL: "https://holescan.bitheart.org/api",
browserURL: "https://holescan.bitheart.org"
}
},
{
network: "movadev",
chainId: 8891,
urls: {
apiURL: "https://scan.mova.bitheart.org/api",
browserURL: "https://scan.mova.bitheart.org"
}
},
{ {
network: "mova", network: "mova",
chainId: 10323, chainId: 10323,
...@@ -84,12 +102,17 @@ module.exports = { ...@@ -84,12 +102,17 @@ module.exports = {
url: "https://mars.rpc.movachain.com", url: "https://mars.rpc.movachain.com",
accounts: privateKeys accounts: privateKeys
}, },
bit: { movadev: {
url: "https://rpc.mova.bitheart.org", url: "https://rpc.mova.bitheart.org",
accounts: privateKeys accounts: privateKeys
}, },
hpb: { hole: {
url: "https://hpbnode.com", url: "https://rpc.hole.bitheart.org",
accounts: privateKeys
},
bsctest: {
// url: "https://bsctest.bitheart.org",
url: "https://bsc-testnet.bnbchain.org",
accounts: privateKeys accounts: privateKeys
} }
} }
......
{ {
"269": { "97": {
"tokenA": "0xF5c10392D841d55C41EBf696A4E437b2DC91f5D3", "tokenA": "0x802Debb02aF95A1e68c7b2586883c77D65E4De01",
"tokenB": "0x6A24C27cF83dAFf6227fa03852465aA65cF22527", "tokenB": "0x6DC00bD82F04890D7aB68cedcA588818760Ad509",
"bridge": "0x9a06d0CfAFc19a4bfe0ecd5f8bC20A26a88fA227" "bridge": "0x5fcEa08A3E2F0Eb96424925dA9a951388b7EC764"
},
"6174": {
"tokenA": "0x25cAa6D61D1b9589D827A29b2c4e9dA0a85080B6",
"tokenB": "0xa77285d7BB3655C98E2f71D21f16e3aa511082c7",
"bridge": "0xC91b0E98572b06a45a456715268Dd17b4b85D7fc"
},
"8891": {
"tokenA": "0x29Ec4977338704e2665020c1FA91187B5d40bfcc",
"tokenB": "0xDe6Fea12B657128331bbB909400793A66EC5828B",
"bridge": "0xa33DD581A5e287535D955bC9961bEC9Af6E39db7"
}, },
"10323": { "10323": {
"tokenA": "0xF5c10392D841d55C41EBf696A4E437b2DC91f5D3", "tokenA": "0x2e97f146364Bf2436414aFC68716e712657Bb929",
"tokenB": "0x6A24C27cF83dAFf6227fa03852465aA65cF22527", "tokenB": "0x15E124E34B24FC6f1608E6ECB3f228826f550C04",
"bridge": "0x9a06d0CfAFc19a4bfe0ecd5f8bC20A26a88fA227" "bridge": "0x802Debb02aF95A1e68c7b2586883c77D65E4De01"
} }
} }
\ No newline at end of file
{
"6174": {
"tokenA": "0x9F225b7BCC4697414D4F6aC1CB985D07d34dAe0a",
"tokenB": "0xA989C4a3ADb9fb1860aFB18543E23F0717c68298",
"bridge": "0xceEC8799139C698De532e363DA7395E25F409775"
},
"8891": {
"tokenA": "0x6Fd62C3a41B46162919B6A7Be1455f511Ed7a9Cf",
"tokenB": "0x2D578F646e0334F3CBA9B17D00c7357372a63FEa",
"bridge": "0xA2d532F956770611647EcBab19d87d380145d0Cf"
}
}
\ No newline at end of file
const fs = require("fs");
const path = require("path");
const hre = require("hardhat");
let INITIAL_VALIDATORS = process.env.BRIDGE_VALIDATORS
let TREASURY = process.env.TREASURY
const DEPLOY_FILE = path.join(__dirname, "deploy.json");
async function getOutConfig(bridge, token , targetchain) {
const config = await bridge.outConfiguration(token, targetchain)
console.log("OutConfig for token:", token, " to chain:", targetchain, " config:", config)
}
async function getDeploy(chainId) {
if (!fs.existsSync(DEPLOY_FILE)) {
throw new Error("deploy.json file not found");
}
const deployData = JSON.parse(fs.readFileSync(DEPLOY_FILE, "utf8"));
if (!deployData[chainId]) {
throw new Error(`No deployment data found for chainId ${chainId}`);
}
const addrs = deployData[chainId];
const tokenA = await hre.ethers.getContractAt("TestToken", addrs.tokenA);
const tokenB = await hre.ethers.getContractAt("TestToken", addrs.tokenB);
const bridge = await hre.ethers.getContractAt("Bridge", addrs.bridge);
return {tokenA, tokenB, bridge}
}
// Define the script
async function main() {
const chainId = await hre.ethers.provider.getNetwork().then(network => network.chainId);
const targetChainId = chainId === 6174n ? 8891 : 6174;
console.log("Current chain ID:", chainId, "Target chain ID:", targetChainId);
const curChainDeploy = await getDeploy(chainId);
await getOutConfig(curChainDeploy.bridge, await curChainDeploy.tokenA.getAddress(), targetChainId);
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const fs = require("fs");
const path = require("path");
const hre = require("hardhat");
var users = [
"0xCb7559B648eE663A2B0C569837F510D5f0ABAaD1"
]
const DEPLOY_FILE = path.join(__dirname, "deploy.json");
async function mintToken(tokenA, tokenB, user) {
var amount = hre.ethers.parseEther("1000")
var tx = await tokenA.mint(user, amount);
await tx.wait();
console.log("Minted TTA to user:", user, " amount:", hre.ethers.formatEther(amount));
tx = await tokenB.mint(user, amount);
await tx.wait();
console.log("Minted TTB to user:", user, " amount:", hre.ethers.formatEther(amount));
}
async function getDeploy(chainId) {
if (!fs.existsSync(DEPLOY_FILE)) {
throw new Error("deploy.json file not found");
}
const deployData = JSON.parse(fs.readFileSync(DEPLOY_FILE, "utf8"));
if (!deployData[chainId]) {
throw new Error(`No deployment data found for chainId ${chainId}`);
}
const addrs = deployData[chainId];
const tokenA = await hre.ethers.getContractAt("TestToken", addrs.tokenA);
const tokenB = await hre.ethers.getContractAt("TestToken", addrs.tokenB);
const bridge = await hre.ethers.getContractAt("Bridge", addrs.bridge);
return {tokenA, tokenB, bridge}
}
// Define the script
async function main() {
const chainId = await hre.ethers.provider.getNetwork().then(network => network.chainId);
const targetChainId = chainId === 6174n ? 8891 : 6174;
console.log("Current chain ID:", chainId, "Target chain ID:", targetChainId);
const curChainDeploy = await getDeploy(chainId);
for (var i = 0; i < users.length; i++) {
await mintToken(curChainDeploy.tokenA, curChainDeploy.tokenB, users[i]);
}
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
...@@ -16,12 +16,24 @@ async function addValidators(contract, validators) { ...@@ -16,12 +16,24 @@ async function addValidators(contract, validators) {
} }
} }
async function setValidatorRequired(contract, count) {
var tx = await contract.changeValidRequired(count);
await tx.wait();
console.log("Set validator required to:", count);
}
async function setTreasury(contract, treasury) { async function setTreasury(contract, treasury) {
var tx = await contract.setTreasury(treasury); var tx = await contract.setTreasury(treasury);
await tx.wait(); await tx.wait();
console.log("Set treasury to:", treasury); console.log("Set treasury to:", treasury);
} }
async function setFeeReceiver(contract, receiver) {
var tx = await contract.setTreasury(receiver);
await tx.wait();
console.log("Set treasury to:", treasury);
}
async function mintToken(tokenA, tokenB, user) { async function mintToken(tokenA, tokenB, user) {
var amount = hre.ethers.parseEther("1000000") var amount = hre.ethers.parseEther("1000000")
var tx = await tokenA.mint(user, amount); var tx = await tokenA.mint(user, amount);
...@@ -43,12 +55,12 @@ async function treasuryApprove(tokenA, tokenB, bridgeAddr, treasury) { ...@@ -43,12 +55,12 @@ async function treasuryApprove(tokenA, tokenB, bridgeAddr, treasury) {
async function setTokenTreasuryConfig(tokenA, tokenB, bridge) { async function setTokenTreasuryConfig(tokenA, tokenB, bridge) {
var tokenAAddr = await tokenA.getAddress(); var tokenAAddr = await tokenA.getAddress();
var tx = await bridge.setTreasuryConfig(tokenAAddr, hre.ethers.parseEther('0.0001'), 500, true); var tx = await bridge.setTreasuryConfig(tokenAAddr, hre.ethers.parseEther('50000'), 5000, true);
await tx.wait(); await tx.wait();
console.log("Set treasury config for TTA"); console.log("Set treasury config for TTA");
var tokenBAddr = await tokenB.getAddress(); var tokenBAddr = await tokenB.getAddress();
tx = await bridge.setTreasuryConfig(tokenBAddr, hre.ethers.parseEther('0.0001'), 500, true); tx = await bridge.setTreasuryConfig(tokenBAddr, hre.ethers.parseEther('50000'), 500, true);
await tx.wait(); await tx.wait();
console.log("Set treasury config for TTB"); console.log("Set treasury config for TTB");
} }
...@@ -60,13 +72,16 @@ async function setConfig(tokenA, tokenB, bridge) { ...@@ -60,13 +72,16 @@ async function setConfig(tokenA, tokenB, bridge) {
[owner, treasury] = await hre.ethers.getSigners(); [owner, treasury] = await hre.ethers.getSigners();
await setValidatorRequired(bridge, 2);
await addValidators(bridge, INITIAL_VALIDATORS); await addValidators(bridge, INITIAL_VALIDATORS);
await setFeeReceiver(bridge, TREASURY);
await setTreasury(bridge, TREASURY); await setTreasury(bridge, TREASURY);
await setTokenTreasuryConfig(tokenA, tokenB, bridge); await setTokenTreasuryConfig(tokenA, tokenB, bridge);
// if treasury is exist, do approve .
var bridgeAddr = await bridge.getAddress(); var bridgeAddr = await bridge.getAddress();
await mintToken(tokenA, tokenB, bridgeAddr) await mintToken(tokenA, tokenB, bridgeAddr)
// if treasury is exist, do approve .
// if (treasury.address) { // if (treasury.address) {
// // test environment, mint token and approve. // // test environment, mint token and approve.
// await mintToken(tokenA, tokenB, TREASURY); // await mintToken(tokenA, tokenB, TREASURY);
...@@ -129,7 +144,8 @@ async function setOutConfig(curTokenMap, targetTokenMap, targetChainId, bridge) ...@@ -129,7 +144,8 @@ async function setOutConfig(curTokenMap, targetTokenMap, targetChainId, bridge)
// Define the script // Define the script
async function main() { async function main() {
const chainId = await hre.ethers.provider.getNetwork().then(network => network.chainId); const chainId = await hre.ethers.provider.getNetwork().then(network => network.chainId);
const targetChainId = chainId === 269n ? 10323 : 269; const targetChainId = chainId === 97n ? 10323 : 97;
// const targetChainId = chainId === 6174n ? 8891 : 6174;
console.log("Current chain ID:", chainId, "Target chain ID:", targetChainId); console.log("Current chain ID:", chainId, "Target chain ID:", targetChainId);
const curChainDeploy = await getDeploy(chainId); const curChainDeploy = await getDeploy(chainId);
......
...@@ -125,20 +125,21 @@ async function outTransfer(bridge, token , amount, targetChainId, receiver) { ...@@ -125,20 +125,21 @@ async function outTransfer(bridge, token , amount, targetChainId, receiver) {
receiver receiver
); );
const receipt = await tx.wait(); const receipt = await tx.wait();
console.log("Bridged token:", await token.getAddress(), "to chain", targetChainId, "tx", receipt.transactionHash); console.log("Bridged token:", await token.getAddress(), "to chain", targetChainId, "tx", receipt.hash);
} }
// Define the script // Define the script
async function main() { async function main() {
const chainId = await hre.ethers.provider.getNetwork().then(network => network.chainId); const chainId = await hre.ethers.provider.getNetwork().then(network => network.chainId);
const targetChainId = chainId === 269n ? 10323 : 269; // const targetChainId = chainId === 6174n ? 8891 : 6174;
const targetChainId = chainId === 97n ? 10323 : 97;
console.log("Current chain ID:", chainId, "Target chain ID:", targetChainId); console.log("Current chain ID:", chainId, "Target chain ID:", targetChainId);
const chainDeploy = await getDeploy(chainId); const chainDeploy = await getDeploy(chainId);
await outTransfer(chainDeploy.bridge, chainDeploy.tokenA, hre.ethers.parseEther("100"), for (let i = 0; i < 1; i++) {
targetChainId, "0x3ef35d7db5f2d6a2fe7d16d4c8d4a20e9ad64a6a"); await outTransfer(chainDeploy.bridge, chainDeploy.tokenA, hre.ethers.parseEther("100"),
await outTransfer(chainDeploy.bridge, chainDeploy.tokenB, hre.ethers.parseEther("2"), targetChainId, "0x3ef35d7db5f2d6a2fe7d16d4c8d4a20e9ad64a6a");
targetChainId, "0x3ef35d7db5f2d6a2fe7d16d4c8d4a20e9ad64a6a"); }
} }
// Run the script // Run the script
......
...@@ -57,7 +57,7 @@ async function main() { ...@@ -57,7 +57,7 @@ async function main() {
// 99950000000000000000 1 269 0xfeed6dB33622Fb526a89c84A0861C29f483f1d0E 0xF5c10392D841d55C41EBf696A4E437b2DC91f5D3 100000000000000000000 // 99950000000000000000 1 269 0xfeed6dB33622Fb526a89c84A0861C29f483f1d0E 0xF5c10392D841d55C41EBf696A4E437b2DC91f5D3 100000000000000000000
// [173 7 190 114 90 113 152 216 28 141 140 44 56 193 112 16 201 218 15 200 10 31 177 5 222 100 31 193 182 38 224 133]}" // [173 7 190 114 90 113 152 216 28 141 140 44 56 193 112 16 201 218 15 200 10 31 177 5 222 100 31 193 182 38 224 133]}"
// sign=ad07be725a7198d81c8d8c2c38c17010c9da0fc80a1fb105de641fc1b626e085 // sign=ad07be725a7198d81c8d8c2c38c17010c9da0fc80a1fb105de641fc1b626e085
const params = { var params = {
toChainID: 10323, toChainID: 10323,
receiver: "0x3Ef35d7Db5F2d6A2fe7d16D4C8d4A20e9aD64A6A", receiver: "0x3Ef35d7Db5F2d6A2fe7d16D4C8d4A20e9aD64A6A",
token: "0xF5c10392D841d55C41EBf696A4E437b2DC91f5D3", token: "0xF5c10392D841d55C41EBf696A4E437b2DC91f5D3",
...@@ -69,6 +69,36 @@ async function main() { ...@@ -69,6 +69,36 @@ async function main() {
sendAmount: ethers.parseEther("100"), sendAmount: ethers.parseEther("100"),
signature: "0xad07be725a7198d81c8d8c2c38c17010c9da0fc80a1fb105de641fc1b626e085", signature: "0xad07be725a7198d81c8d8c2c38c17010c9da0fc80a1fb105de641fc1b626e085",
}; };
// {10323 0x3Ef35d7Db5F2d6A2fe7d16D4C8d4A20e9aD64A6A 0x6A24C27cF83dAFf6227fa03852465aA65cF22527 1960000000000000000
// 2 269 0xfeed6dB33622Fb526a89c84A0861C29f483f1d0E 0x6A24C27cF83dAFf6227fa03852465aA65cF22527 2000000000000000000}
// sign=9da901b0f85b070b4036d766bbc179dc84e55e06d908d0435213468e1dd1c9d8
params = {
toChainID: 10323,
receiver:"0x3Ef35d7Db5F2d6A2fe7d16D4C8d4A20e9aD64A6A",
token:"0x6A24C27cF83dAFf6227fa03852465aA65cF22527",
amount: ethers.parseEther("1.96"),
outId: 2,
fromChainID: 269,
sender: "0xfeed6dB33622Fb526a89c84A0861C29f483f1d0E",
sendToken: "0x6A24C27cF83dAFf6227fa03852465aA65cF22527",
sendAmount: ethers.parseEther("2"),
signature: "0x9da901b0f85b070b4036d766bbc179dc84e55e06d908d0435213468e1dd1c9d8",
}
// msg="build param" param="{269 0x3Ef35d7Db5F2d6A2fe7d16D4C8d4A20e9aD64A6A 0xF5c10392D841d55C41EBf696A4E437b2DC91f5D3
// 99950000000000000000 1 10323 0xfeed6dB33622Fb526a89c84A0861C29f483f1d0E 0xF5c10392D841d55C41EBf696A4E437b2DC91f5D3 100000000000000000000}" sign=26b9fea993b2e9f363fb90fdfb9ecd6a90c056abcb83af4b19239383ca1b8468
params = {
toChainID: 269,
receiver: "0x3Ef35d7Db5F2d6A2fe7d16D4C8d4A20e9aD64A6A",
token: "0xF5c10392D841d55C41EBf696A4E437b2DC91f5D3",
amount: hre.ethers.parseEther("99.95"),
outId: 1,
fromChainID: 10323,
sender: "0xfeed6dB33622Fb526a89c84A0861C29f483f1d0E",
sendToken: "0xF5c10392D841d55C41EBf696A4E437b2DC91f5D3",
sendAmount: hre.ethers.parseEther("100"),
signature: "0x26b9fea993b2e9f363fb90fdfb9ecd6a90c056abcb83af4b19239383ca1b8468",
}
const bridge = chainDeploy.bridge; const bridge = chainDeploy.bridge;
var tx = await bridge.connect(wallet).submitInTransfer(params); var tx = await bridge.connect(wallet).submitInTransfer(params);
await tx.wait(); await tx.wait();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment