Skip to content

Commit

Permalink
feat: add bridge call contract (#191)
Browse files Browse the repository at this point in the history
Co-authored-by: nulnut <151493716+nulnut@users.noreply.github.com>
  • Loading branch information
zakir-code and nulnut committed Feb 18, 2024
1 parent 1c44b3f commit 0ecb53f
Show file tree
Hide file tree
Showing 17 changed files with 4,537 additions and 5,498 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ local.*
release-note.md
artifacts
dist
out
out
typechain-types
5 changes: 4 additions & 1 deletion solidity/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ cache
.env
contracts/LICENSE
contracts/README.md
contracts/build
contracts/build
typechain-types
artifacts
*.log
2 changes: 1 addition & 1 deletion solidity/.solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
],
"reason-string": ["warn", { "maxLength": 64 }]
}
}
}
108 changes: 108 additions & 0 deletions solidity/contracts/bridge/FxBridgeLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/se

import {IERC20ExtensionsUpgradeable} from "./IERC20ExtensionsUpgradeable.sol";

/* solhint-disable custom-errors */

contract FxBridgeLogic is
ReentrancyGuardUpgradeable,
OwnableUpgradeable,
Expand Down Expand Up @@ -273,6 +275,36 @@ contract FxBridgeLogic is
);
}

function bridgeCall(
string memory _dstChainId,
uint256 _gasLimit,
address _receiver,
address _to,
bytes calldata _message,
uint256 _value,
bytes memory _asset
) external {
// decode and transfer asset
(string memory assetType, bytes memory assetData) = decodeType(_asset);
transferAsset(msg.sender, assetType, assetData);

// last event nonce +1
state_lastEventNonce = state_lastEventNonce.add(1);

// bridge call event
emit BridgeCallEvent(
_msgSender(),
_receiver,
_to,
state_lastEventNonce,
_dstChainId,
_gasLimit,
_value,
_message,
_asset
);
}

function submitBatch(
address[] memory _currentOracles,
uint256[] memory _currentPowers,
Expand Down Expand Up @@ -505,6 +537,70 @@ contract FxBridgeLogic is
return result;
}

function decodeType(
bytes memory _asset
) public pure returns (string memory, bytes memory) {
return abi.decode(_asset, (string, bytes));
}

function transferAsset(
address _sender,
string memory _assetType,
bytes memory _assetData
) internal {
if (
keccak256(bytes(_assetType)) ==
bytes32(
0x8ae85d849167ff996c04040c44924fd364217285e4cad818292c7ac37c0a345b
)
) {
transferERC20(_sender, _assetData);
} else {
revert("Asset type not support");
}
}

function transferERC20(address _from, bytes memory _asset) internal {
(address[] memory token, uint256[] memory amount) = decodeERC20(_asset);
for (uint256 i = 0; i < token.length; i++) {
require(amount[i] > 0, "amount should be greater than zero");
TokenStatus memory _tokenStatus = tokenStatus[token[i]];
require(_tokenStatus.isExist, "Unsupported token address");
require(_tokenStatus.isActive, "token was paused");

IERC20MetadataUpgradeable(token[i]).safeTransferFrom(
_from,
address(this),
amount[i]
);
if (_tokenStatus.isOriginated == true) {
IERC20ExtensionsUpgradeable(token[i]).burn(amount[i]);
}
}
}

function decodeERC20(
bytes memory _data
) internal pure returns (address[] memory, uint256[] memory) {
(bytes memory tokenBytes, uint256[] memory amounts) = abi.decode(
_data,
(bytes, uint256[])
);
uint256 tokenCount = amounts.length;
require(tokenBytes.length == tokenCount * 20, "Token not match amount");
address[] memory tokens = new address[](tokenCount);
for (uint256 i = 0; i < tokenCount; i++) {
uint256 currentTokenStartingByte = 20 + i * 20;
address currentToken;
// solhint-disable-next-line no-inline-assembly
assembly {
currentToken := mload(add(tokenBytes, currentTokenStartingByte))
}
tokens[i] = currentToken;
}
return (tokens, amounts);
}

/* =============== EVENTS =============== */

event TransactionBatchExecutedEvent(
Expand Down Expand Up @@ -535,4 +631,16 @@ contract FxBridgeLogic is
uint256[] _powers
);
event TransferOwnerEvent(address _token, address _newOwner);

event BridgeCallEvent(
address indexed _sender,
address indexed _receiver,
address indexed _to,
uint256 _eventNonce,
string _dstChainId,
uint256 _gasLimit,
uint256 _value,
bytes _message,
bytes _asset
);
}
2 changes: 2 additions & 0 deletions solidity/contracts/bridge/FxBridgeLogicBSC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/se

import {IERC20ExtensionsUpgradeable} from "./IERC20ExtensionsUpgradeable.sol";

/* solhint-disable custom-errors */

contract FxBridgeLogicBSC is
ReentrancyGuardUpgradeable,
OwnableUpgradeable,
Expand Down
2 changes: 2 additions & 0 deletions solidity/contracts/bridge/FxBridgeLogicETH.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/se

import {IERC20ExtensionsUpgradeable} from "./IERC20ExtensionsUpgradeable.sol";

/* solhint-disable custom-errors */

contract FxBridgeLogicETH is
ReentrancyGuardUpgradeable,
OwnableUpgradeable,
Expand Down
3 changes: 3 additions & 0 deletions solidity/contracts/fip20/FIP20Upgradable.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
/* solhint-disable one-contract-per-file */

pragma solidity ^0.8.0;

Expand All @@ -13,6 +14,7 @@ import "./IFIP20Upgradable.sol";
import "../crosschain/CrossChainCall.sol";

/* solhint-enable no-global-import */
/* solhint-disable custom-errors */

/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
Expand All @@ -38,6 +40,7 @@ abstract contract UUPSUpgradeable is
function __UUPSUpgradeable_init_unchained() internal onlyInitializing {}

/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
// solhint-disable-next-line immutable-vars-naming
address private immutable __self =
0x0000000000000000000000000000000000001001;

Expand Down
3 changes: 3 additions & 0 deletions solidity/contracts/fip20/WFXUpgradable.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
/* solhint-disable one-contract-per-file */

pragma solidity ^0.8.0;

Expand All @@ -12,6 +13,7 @@ import "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradea
import "../crosschain/CrossChainCall.sol";

/* solhint-enable no-global-import */
/* solhint-disable custom-errors */

/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
Expand All @@ -37,6 +39,7 @@ abstract contract UUPSUpgradeable is
function __UUPSUpgradeable_init_unchained() internal onlyInitializing {}

/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
// solhint-disable-next-line immutable-vars-naming
address private immutable __self =
0x0000000000000000000000000000000000001002;

Expand Down
1 change: 1 addition & 0 deletions solidity/contracts/test/CrossChainTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import "../crosschain/CrossChainCall.sol";
import "../fip20/IFIP20Upgradable.sol";

/* solhint-enable no-global-import */
/* solhint-disable custom-errors */

contract CrossChainTest {
function crossChain(
Expand Down
18 changes: 18 additions & 0 deletions solidity/contracts/test/ERC1155TokenTest.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import {ERC1155Burnable} from "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract ERC1155TokenTest is ERC1155, ERC1155Burnable, Ownable {
constructor(string memory uri_) ERC1155(uri_) {}

function mint(
address _to,
uint256 _id,
uint256 _amount
) external onlyOwner {
_mint(_to, _id, _amount, "");
}
}
76 changes: 12 additions & 64 deletions solidity/contracts/test/ERC721TokenTest.sol
Original file line number Diff line number Diff line change
@@ -1,73 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/* solhint-disable no-global-import */
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";

/* solhint-enable no-global-import */

contract ERC721TokenTest is
Initializable,
ERC721Upgradeable,
ERC721URIStorageUpgradeable,
OwnableUpgradeable,
UUPSUpgradeable
{
using CountersUpgradeable for CountersUpgradeable.Counter;

CountersUpgradeable.Counter private _tokenIdCounter;

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

function initialize() public initializer {
__ERC721_init("ERC721TokenTest", "TTT");
__ERC721URIStorage_init();
__Ownable_init();
__UUPSUpgradeable_init();
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {ERC721Burnable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract ERC721TokenTest is ERC721, ERC721Burnable, Ownable {
constructor(
string memory name,
string memory symbol
) ERC721(name, symbol) {}

function mint(address _to, uint256 _id) external onlyOwner {
_safeMint(_to, _id);
}

function _baseURI() internal pure override returns (string memory) {
return "ipfs://test-url";
}

function safeMint(address to, string memory uri) public onlyOwner {
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(to, tokenId);
_setTokenURI(tokenId, uri);
}

/* solhint-disable no-empty-blocks */
function _authorizeUpgrade(
address newImplementation
) internal override onlyOwner {}

/* solhint-enable no-empty-blocks */

// The following functions are overrides required by Solidity.

function _burn(
uint256 tokenId
) internal override(ERC721Upgradeable, ERC721URIStorageUpgradeable) {
super._burn(tokenId);
}

function tokenURI(
uint256 tokenId
)
public
view
override(ERC721Upgradeable, ERC721URIStorageUpgradeable)
returns (string memory)
{
return super.tokenURI(tokenId);
}
}
19 changes: 11 additions & 8 deletions solidity/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import {HardhatUserConfig} from "hardhat/config"
import "hardhat-dependency-compiler"
import "@nomicfoundation/hardhat-ethers"
import '@typechain/hardhat'
import "hardhat-gas-reporter"

import './tasks/task'

const config: HardhatUserConfig = {
defaultNetwork: "localhost",
defaultNetwork: "hardhat",
networks: {
hardhat: {
forking: {
url: `${process.env.MAINNET_URL || "https://mainnet.infura.io/v3/infura-key"}`,
}
},
hardhat: {},
localhost: {
url: `${process.env.LOCAL_URL || "http://localhost:8545"}`,
url: `${process.env.LOCAL_URL || "http://127.0.0.1:8545"}`,
},
},
solidity: {
Expand Down Expand Up @@ -53,6 +51,11 @@ const config: HardhatUserConfig = {
"@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol",
],
},
gasReporter: {
enabled: false,
currency: 'USD',
gasPrice: 30
},
};

export default config;
export default config;
Loading

0 comments on commit 0ecb53f

Please sign in to comment.