Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
B
bridgecontract
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
movabridge
bridgecontract
Commits
fb799d56
Commit
fb799d56
authored
Sep 18, 2025
by
vicotor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update contract
parent
82f35570
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
237 additions
and
21 deletions
+237
-21
bridge.sol
contracts/bridge.sol
+21
-0
hardhat.config.js
hardhat.config.js
+26
-3
deploy.json
scripts/deploy.json
+17
-7
deploy.json_bak
scripts/deploy.json_bak
+12
-0
getinfo.js
scripts/getinfo.js
+47
-0
mintforuser.js
scripts/mintforuser.js
+56
-0
setconfig.js
scripts/setconfig.js
+20
-4
usercase.js
scripts/usercase.js
+7
-6
validatorcase.js
scripts/validatorcase.js
+31
-1
No files found.
contracts/bridge.sol
View file @
fb799d56
...
...
@@ -74,6 +74,9 @@ contract Bridge is Ownable {
/// @dev 金库地址
address public treasury;
/// @dev 手续费接收地址
address public feeReceiver;
/**
* @dev 代币金库配置结构体
* @param minReserve 最小保留金额(合约必须保留的最少数量)
...
...
@@ -234,6 +237,9 @@ contract Bridge is Ownable {
/// @dev 金库地址变更事件
event TreasuryChanged(address indexed oldTreasury, address indexed newTreasury);
/// @dev feeRecevier地址变更事件
event FeeReceiverChanged(address indexed oldReceiver, address indexed newReceiver);
/// @dev 金库配置变更事件
event TreasuryConfigChanged(address indexed token, uint256 minReserve, uint256 reserveRatio, bool enabled);
...
...
@@ -388,6 +394,13 @@ contract Bridge is Ownable {
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 设置代币的金库配置
* @param token 代币地址
...
...
@@ -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));
require(params.signature == _signature, "signature not equal");
require(params.sendAmount >= params.amount, "invalid amounts");
// 检查是否已存在对应的转入记录
uint256 inId = getInId[params.fromChainID][params.outId];
...
...
@@ -607,6 +621,7 @@ contract Bridge is Ownable {
inId = _inID;
InInfo storage info = inTransfers[inId];
info.inId = inId;
info.fee = params.sendAmount - params.amount;
info.token = params.token;
info.receiver = params.receiver;
info.amount = params.amount;
...
...
@@ -635,6 +650,7 @@ contract Bridge is Ownable {
* @notice 验证者可以单独确认已提交的转入操作
*/
function confirmInTransfer(uint256 inId) public onlyValidator {
require(inTransfers[inId].token != address(0), "inId not exist");
_confirm(inId);
}
...
...
@@ -695,6 +711,11 @@ contract Bridge is Ownable {
// 执行代币转账
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;
...
...
hardhat.config.js
View file @
fb799d56
...
...
@@ -47,6 +47,8 @@ module.exports = {
etherscan
:
{
apiKey
:
{
'
achain
'
:
'
empty
'
,
'
movadev
'
:
'
empty
'
,
'
hole
'
:
'
empty
'
,
'
mova
'
:
'
empty
'
,
'
bsc
'
:
'
AVZIFYCHUFHPG9FDKNMHEWJ1VAW1H5U66T
'
},
...
...
@@ -59,6 +61,22 @@ module.exports = {
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
"
,
chainId
:
10323
,
...
...
@@ -84,12 +102,17 @@ module.exports = {
url
:
"
https://mars.rpc.movachain.com
"
,
accounts
:
privateKeys
},
bit
:
{
movadev
:
{
url
:
"
https://rpc.mova.bitheart.org
"
,
accounts
:
privateKeys
},
hpb
:
{
url
:
"
https://hpbnode.com
"
,
hole
:
{
url
:
"
https://rpc.hole.bitheart.org
"
,
accounts
:
privateKeys
},
bsctest
:
{
// url: "https://bsctest.bitheart.org",
url
:
"
https://bsc-testnet.bnbchain.org
"
,
accounts
:
privateKeys
}
}
...
...
scripts/deploy.json
View file @
fb799d56
{
"269"
:
{
"tokenA"
:
"0xF5c10392D841d55C41EBf696A4E437b2DC91f5D3"
,
"tokenB"
:
"0x6A24C27cF83dAFf6227fa03852465aA65cF22527"
,
"bridge"
:
"0x9a06d0CfAFc19a4bfe0ecd5f8bC20A26a88fA227"
"97"
:
{
"tokenA"
:
"0x802Debb02aF95A1e68c7b2586883c77D65E4De01"
,
"tokenB"
:
"0x6DC00bD82F04890D7aB68cedcA588818760Ad509"
,
"bridge"
:
"0x5fcEa08A3E2F0Eb96424925dA9a951388b7EC764"
},
"6174"
:
{
"tokenA"
:
"0x25cAa6D61D1b9589D827A29b2c4e9dA0a85080B6"
,
"tokenB"
:
"0xa77285d7BB3655C98E2f71D21f16e3aa511082c7"
,
"bridge"
:
"0xC91b0E98572b06a45a456715268Dd17b4b85D7fc"
},
"8891"
:
{
"tokenA"
:
"0x29Ec4977338704e2665020c1FA91187B5d40bfcc"
,
"tokenB"
:
"0xDe6Fea12B657128331bbB909400793A66EC5828B"
,
"bridge"
:
"0xa33DD581A5e287535D955bC9961bEC9Af6E39db7"
},
"10323"
:
{
"tokenA"
:
"0x
F5c10392D841d55C41EBf696A4E437b2DC91f5D3
"
,
"tokenB"
:
"0x
6A24C27cF83dAFf6227fa03852465aA65cF22527
"
,
"bridge"
:
"0x
9a06d0CfAFc19a4bfe0ecd5f8bC20A26a88fA227
"
"tokenA"
:
"0x
2e97f146364Bf2436414aFC68716e712657Bb929
"
,
"tokenB"
:
"0x
15E124E34B24FC6f1608E6ECB3f228826f550C04
"
,
"bridge"
:
"0x
802Debb02aF95A1e68c7b2586883c77D65E4De01
"
}
}
\ No newline at end of file
scripts/deploy.json_bak
0 → 100644
View file @
fb799d56
{
"6174": {
"tokenA": "0x9F225b7BCC4697414D4F6aC1CB985D07d34dAe0a",
"tokenB": "0xA989C4a3ADb9fb1860aFB18543E23F0717c68298",
"bridge": "0xceEC8799139C698De532e363DA7395E25F409775"
},
"8891": {
"tokenA": "0x6Fd62C3a41B46162919B6A7Be1455f511Ed7a9Cf",
"tokenB": "0x2D578F646e0334F3CBA9B17D00c7357372a63FEa",
"bridge": "0xA2d532F956770611647EcBab19d87d380145d0Cf"
}
}
\ No newline at end of file
scripts/getinfo.js
0 → 100644
View file @
fb799d56
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
===
6174
n
?
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
scripts/mintforuser.js
0 → 100644
View file @
fb799d56
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
===
6174
n
?
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
scripts/setconfig.js
View file @
fb799d56
...
...
@@ -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
)
{
var
tx
=
await
contract
.
setTreasury
(
treasury
);
await
tx
.
wait
();
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
)
{
var
amount
=
hre
.
ethers
.
parseEther
(
"
1000000
"
)
var
tx
=
await
tokenA
.
mint
(
user
,
amount
);
...
...
@@ -43,12 +55,12 @@ async function treasuryApprove(tokenA, tokenB, bridgeAddr, treasury) {
async
function
setTokenTreasuryConfig
(
tokenA
,
tokenB
,
bridge
)
{
var
tokenAAddr
=
await
tokenA
.
getAddress
();
var
tx
=
await
bridge
.
setTreasuryConfig
(
tokenAAddr
,
hre
.
ethers
.
parseEther
(
'
0.0001
'
),
5
00
,
true
);
var
tx
=
await
bridge
.
setTreasuryConfig
(
tokenAAddr
,
hre
.
ethers
.
parseEther
(
'
50000
'
),
50
00
,
true
);
await
tx
.
wait
();
console
.
log
(
"
Set treasury config for TTA
"
);
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
();
console
.
log
(
"
Set treasury config for TTB
"
);
}
...
...
@@ -60,13 +72,16 @@ async function setConfig(tokenA, tokenB, bridge) {
[
owner
,
treasury
]
=
await
hre
.
ethers
.
getSigners
();
await
setValidatorRequired
(
bridge
,
2
);
await
addValidators
(
bridge
,
INITIAL_VALIDATORS
);
await
setFeeReceiver
(
bridge
,
TREASURY
);
await
setTreasury
(
bridge
,
TREASURY
);
await
setTokenTreasuryConfig
(
tokenA
,
tokenB
,
bridge
);
// if treasury is exist, do approve .
var
bridgeAddr
=
await
bridge
.
getAddress
();
await
mintToken
(
tokenA
,
tokenB
,
bridgeAddr
)
// if treasury is exist, do approve .
// if (treasury.address) {
// // test environment, mint token and approve.
// await mintToken(tokenA, tokenB, TREASURY);
...
...
@@ -129,7 +144,8 @@ async function setOutConfig(curTokenMap, targetTokenMap, targetChainId, bridge)
// Define the script
async
function
main
()
{
const
chainId
=
await
hre
.
ethers
.
provider
.
getNetwork
().
then
(
network
=>
network
.
chainId
);
const
targetChainId
=
chainId
===
269
n
?
10323
:
269
;
const
targetChainId
=
chainId
===
97
n
?
10323
:
97
;
// const targetChainId = chainId === 6174n ? 8891 : 6174;
console
.
log
(
"
Current chain ID:
"
,
chainId
,
"
Target chain ID:
"
,
targetChainId
);
const
curChainDeploy
=
await
getDeploy
(
chainId
);
...
...
scripts/usercase.js
View file @
fb799d56
...
...
@@ -125,20 +125,21 @@ async function outTransfer(bridge, token , amount, targetChainId, receiver) {
receiver
);
const
receipt
=
await
tx
.
wait
();
console
.
log
(
"
Bridged token:
"
,
await
token
.
getAddress
(),
"
to chain
"
,
targetChainId
,
"
tx
"
,
receipt
.
transactionH
ash
);
console
.
log
(
"
Bridged token:
"
,
await
token
.
getAddress
(),
"
to chain
"
,
targetChainId
,
"
tx
"
,
receipt
.
h
ash
);
}
// Define the script
async
function
main
()
{
const
chainId
=
await
hre
.
ethers
.
provider
.
getNetwork
().
then
(
network
=>
network
.
chainId
);
const
targetChainId
=
chainId
===
269
n
?
10323
:
269
;
// const targetChainId = chainId === 6174n ? 8891 : 6174;
const
targetChainId
=
chainId
===
97
n
?
10323
:
97
;
console
.
log
(
"
Current chain ID:
"
,
chainId
,
"
Target chain ID:
"
,
targetChainId
);
const
chainDeploy
=
await
getDeploy
(
chainId
);
for
(
let
i
=
0
;
i
<
1
;
i
++
)
{
await
outTransfer
(
chainDeploy
.
bridge
,
chainDeploy
.
tokenA
,
hre
.
ethers
.
parseEther
(
"
100
"
),
targetChainId
,
"
0x3ef35d7db5f2d6a2fe7d16d4c8d4a20e9ad64a6a
"
);
await
outTransfer
(
chainDeploy
.
bridge
,
chainDeploy
.
tokenB
,
hre
.
ethers
.
parseEther
(
"
2
"
),
targetChainId
,
"
0x3ef35d7db5f2d6a2fe7d16d4c8d4a20e9ad64a6a
"
);
}
}
// Run the script
...
...
scripts/validatorcase.js
View file @
fb799d56
...
...
@@ -57,7 +57,7 @@ async function main() {
// 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]}"
// sign=ad07be725a7198d81c8d8c2c38c17010c9da0fc80a1fb105de641fc1b626e085
const
params
=
{
var
params
=
{
toChainID
:
10323
,
receiver
:
"
0x3Ef35d7Db5F2d6A2fe7d16D4C8d4A20e9aD64A6A
"
,
token
:
"
0xF5c10392D841d55C41EBf696A4E437b2DC91f5D3
"
,
...
...
@@ -69,6 +69,36 @@ async function main() {
sendAmount
:
ethers
.
parseEther
(
"
100
"
),
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
;
var
tx
=
await
bridge
.
connect
(
wallet
).
submitInTransfer
(
params
);
await
tx
.
wait
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment