diff --git a/contracts/SpaceBridge.sol b/contracts/SpaceBridge.sol index 3ef9aaf..7f51a42 100644 --- a/contracts/SpaceBridge.sol +++ b/contracts/SpaceBridge.sol @@ -45,7 +45,8 @@ contract SpaceBridge is ReentrancyGuard, uint24 dst_network, uint256 amount, address hash, - address src_address + address src_address, + uint256 nonce ); event Burn( @@ -53,7 +54,8 @@ contract SpaceBridge is ReentrancyGuard, uint24 dst_network, uint256 amount, address hash, - address src_address + address src_address, + uint256 nonce ); event Unlock( @@ -80,9 +82,13 @@ contract SpaceBridge is ReentrancyGuard, spaceStorage = ISpaceStorage(_storage); } - function getTransfer(string memory src_address, string memory src_hash, uint256 src_network, string memory dst_address, uint256 dst_network) external view returns (uint256) { - bytes32 id = TransferKey.compute(src_address, src_hash, src_network, dst_address, dst_network); - return spaceStorage.transfers(id); + function getChannelNonce(string memory src_address, string memory src_hash, uint256 src_network, string memory dst_address, uint256 dst_network) external view returns (uint256) { + bytes32 id = TransferKey.compute(src_address, src_hash, src_network, dst_address, dst_network); + return spaceStorage.transfers(id); + } + + function getChannelId(string memory src_address, string memory src_hash, uint256 src_network, string memory dst_address, uint256 dst_network) external pure returns (bytes32) { + return TransferKey.compute(src_address, src_hash, src_network, dst_address, dst_network); } // @@ -104,10 +110,6 @@ contract SpaceBridge is ReentrancyGuard, // // LOCK // - //@param dst_address - адрес получателя в сети назначения - //@param dst_network - идентификатор сети назначения - //@param amount - количество - //@param hash - хеш токена в сети отправления function lock(bytes memory dst_address, uint24 dst_network, uint256 amount, address hash, uint256 nonce) checkSetup nonReentrant external { require( spaceStorage.known_networks(dst_network).valid, @@ -146,10 +148,10 @@ contract SpaceBridge is ReentrancyGuard, if(bytes(spaceStorage.minted(hash).origin_hash).length == 0){ vault.deposit(hash, msg.sender, amount); - emit Lock(dst_address, dst_network, amount, hash, msg.sender); + emit Lock(dst_address, dst_network, amount, hash, msg.sender, nonce); }else{ vault.burn(hash, msg.sender, amount); - emit Burn(dst_address, dst_network, amount, hash, msg.sender); + emit Burn(dst_address, dst_network, amount, hash, msg.sender, nonce); } spaceStorage.incrementNonce(TransferKey.compute(Converter.toAsciiString(msg.sender), Converter.toAsciiString(hash), network_id, string(abi.encodePacked(dst_address)), dst_network)); @@ -176,34 +178,29 @@ contract SpaceBridge is ReentrancyGuard, "Invalid signature" ); - if((ticket.origin_network == ticket.src_network) || ((ticket.origin_network != ticket.src_network) && (ticket.origin_network != network_id))) { //EСЛИ *origin_network* РАВНО *src_network* - address token_address = spaceStorage.getAddressFromOriginHahs(ticket.origin_hash); - // ТО ЕСЛИ {*origin_hash*, *origin_network*} СОДЕРЖИТСЯ В {*contract.minted.origin.hash*, *contract.minted.origin.network*} - // TO сминтить_токен(*amount*, *contract.minted.wrapped_hash*) - // передать_актив(*dst_address*, *amount*, *contract.minted.wrapped_hash*) - // ИНАЧЕ + if((ticket.origin_network == ticket.src_network) || ((ticket.origin_network != ticket.src_network) && (ticket.origin_network != network_id))) { + address token_address = spaceStorage.getAddressFromOriginHash(ticket.origin_hash); if(token_address == address(0x0)){ - // *new_hash* = создать_токен(*amount*) bytes memory bytes_hash = bytes(ticket.origin_hash); token_address = vault.deploy( string(abi.encodePacked(ticket.name)), string(abi.encodePacked(ticket.symbol)), ticket.origin_network, - bytes_hash); + bytes_hash, + ticket.origin_decimals); spaceStorage.addMinted( token_address, ticket.origin_hash, Storage.TKN({ origin_network: ticket.origin_network, - origin_hash: ticket.origin_hash} - ) - );//ВСТАВИТЬ {*new_hash*, *origin_hash*, *origin_network*} В *minted* + origin_hash: ticket.origin_hash, + origin_decimals: ticket.origin_decimals}) + ); } - // передать_актив(*new_hash*, *dst_address*, *amount*) vault.mint(token_address, ticket.dst_address, ticket.amount); emit Mint(token_address, ticket.dst_address, ticket.amount); - } else { //if(ticket.origin_network == network_id) { // ИНАЧЕ ЕСЛИ *origin_network* РАВНО *contract.network_id* - vault.withdraw(spaceStorage.lock_map(ticket.origin_hash), ticket.dst_address, ticket.amount); // ТО передать_актив(*dst_address*, *amount*, *origin_hash*) + } else { + vault.withdraw(spaceStorage.lock_map(ticket.origin_hash), ticket.dst_address, ticket.amount); emit Unlock(ticket.dst_address, ticket.amount); } spaceStorage.incrementNonce(TransferKey.compute(ticket.src_address, ticket.src_hash, ticket.src_network, Converter.toAsciiString(ticket.dst_address), ticket.dst_network)); diff --git a/contracts/SpaceStorage.sol b/contracts/SpaceStorage.sol index bf3205f..d87b3eb 100644 --- a/contracts/SpaceStorage.sol +++ b/contracts/SpaceStorage.sol @@ -7,37 +7,46 @@ import {Storage} from "./libraries/Struct.sol"; contract SpaceStorage is OnlyGovernance, OnlyBridge { - uint nextValidatorId = 1; - // количество подписей, необходимых для перевода активов uint24 public threshold; - mapping(address => uint) public validators; + mapping(address => bool) public validators; mapping(uint256 => Storage.NETWORK) public known_networks; mapping(address => Storage.TKN) _minted; - mapping(string => address) public getAddressFromOriginHahs; + mapping(string => address) public getAddressFromOriginHash; mapping(bytes32 => uint256) public transfers; mapping(string => address) public lock_map; function addNetwork(uint256 id, uint8 decimals_) onlyGovernance external { + require( + !known_networks[id].valid, + "Network exist" + ); known_networks[id] = Storage.NETWORK({valid:true, decimals:decimals_}); } + function removeNetwork(uint256 id) onlyGovernance external { + require( + known_networks[id].valid, + "dosnt exist network" + ); + delete known_networks[id]; + } + function addValidator(address validator) onlyGovernance public { require( - validators[validator] == 0, + !validators[validator], "Owner exist" ); - validators[validator] = nextValidatorId; - nextValidatorId++; + validators[validator] = true; } function removeValidator(address validator) onlyGovernance external { require( - validators[validator] != 0, + validators[validator], "dosnt exist owner" ); delete validators[validator]; @@ -49,7 +58,7 @@ contract SpaceStorage is OnlyGovernance, OnlyBridge { function addMinted(address token_address, string memory origin_hash, Storage.TKN memory tkn) onlyBridge external { _minted[token_address] = tkn; - getAddressFromOriginHahs[origin_hash] = token_address; + getAddressFromOriginHash[origin_hash] = token_address; } function incrementNonce(bytes32 key) onlyBridge external { diff --git a/contracts/SpaceVault.sol b/contracts/SpaceVault.sol index 9510f75..5385838 100644 --- a/contracts/SpaceVault.sol +++ b/contracts/SpaceVault.sol @@ -91,9 +91,10 @@ contract SpaceVault is IVault, string memory name, string memory symbol, uint256 origin, - bytes memory origin_hash + bytes memory origin_hash, + uint8 origin_decimals ) nonReentrant onlyBridge external override returns(address){ - return _deploy(name, symbol, origin, origin_hash); + return _deploy(name, symbol, origin, origin_hash, origin_decimals); } function mint( diff --git a/contracts/interfaces/ISpaceStorage.sol b/contracts/interfaces/ISpaceStorage.sol index a879cb0..47d8de1 100644 --- a/contracts/interfaces/ISpaceStorage.sol +++ b/contracts/interfaces/ISpaceStorage.sol @@ -11,7 +11,7 @@ interface ISpaceStorage { function threshold() external view returns (uint24); // Function signature for mapping - function validators(address key) external view returns (uint); + function validators(address key) external view returns (bool); // Function signature for mapping function known_networks(uint256 key) external view returns (Storage.NETWORK memory); @@ -19,7 +19,7 @@ interface ISpaceStorage { // Function signature for mapping function minted(address key) external view returns (Storage.TKN memory); // Function signature for mapping - function getAddressFromOriginHahs(string memory key) external view returns (address); + function getAddressFromOriginHash(string memory key) external view returns (address); // Function signature for mapping function transfers(bytes32 key) external view returns (uint256); @@ -35,6 +35,10 @@ interface ISpaceStorage { uint8 ) external; + function removeNetwork( + uint256 id + ) external; + function addValidator( address ) external; @@ -61,7 +65,4 @@ interface ISpaceStorage { string memory t, address token_hash ) external; - - - } \ No newline at end of file diff --git a/contracts/interfaces/IVault.sol b/contracts/interfaces/IVault.sol index b13696c..93378e0 100644 --- a/contracts/interfaces/IVault.sol +++ b/contracts/interfaces/IVault.sol @@ -19,7 +19,8 @@ interface IVault { string memory name, string memory symbol, uint256 origin, - bytes memory origin_hash + bytes memory origin_hash, + uint8 origin_decimals ) external returns(address); function mint( diff --git a/contracts/interfaces/IWrapedTokenDeployer.sol b/contracts/interfaces/IWrapedTokenDeployer.sol index 1899235..9d737cc 100644 --- a/contracts/interfaces/IWrapedTokenDeployer.sol +++ b/contracts/interfaces/IWrapedTokenDeployer.sol @@ -14,6 +14,7 @@ interface IWrapedTokenDeployer { external returns ( uint256 origin, - bytes memory origin_hash + bytes memory origin_hash, + uint8 origin_decimals ); } \ No newline at end of file diff --git a/contracts/libraries/Converter.sol b/contracts/libraries/Converter.sol index 49e4402..b03a394 100644 --- a/contracts/libraries/Converter.sol +++ b/contracts/libraries/Converter.sol @@ -21,6 +21,7 @@ library Converter { ticket.dst_network, ticket.name, ticket.nonce, + ticket.origin_decimals, ticket.origin_hash, ticket.origin_network, ticket.src_address, diff --git a/contracts/libraries/ECDSA.sol b/contracts/libraries/ECDSA.sol index 0521444..bb50e30 100644 --- a/contracts/libraries/ECDSA.sol +++ b/contracts/libraries/ECDSA.sol @@ -21,7 +21,7 @@ library ECDSA { //4 - v for (uint i=0; i; /** @type import('hardhat/config').HardhatUserConfig */ module.exports = { solidity: "0.8.7", + networks: { + goerli: { + url: `https://goerli.infura.io/v3/88762928a4164487b3fcdd2dc892598d`, + accounts: [PRIVATE_KEY], + id: 5 + }, + polygonMumbai: { + url: "https://rpc-mumbai.maticvigil.com", + accounts: [PRIVATE_KEY], + id: 80001 + }, + bscTestnet: { + url: `https://data-seed-prebsc-1-s1.binance.org:8545`, + accounts: [PRIVATE_KEY], + id: 97 + } + }, + etherscan: { + apiKey: { + goerli: "IVD4ZVQ8Z2VU613SHF9FNS4ABKKF7WPDYK", + bscTestnet : 'G6FS6SET5P7V7B6KGFHTTGAFY8Q62FI72H', + polygonMumbai : 'NRSIR1KMP51HM6S2XXAAI2V867G6SUS2DV' + }, + customChains: [ + { + network: "goerli", + chainId: 5, + urls: { + apiURL: "https://api-goerli.etherscan.io/api", + browserURL: "https://goerli.etherscan.io" + } + }, + { + network: "polygonMumbai", + chainId: 80001, + urls: { + apiURL: "https://api-testnet.polygonscan.com", + browserURL: "https://mumbai.polygonscan.com" + } + } + ] + } }; diff --git a/package.json b/package.json index 067aea2..abeabbf 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "homepage": "https://github.com/TrinityLabDAO/eth-enq-bridge-v1.0#readme", "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^2.0.1", + "@nomiclabs/hardhat-etherscan": "^3.1.6", "hardhat": "^2.12.7" }, "dependencies": { diff --git a/scripts/arguments_bscTestnet.js b/scripts/arguments_bscTestnet.js new file mode 100644 index 0000000..76e5bb9 --- /dev/null +++ b/scripts/arguments_bscTestnet.js @@ -0,0 +1,3 @@ +module.exports = [ + 97, +]; \ No newline at end of file diff --git a/scripts/arguments_goerli.js b/scripts/arguments_goerli.js new file mode 100644 index 0000000..e026d5b --- /dev/null +++ b/scripts/arguments_goerli.js @@ -0,0 +1,3 @@ +module.exports = [ + 5, +]; \ No newline at end of file diff --git a/scripts/arguments_polygonMumbai.js b/scripts/arguments_polygonMumbai.js new file mode 100644 index 0000000..54cbfa6 --- /dev/null +++ b/scripts/arguments_polygonMumbai.js @@ -0,0 +1,3 @@ +module.exports = [ + 80001, +]; \ No newline at end of file diff --git a/scripts/arguments_sepolia.js b/scripts/arguments_sepolia.js new file mode 100644 index 0000000..ed10425 --- /dev/null +++ b/scripts/arguments_sepolia.js @@ -0,0 +1,3 @@ +module.exports = [ + 11155111, +]; \ No newline at end of file diff --git a/scripts/deploy_bscTestnet.js b/scripts/deploy_bscTestnet.js new file mode 100644 index 0000000..29e4359 --- /dev/null +++ b/scripts/deploy_bscTestnet.js @@ -0,0 +1,46 @@ +async function main() { + const [deployer] = await ethers.getSigners(); + + console.log("Deploying contracts with the account:", deployer.address); + + console.log("Account balance:", (await deployer.getBalance()).toString()); + const SpaceVault = await ethers.getContractFactory("SpaceVault"); + const SpaceStorage = await ethers.getContractFactory("SpaceStorage"); + const SpaceBridge = await ethers.getContractFactory("SpaceBridge"); + // To deploy our contract, we just have to call Token.deploy() and await + // its deployed() method, which happens once its transaction has been + // mined. + const hardhatVault = await SpaceVault.deploy(); + const hardhatStorage = await SpaceStorage.deploy(); + const hardhatBridge = await SpaceBridge.deploy(97); + + await hardhatVault.setBridge(hardhatBridge.address); + await hardhatStorage.setBridge(hardhatBridge.address); + //BIT network + let networkId = 1; + let decimals = 10; + await hardhatStorage.addNetwork(networkId, decimals); + await hardhatStorage.addNetwork(80001, 18); //mumbai + await hardhatStorage.addNetwork(5, 18); //goerli + await hardhatStorage.addNetwork(23, 3); //test + await hardhatStorage.addNetwork(29, 4); //test 2 + + await hardhatStorage.addValidator("0x1F04445E17AA4B64cc9390fd2f76474A5e9B72c1"); + await hardhatStorage.addValidator("0xf784C9bca8BbDD93A195aeCdBa23472f89B1E7d6"); + + await hardhatStorage.setThreshold(1); + + await hardhatBridge.setVault(hardhatVault.address); + await hardhatBridge.setStorage(hardhatStorage.address); + + console.log("Vault address:", hardhatVault.address); + console.log("Storage address:", hardhatStorage.address); + console.log("Bridge address:", hardhatBridge.address); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deploy_goerli.js b/scripts/deploy_goerli.js new file mode 100644 index 0000000..2eca951 --- /dev/null +++ b/scripts/deploy_goerli.js @@ -0,0 +1,44 @@ +async function main() { + const [deployer] = await ethers.getSigners(); + + console.log("Deploying contracts with the account:", deployer.address); + + console.log("Account balance:", (await deployer.getBalance()).toString()); + + const SpaceVault = await ethers.getContractFactory("SpaceVault"); + const SpaceStorage = await ethers.getContractFactory("SpaceStorage"); + const SpaceBridge = await ethers.getContractFactory("SpaceBridge"); + // To deploy our contract, we just have to call Token.deploy() and await + // its deployed() method, which happens once its transaction has been + // mined. + const hardhatVault = await SpaceVault.deploy(); + const hardhatStorage = await SpaceStorage.deploy(); + const hardhatBridge = await SpaceBridge.deploy(5); + + await hardhatVault.setBridge(hardhatBridge.address); + await hardhatStorage.setBridge(hardhatBridge.address); + //BIT network + let networkId = 1; + let decimals = 10; + await hardhatStorage.addNetwork(networkId, decimals); + await hardhatStorage.addNetwork(80001, 18); //mumbai + await hardhatStorage.addNetwork(97, 18); //bsc + + await hardhatStorage.addValidator("0x1F04445E17AA4B64cc9390fd2f76474A5e9B72c1"); + + await hardhatStorage.setThreshold(1); + + await hardhatBridge.setVault(hardhatVault.address); + await hardhatBridge.setStorage(hardhatStorage.address); + + console.log("Vault address:", hardhatVault.address); + console.log("Storage address:", hardhatStorage.address); + console.log("Bridge address:", hardhatBridge.address); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deploy_polygonMumbai.js b/scripts/deploy_polygonMumbai.js new file mode 100644 index 0000000..728b167 --- /dev/null +++ b/scripts/deploy_polygonMumbai.js @@ -0,0 +1,47 @@ +async function main() { + const [deployer] = await ethers.getSigners(); + + console.log("Deploying contracts with the account:", deployer.address); + + console.log("Account balance:", (await deployer.getBalance()).toString()); + + const SpaceVault = await ethers.getContractFactory("SpaceVault"); + const SpaceStorage = await ethers.getContractFactory("SpaceStorage"); + const SpaceBridge = await ethers.getContractFactory("SpaceBridge"); + // To deploy our contract, we just have to call Token.deploy() and await + // its deployed() method, which happens once its transaction has been + // mined. + const hardhatVault = await SpaceVault.deploy(); + const hardhatStorage = await SpaceStorage.deploy(); + const hardhatBridge = await SpaceBridge.deploy(80001); + + await hardhatVault.setBridge(hardhatBridge.address); + await hardhatStorage.setBridge(hardhatBridge.address); + //BIT network + let networkId = 1; + let decimals = 10; + await hardhatStorage.addNetwork(networkId, decimals); + await hardhatStorage.addNetwork(5, 18); //goerli + await hardhatStorage.addNetwork(97, 18); //bsc + await hardhatStorage.addNetwork(23, 3); //test + await hardhatStorage.addNetwork(29, 4); //test 2 + + await hardhatStorage.addValidator("0x1F04445E17AA4B64cc9390fd2f76474A5e9B72c1"); + await hardhatStorage.addValidator("0xf784C9bca8BbDD93A195aeCdBa23472f89B1E7d6"); + + await hardhatStorage.setThreshold(1); + + await hardhatBridge.setVault(hardhatVault.address); + await hardhatBridge.setStorage(hardhatStorage.address); + + console.log("Vault address:", hardhatVault.address); + console.log("Storage address:", hardhatStorage.address); + console.log("Bridge address:", hardhatBridge.address); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deploy_sepolia.js b/scripts/deploy_sepolia.js new file mode 100644 index 0000000..61191cb --- /dev/null +++ b/scripts/deploy_sepolia.js @@ -0,0 +1,48 @@ +async function main() { + const [deployer] = await ethers.getSigners(); + + console.log("Deploying contracts with the account:", deployer.address); + + console.log("Account balance:", (await deployer.getBalance()).toString()); + + const SpaceVault = await ethers.getContractFactory("SpaceVault"); + const SpaceStorage = await ethers.getContractFactory("SpaceStorage"); + const SpaceBridge = await ethers.getContractFactory("SpaceBridge"); + // To deploy our contract, we just have to call Token.deploy() and await + // its deployed() method, which happens once its transaction has been + // mined. + const hardhatVault = await SpaceVault.deploy(); + const hardhatStorage = await SpaceStorage.deploy(); + const hardhatBridge = await SpaceBridge.deploy(11155111); + + await hardhatVault.setBridge(hardhatBridge.address); + await hardhatStorage.setBridge(hardhatBridge.address); + //BIT network + let networkId = 1; + let decimals = 10; + await hardhatStorage.addNetwork(networkId, decimals); + await hardhatStorage.addNetwork(80001, 18); //mumbai + await hardhatStorage.addNetwork(5, 18); //goerli + await hardhatStorage.addNetwork(97, 18); //bsc + await hardhatStorage.addNetwork(23, 3); //test + await hardhatStorage.addNetwork(29, 4); //test 2 + + await hardhatStorage.addValidator("0x1F04445E17AA4B64cc9390fd2f76474A5e9B72c1"); + await hardhatStorage.addValidator("0xf784C9bca8BbDD93A195aeCdBa23472f89B1E7d6"); + + await hardhatStorage.setThreshold(1); + + await hardhatBridge.setVault(hardhatVault.address); + await hardhatBridge.setStorage(hardhatStorage.address); + + console.log("Vault address:", hardhatVault.address); + console.log("Storage address:", hardhatStorage.address); + console.log("Bridge address:", hardhatBridge.address); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + });