diff --git a/contracts/BKCommon.sol b/contracts/BKCommon.sol deleted file mode 100644 index e4992d6..0000000 --- a/contracts/BKCommon.sol +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -import "@openzeppelin/contracts/access/Ownable.sol"; -import "@openzeppelin/contracts/security/Pausable.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; -import "./interfaces/IBKErrors.sol"; - -contract BKCommon is IBKErrors, Ownable, Pausable, ReentrancyGuard { - - using SafeERC20 for IERC20; - - mapping(address => bool) isOperator; - - event RescueETH(address indexed recipient, uint256 amount); - event RescueERC20(address indexed asset, address recipient); - event SetOperator(address operator, bool isOperator); - - modifier onlyOperator() { - require(isOperator[_msgSender()], "Operator: caller is not the operator"); - _; - } - - function setOperator(address[] calldata _operators, bool _isOperator) external onlyOwner { - for(uint i = 0; i < _operators.length; i++) { - isOperator[_operators[i]] = _isOperator; - emit SetOperator(_operators[i], _isOperator); - } - } - - function pause() external onlyOperator { - _pause(); - } - - function unpause() external onlyOperator { - _unpause(); - } - - function rescueERC20(address asset, address recipient) external onlyOperator { - IERC20(asset).safeTransfer( - recipient, - IERC20(asset).balanceOf(address(this)) - ); - emit RescueERC20(asset, recipient); - } - - function rescueETH(address recipient) external onlyOperator { - _transferEth(recipient, address(this).balance); - } - - function _transferEth(address _to, uint256 _amount) internal { - bool callStatus; - assembly { - // Transfer the ETH and store if it succeeded or not. - callStatus := call(gas(), _to, _amount, 0, 0, 0, 0) - } - require(callStatus, "_transferEth: Eth transfer failed"); - emit RescueETH(_to, _amount); - } - - /// @dev Revert with arbitrary bytes. - /// @param data Revert data. - function _revertWithData(bytes memory data) internal pure { - assembly { revert(add(data, 32), mload(data)) } - } - - receive() external payable {} -} \ No newline at end of file diff --git a/contracts/BKFees.sol b/contracts/BKFees.sol deleted file mode 100644 index aaa17f4..0000000 --- a/contracts/BKFees.sol +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import "./BKCommon.sol"; - -contract BKFees is BKCommon { - - using ECDSA for bytes32; - - address payable private feeTo; - address payable private altcoinsFeeTo; - uint private feeRate; - address private signer; - mapping (bytes32 => bool) private executed; - - event SetFeeTo( - address operator, - address payable feeTo, - address payable altcoinsFeeTo, - uint feeRate - ); - event SetSigner(address operator, address newSigner); - - constructor ( - address _signer, - address payable _feeTo, - address payable _altcoinsFeeTo, - uint _feeRate, - address _owner - ) { - if (_signer == address(0) || _feeTo == address(0) || _altcoinsFeeTo == address(0)) { - revert InvalidZeroAddress(); - } - - if (_feeRate < 10 || _feeRate > 50) { - revert InvalidFeeRate(_feeRate); - } - - signer = _signer; - feeTo = _feeTo; - altcoinsFeeTo = _altcoinsFeeTo; - feeRate = _feeRate; - emit SetFeeTo(msg.sender, _feeTo, _altcoinsFeeTo, _feeRate); - _transferOwnership(_owner); - } - - function setFeeTo ( - address payable _feeTo, - address payable _altcoinsFeeTo, - uint _feeRate - ) external onlyOwner whenNotPaused { - - if ( _feeTo == address(0) || _altcoinsFeeTo == address(0)) { - revert InvalidZeroAddress(); - } - - if (_feeRate < 10 || _feeRate > 50) { - revert InvalidFeeRate(_feeRate); - } - - feeTo = _feeTo; - altcoinsFeeTo = _altcoinsFeeTo; - feeRate = _feeRate; - - emit SetFeeTo(msg.sender, _feeTo, _altcoinsFeeTo, _feeRate); - } - - function getFeeTo () external view returns( - address payable _feeTo, - address payable _altcoinsFeeTo, - uint _feeRate - ){ - _feeTo = feeTo; - _altcoinsFeeTo = altcoinsFeeTo; - _feeRate = feeRate; - } - - function setSigner(address _signer) external onlyOwner whenNotPaused { - - if ( _signer == address(0)) { - revert InvalidZeroAddress(); - } - signer = _signer; - - emit SetSigner(msg.sender, _signer); - } - - function getSigner() external view returns(address){ - return signer; - } - - function checkIsSigner(bytes32 _nonceHash, bytes calldata _signature) external { - - bytes32 msgHash = keccak256(abi.encodePacked(_nonceHash, block.chainid, address(this))); - - bytes32 finalMsgHash = msgHash.toEthSignedMessageHash(); - - if (executed[finalMsgHash]) { - revert IBKErrors.InvalidNonce(finalMsgHash); - } else { - executed[finalMsgHash] = true; - } - - address signer_ = finalMsgHash.recover(_signature); - - if(signer_ != signer){ - revert IBKErrors.InvalidSigner(); - } - } -} diff --git a/contracts/BKRegistry.sol b/contracts/BKRegistry.sol deleted file mode 100644 index 0d7f7a5..0000000 --- a/contracts/BKRegistry.sol +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -import "./BKCommon.sol"; - -contract BKRegistry is BKCommon { - struct Feature { - address proxy; - bool isLib; - bool isActive; - } - - mapping(bytes4 => Feature) private features; - mapping(bytes4 => mapping(address => bool)) private isCallTargets; - mapping(bytes4 => mapping(address => bool)) private isApproveTargets; - - event SetFeature(address operator, bytes4 methodId, address proxy, bool isLib, bool isActive); - event SetCallTarget(address operator, bytes4 methodId, address target, bool isEnable); - event SetApproveTarget(address operator, bytes4 methodId, address target, bool isEnable); - - constructor(address _owner) { - _transferOwnership(_owner); - } - - function setFeature( - bytes4 _methodId, - address _proxy, - bool _isLib, - bool _isActive - ) external onlyOwner whenNotPaused { - - Feature memory feat = Feature({ - proxy : _proxy, - isLib : _isLib, - isActive : _isActive - }); - features[_methodId] = feat; - - emit SetFeature(msg.sender, _methodId, _proxy, _isLib, _isActive); - } - - function getFeature(bytes4 _methodId) - external - view - returns (address proxy, bool isLib) { - Feature memory feat = features[_methodId]; - - _checkFeatureStatus(feat); - - proxy = feat.proxy; - isLib = feat.isLib; - } - - function setCallTarget( - bytes4 _methodId, - address [] calldata _targets, - bool _isEnable - ) external onlyOwner whenNotPaused { - Feature memory feat = features[_methodId]; - - _checkFeatureStatus(feat); - - for (uint256 i = 0; i < _targets.length; i++) { - isCallTargets[_methodId][_targets[i]] = _isEnable; - emit SetCallTarget(msg.sender, _methodId, _targets[i], _isEnable); - } - } - - function isCallTarget(bytes4 _methodId, address _target) - external - view - returns (bool) { - Feature memory feat = features[_methodId]; - - _checkFeatureStatus(feat); - - return isCallTargets[_methodId][_target]; - } - - function setApproveTarget( - bytes4 _methodId, - address [] calldata _targets, - bool _isEnable - ) external onlyOwner whenNotPaused { - Feature memory feat = features[_methodId]; - - _checkFeatureStatus(feat); - - for (uint256 i = 0; i < _targets.length; i++) { - isApproveTargets[_methodId][_targets[i]] = _isEnable; - emit SetApproveTarget(msg.sender, _methodId, _targets[i], _isEnable); - } - } - - function isApproveTarget(bytes4 _methodId, address _target) - external - view - returns (bool) { - Feature memory feat = features[_methodId]; - - _checkFeatureStatus(feat); - - return isApproveTargets[_methodId][_target]; - } - - function _checkFeatureStatus(Feature memory _feat) internal pure { - if (_feat.proxy == address(0)) { - revert FeatureNotExist(); - } - - if (!_feat.isActive) { - revert FeatureInActive(); - } - } -} diff --git a/contracts/BKSwap.sol b/contracts/BKSwap.sol deleted file mode 100644 index 529053a..0000000 --- a/contracts/BKSwap.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -import "./BKCommon.sol"; -import "./interfaces/IBKRegistry.sol"; - -contract BKSwap is BKCommon { - address public bkRegistry; - mapping(address => bool) public isCaller; - - event ManagerCaller(address operator, address caller, bool isCaller); - event SetRegistry(address operator, address bkRegistry); - - constructor(address _bkRegistry, address _owner) { - bkRegistry = _bkRegistry; - emit SetRegistry(msg.sender, _bkRegistry); - _transferOwnership(_owner); - } - - function setRegistry(address _bkRegistry) external whenNotPaused onlyOwner { - bkRegistry = _bkRegistry; - emit SetRegistry(msg.sender, _bkRegistry); - } - - function managerCaller(address _caller, bool _isCaller) external onlyOwner { - isCaller[_caller] = _isCaller; - emit ManagerCaller(msg.sender, _caller, _isCaller); - } - - fallback() external payable whenNotPaused nonReentrant { - if(!isCaller[msg.sender]) { - revert InvalidCaller(); - } - - if (msg.sig.length != 4) { - revert InvalidMsgSig(); - } - - (address proxy, bool isLib) = IBKRegistry(bkRegistry).getFeature(msg.sig); - - (bool success, bytes memory resultData) = isLib - ? proxy.delegatecall(msg.data) - : proxy.call{value: msg.value}(msg.data); - - if (!success) { - _revertWithData(resultData); - } - } -} \ No newline at end of file diff --git a/contracts/BKSwapRouter.sol b/contracts/BKSwapRouter.sol deleted file mode 100644 index 63bdf7b..0000000 --- a/contracts/BKSwapRouter.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -import "./BKCommon.sol"; -import "./utils/TransferHelper.sol"; -import {BasicParams, AggregationParams, SwapType, OrderInfo} from "./interfaces/IBKStructsAndEnums.sol"; -import {IBKErrors} from "./interfaces/IBKErrors.sol"; - -contract BKSwapRouter is BKCommon { - address public immutable BKSWAP_V2; - - struct SwapParams { - address fromTokenAddress; - uint256 amountInTotal; - bytes data; - } - - constructor(address bkSwapAddress, address owner) { - BKSWAP_V2 = bkSwapAddress; - _transferOwnership(owner); - } - - function swap(SwapParams calldata swapParams) - external - payable - whenNotPaused - nonReentrant - { - if (!TransferHelper.isETH(swapParams.fromTokenAddress)) { - - TransferHelper.safeTransferFrom( - swapParams.fromTokenAddress, - msg.sender, - BKSWAP_V2, - swapParams.amountInTotal - ); - } else { - if (msg.value < swapParams.amountInTotal) { - revert IBKErrors.SwapEthBalanceNotEnough(); - } - } - - (bool success, bytes memory resultData) = BKSWAP_V2.call{ - value: msg.value - }(swapParams.data); - - if (!success) { - _revertWithData(resultData); - } - } -} diff --git a/contracts/features/AggregationFeature.sol b/contracts/features/AggregationFeature.sol deleted file mode 100644 index d103d36..0000000 --- a/contracts/features/AggregationFeature.sol +++ /dev/null @@ -1,327 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -import "../interfaces/IBKFees.sol"; -import "../interfaces/IBKRegistry.sol"; -import "../utils/TransferHelper.sol"; - -import { - BasicParams, - AggregationParams, - SwapType, - OrderInfo -} from "../interfaces/IBKStructsAndEnums.sol"; - -import { - IBKErrors -} from "../interfaces/IBKErrors.sol"; - -library AggregationFeature { - string public constant FEATURE_NAME = "BitKeep SOR: Aggregation Feature"; - string public constant FEATURE_VERSION = "1.0"; - - address public constant BK_FEES = 0xE4DA6f981a78b8b9edEfE4D7a955C04bA7e67D8D; - address public constant BK_REGISTRY = 0x9aFD2948F573DD8684347924eBcE1847D50621eD; - - bytes4 public constant FUNC_SWAP = bytes4(keccak256(bytes("swap(AggregationFeature.SwapDetail)"))); // 0x6a2b69f0 - - event BKSwapV2( - SwapType indexed swapType, - address indexed receiver, - uint feeAmount, - string featureName, - string featureVersion - ); - - event OrderInfoEvent( - bytes transferId, - uint dstChainId, - address sender, - address bridgeReceiver, - address tokenIn, - address desireToken, - uint amount - ); - - struct SwapDetail { - BasicParams basicParams; - AggregationParams aggregationParams; - OrderInfo orderInfo; - } - - function swap(SwapDetail calldata swapDetail) public { - if(!IBKRegistry(BK_REGISTRY).isCallTarget(FUNC_SWAP, swapDetail.aggregationParams.callTarget)) { - revert IBKErrors.IllegalCallTarget(); - } - - if(!IBKRegistry(BK_REGISTRY).isApproveTarget(FUNC_SWAP, swapDetail.aggregationParams.approveTarget)) { - revert IBKErrors.IllegalApproveTarget(); - } - - (address feeTo, address altcoinFeeTo, uint feeRate) = IBKFees(BK_FEES).getFeeTo(); - - if(swapDetail.basicParams.swapType > SwapType.WHITE_TO_TOKEN) { - revert IBKErrors.SwapTypeNotAvailable(); - } - - if(swapDetail.basicParams.swapType == SwapType.FREE) { - _swapForFree(swapDetail); - } else if(swapDetail.basicParams.swapType == SwapType.ETH_TOKEN) { - if(msg.value < swapDetail.basicParams.amountInForSwap) { - revert IBKErrors.SwapEthBalanceNotEnough(); - } - _swapEth2Token(swapDetail, payable(feeTo), feeRate); - } else { - _swapToken2Others(swapDetail, payable(feeTo), altcoinFeeTo, feeRate); - } - } - - function _swapForFree(SwapDetail calldata swapDetail) internal { - IBKFees(BK_FEES).checkIsSigner( - swapDetail.basicParams.signParams.nonceHash, - swapDetail.basicParams.signParams.signature - ); - - IERC20 fromToken = IERC20(swapDetail.basicParams.fromTokenAddress); - - bool toTokenIsETH = TransferHelper.isETH(swapDetail.basicParams.toTokenAddress); - - if(TransferHelper.isETH(swapDetail.basicParams.fromTokenAddress)) { - if(msg.value < swapDetail.basicParams.amountInForSwap) { - revert IBKErrors.SwapEthBalanceNotEnough(); - } - } else { - uint fromBalanceOfThis = fromToken.balanceOf(address(this)); - - if(fromBalanceOfThis < swapDetail.basicParams.amountInTotal) { - revert IBKErrors.BurnToMuch(); - } - - TransferHelper.approveMax( - fromToken, - swapDetail.aggregationParams.approveTarget, - swapDetail.basicParams.amountInTotal - ); - } - - uint balanceOfThis = - toTokenIsETH ? - address(this).balance : IERC20(swapDetail.basicParams.toTokenAddress).balanceOf(address(this)); - - (bool success, ) = swapDetail.aggregationParams.callTarget.call{value: msg.value}(swapDetail.aggregationParams.data); - _checkCallResult(success); - - uint balanceNow = - toTokenIsETH ? - address(this).balance : IERC20(swapDetail.basicParams.toTokenAddress).balanceOf(address(this)); - - if(toTokenIsETH) { - TransferHelper.safeTransferETH(swapDetail.basicParams.receiver, balanceNow - balanceOfThis); - } else { - TransferHelper.safeTransfer(swapDetail.basicParams.toTokenAddress, swapDetail.basicParams.receiver, balanceNow - balanceOfThis); - } - - emit BKSwapV2( - swapDetail.basicParams.swapType, - swapDetail.basicParams.receiver, - 0, - FEATURE_NAME, - FEATURE_VERSION - ); - - emit OrderInfoEvent( - swapDetail.orderInfo.transferId, - swapDetail.orderInfo.dstChainId, - msg.sender, - swapDetail.orderInfo.bridgeReceiver, - swapDetail.basicParams.fromTokenAddress, - swapDetail.orderInfo.desireToken, - balanceNow - balanceOfThis - ); - } - - function _swapEth2Token(SwapDetail calldata swapDetail, address payable _feeTo, uint _feeRate) internal { - IERC20 toToken = IERC20(swapDetail.basicParams.toTokenAddress); - - uint beforeBalanceOfToken = toToken.balanceOf(address(this)); - - uint feeAmount = swapDetail.basicParams.amountInTotal * _feeRate / 1e4; - TransferHelper.safeTransferETH(_feeTo, feeAmount); - - (bool success, ) = swapDetail.aggregationParams.callTarget.call{value: swapDetail.basicParams.amountInForSwap}(swapDetail.aggregationParams.data); - - _checkCallResult(success); - - uint afterBalanceOfToken = toToken.balanceOf(address(this)); - - TransferHelper.safeTransfer( - swapDetail.basicParams.toTokenAddress, - swapDetail.basicParams.receiver, - afterBalanceOfToken - beforeBalanceOfToken - ); - - emit BKSwapV2( - swapDetail.basicParams.swapType, - swapDetail.basicParams.receiver, - feeAmount, - FEATURE_NAME, - FEATURE_VERSION - ); - - emit OrderInfoEvent( - swapDetail.orderInfo.transferId, - swapDetail.orderInfo.dstChainId, - msg.sender, - swapDetail.orderInfo.bridgeReceiver, - swapDetail.basicParams.fromTokenAddress, - swapDetail.orderInfo.desireToken, - afterBalanceOfToken - beforeBalanceOfToken - ); - } - - function _swapToken2Others(SwapDetail calldata swapDetail, address feeTo, address altcoinFeeTo, uint feeRate) internal { - IERC20 fromToken = IERC20(swapDetail.basicParams.fromTokenAddress); - - uint balanceOfThis = fromToken.balanceOf(address(this)); - - if(balanceOfThis < swapDetail.basicParams.amountInTotal) { - revert IBKErrors.BurnToMuch(); - } - - TransferHelper.approveMax( - fromToken, - swapDetail.aggregationParams.approveTarget, - swapDetail.basicParams.amountInTotal - ); - - if(swapDetail.basicParams.swapType == SwapType.TOKEN_ETH) { - _swapToken2ETH(swapDetail, payable(feeTo), feeRate); - } else if(swapDetail.basicParams.swapType == SwapType.TOKEN_TO_WHITE) { - _swapToken2white(swapDetail, feeTo, feeRate); - } else { - _swapToken2token( - swapDetail, - swapDetail.basicParams.swapType == SwapType.TOKEN_TOKEN ? altcoinFeeTo : feeTo, - feeRate - ); - } - } - - function _swapToken2ETH(SwapDetail calldata swapDetail, address payable _feeTo, uint _feeRate) internal { - uint balanceBefore = address(this).balance; - uint feeAmount; - uint swappedAmount; - - (bool success, ) = swapDetail.aggregationParams.callTarget.call{value: 0}(swapDetail.aggregationParams.data); - _checkCallResult(success); - - swappedAmount = address(this).balance - balanceBefore; - - feeAmount = swappedAmount * _feeRate / 1e4; - TransferHelper.safeTransferETH(_feeTo, feeAmount); - - TransferHelper.safeTransferETH(swapDetail.basicParams.receiver, swappedAmount - feeAmount); - - emit BKSwapV2( - swapDetail.basicParams.swapType, - swapDetail.basicParams.receiver, - feeAmount, - FEATURE_NAME, - FEATURE_VERSION - ); - - emit OrderInfoEvent( - swapDetail.orderInfo.transferId, - swapDetail.orderInfo.dstChainId, - msg.sender, - swapDetail.orderInfo.bridgeReceiver, - swapDetail.basicParams.fromTokenAddress, - swapDetail.orderInfo.desireToken, - swappedAmount - feeAmount - ); - } - - function _swapToken2token(SwapDetail calldata swapDetail, address _feeTo, uint _feeRate) internal { - IERC20 toToken = IERC20(swapDetail.basicParams.toTokenAddress); - uint balanceBefore = toToken.balanceOf(address(this)); - uint feeAmount; - - feeAmount = swapDetail.basicParams.amountInTotal * _feeRate / 1e4; - TransferHelper.safeTransfer(swapDetail.basicParams.fromTokenAddress, _feeTo, feeAmount); - - (bool success, ) = swapDetail.aggregationParams.callTarget.call{value: 0}(swapDetail.aggregationParams.data); - _checkCallResult(success); - - uint balanceAfter = toToken.balanceOf(address(this)); - - TransferHelper.safeTransfer( - swapDetail.basicParams.toTokenAddress, - swapDetail.basicParams.receiver, - balanceAfter- balanceBefore - ); - - emit BKSwapV2( - swapDetail.basicParams.swapType, - swapDetail.basicParams.receiver, - feeAmount, - FEATURE_NAME, - FEATURE_VERSION - ); - - emit OrderInfoEvent( - swapDetail.orderInfo.transferId, - swapDetail.orderInfo.dstChainId, - msg.sender, - swapDetail.orderInfo.bridgeReceiver, - swapDetail.basicParams.fromTokenAddress, - swapDetail.orderInfo.desireToken, - balanceAfter- balanceBefore - ); - } - - function _swapToken2white(SwapDetail calldata swapDetail, address _feeTo, uint _feeRate) internal { - IERC20 toToken = IERC20(swapDetail.basicParams.toTokenAddress); - - uint balanceBefore = toToken.balanceOf(address(this)); - uint swappedAmount; - uint feeAmount; - - (bool success, ) = swapDetail.aggregationParams.callTarget.call{value: 0}(swapDetail.aggregationParams.data); - _checkCallResult(success); - - swappedAmount = toToken.balanceOf(address(this)) - balanceBefore; - - feeAmount = swappedAmount * _feeRate / 1e4; - TransferHelper.safeTransfer(swapDetail.basicParams.toTokenAddress, _feeTo, feeAmount); - - TransferHelper.safeTransfer(swapDetail.basicParams.toTokenAddress, swapDetail.basicParams.receiver, swappedAmount - feeAmount); - - emit BKSwapV2( - swapDetail.basicParams.swapType, - swapDetail.basicParams.receiver, - feeAmount, - FEATURE_NAME, - FEATURE_VERSION - ); - - emit OrderInfoEvent( - swapDetail.orderInfo.transferId, - swapDetail.orderInfo.dstChainId, - msg.sender, - swapDetail.orderInfo.bridgeReceiver, - swapDetail.basicParams.fromTokenAddress, - swapDetail.orderInfo.desireToken, - swappedAmount - feeAmount - ); - } - - function _checkCallResult(bool _success) internal pure { - if (!_success) { - // Copy revert reason from call - assembly { - returndatacopy(0, 0, returndatasize()) - revert(0, returndatasize()) - } - } - } -} \ No newline at end of file diff --git a/contracts/features/BridgeAggregationFeature.sol b/contracts/features/BridgeAggregationFeature.sol deleted file mode 100644 index 3d44770..0000000 --- a/contracts/features/BridgeAggregationFeature.sol +++ /dev/null @@ -1,252 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.18; - -import "../interfaces/IBKFees.sol"; -import "../interfaces/IBKRegistry.sol"; -import "../utils/TransferHelper.sol"; - -import {SignParams, AggregationParams} from "../interfaces/IBKStructsAndEnums.sol"; -import {IBKErrors} from "../interfaces/IBKErrors.sol"; - -library BridgeAggregationFeature { - string public constant FEATURE_NAME = - "BitKeep SOR: Bridge Aggregation Feature"; - string public constant FEATURE_VERSION = "1.0"; - - address public constant BK_FEES = - 0xE4DA6f981a78b8b9edEfE4D7a955C04bA7e67D8D; - address public constant BK_REGISTRY = - 0x9aFD2948F573DD8684347924eBcE1847D50621eD; - - bytes4 public constant FUNC_BRIDGE_AGG = - bytes4( - keccak256( - bytes("bridge_agg(BridgeAggregationFeature.BridgeDetail)") - ) - ); // 0xb0dce4dd - - event BridgeAgg( - BridgeType indexed bridgeType, - address fromTokenAddress, - address toTokenAddress, - address fromChainId, - address dstChainId, - uint256 amountInTotal, - uint256 amountInForSwap, - uint256 additionalFee, - address receiver, - uint256 minAmountOut, - uint256 feeAmount, - string featureName, - string featureVersion - ); - - enum BridgeType { - FREE, - ETH_OTHERS, - TOKEN_OTHERS - } - - struct BridgeBasicParams { - SignParams signParams; - BridgeType bridgeType; - bool feeTokenIsWhite; - address fromTokenAddress; - address toTokenAddress; - address fromChainId; - address dstChainId; - uint256 amountInTotal; - uint256 amountInForSwap; - uint256 additionalFee; - address receiver; - uint256 minAmountOut; - } - - struct BridgeDetail { - BridgeBasicParams basicParams; - AggregationParams aggregationParams; - } - - function bridge_agg(BridgeDetail calldata bridgeDetail) external { - if ( - !IBKRegistry(BK_REGISTRY).isCallTarget( - FUNC_BRIDGE_AGG, - bridgeDetail.aggregationParams.callTarget - ) - ) { - revert IBKErrors.IllegalCallTarget(); - } - - if ( - !IBKRegistry(BK_REGISTRY).isApproveTarget( - FUNC_BRIDGE_AGG, - bridgeDetail.aggregationParams.approveTarget - ) - ) { - revert IBKErrors.IllegalApproveTarget(); - } - - if (bridgeDetail.basicParams.bridgeType > BridgeType.TOKEN_OTHERS) { - revert IBKErrors.SwapTypeNotAvailable(); - } - - bool fromTokenIsETH = TransferHelper.isETH( - bridgeDetail.basicParams.fromTokenAddress - ); - - if (fromTokenIsETH) { - if (msg.value < bridgeDetail.basicParams.amountInTotal) { - revert IBKErrors.SwapEthBalanceNotEnough(); - } - } else { - if (msg.value < bridgeDetail.basicParams.additionalFee) { - revert IBKErrors.SwapEthBalanceNotEnough(); - } - } - - IBKFees(BK_FEES).checkIsSigner( - keccak256( - abi.encodePacked( - bridgeDetail.basicParams.signParams.nonceHash, - bridgeDetail.basicParams.amountInTotal, - bridgeDetail.basicParams.amountInForSwap, - bridgeDetail.basicParams.additionalFee - ) - ), - bridgeDetail.basicParams.signParams.signature - ); - - if (bridgeDetail.basicParams.bridgeType == BridgeType.FREE) { - if (fromTokenIsETH) { - _bridgeEth2Others(bridgeDetail, true, payable(address(0)), 0); - } else { - _bridgeToken2Others(bridgeDetail, true, address(0), 0); - } - } else { - (address feeTo, address altcoinFeeTo, uint256 feeRate) = IBKFees( - BK_FEES - ).getFeeTo(); - - if (bridgeDetail.basicParams.bridgeType == BridgeType.ETH_OTHERS) { - _bridgeEth2Others(bridgeDetail, false, payable(feeTo), feeRate); - } else { - if (bridgeDetail.basicParams.feeTokenIsWhite) { - _bridgeToken2Others(bridgeDetail, false, feeTo, feeRate); - } else { - _bridgeToken2Others( - bridgeDetail, - false, - altcoinFeeTo, - feeRate - ); - } - } - } - } - - function _bridgeEth2Others( - BridgeDetail calldata bridgeDetail, - bool _isFree, - address payable _feeTo, - uint256 _feeRate - ) internal { - uint256 feeAmount; - if (!_isFree) { - feeAmount = - ((bridgeDetail.basicParams.amountInTotal - - bridgeDetail.basicParams.additionalFee) * _feeRate) / - 1e4; - TransferHelper.safeTransferETH(_feeTo, feeAmount); - } - - if ( - bridgeDetail.basicParams.amountInForSwap != - bridgeDetail.basicParams.amountInTotal - - bridgeDetail.basicParams.additionalFee - - feeAmount - ) { - revert IBKErrors.SwapEthBalanceNotEnough(); - } - - (bool success, ) = bridgeDetail.aggregationParams.callTarget.call{ - value: bridgeDetail.basicParams.amountInForSwap + - bridgeDetail.basicParams.additionalFee - }(bridgeDetail.aggregationParams.data); - - _checkCallResult(success); - - _emitEvent(bridgeDetail, feeAmount); - } - - function _bridgeToken2Others( - BridgeDetail calldata bridgeDetail, - bool _isFree, - address _feeTo, - uint256 _feeRate - ) internal { - IERC20 fromToken = IERC20(bridgeDetail.basicParams.fromTokenAddress); - - TransferHelper.approveMax( - fromToken, - bridgeDetail.aggregationParams.approveTarget, - bridgeDetail.basicParams.amountInTotal - ); - - uint256 feeAmount; - if (!_isFree) { - feeAmount = - (bridgeDetail.basicParams.amountInTotal * _feeRate) / - 1e4; - TransferHelper.safeTransfer( - bridgeDetail.basicParams.fromTokenAddress, - _feeTo, - feeAmount - ); - } - - if ( - bridgeDetail.basicParams.amountInForSwap != - bridgeDetail.basicParams.amountInTotal - feeAmount - ) { - revert IBKErrors.SwapTokenBalanceNotEnough(); - } - - (bool success, ) = bridgeDetail.aggregationParams.callTarget.call{ - value: bridgeDetail.basicParams.additionalFee - }(bridgeDetail.aggregationParams.data); - - _checkCallResult(success); - - _emitEvent(bridgeDetail, feeAmount); - } - - function _emitEvent( - BridgeDetail calldata bridgeDetail, - uint256 feeAmount - ) internal { - emit BridgeAgg( - bridgeDetail.basicParams.bridgeType, - bridgeDetail.basicParams.fromTokenAddress, - bridgeDetail.basicParams.toTokenAddress, - bridgeDetail.basicParams.fromChainId, - bridgeDetail.basicParams.dstChainId, - bridgeDetail.basicParams.amountInTotal, - bridgeDetail.basicParams.amountInForSwap, - bridgeDetail.basicParams.additionalFee, - bridgeDetail.basicParams.receiver, - bridgeDetail.basicParams.minAmountOut, - feeAmount, - FEATURE_NAME, - FEATURE_VERSION - ); - } - - function _checkCallResult(bool _success) internal pure { - if (!_success) { - assembly { - returndatacopy(0, 0, returndatasize()) - revert(0, returndatasize()) - } - } - } -} diff --git a/contracts/features/IAggregationFeature.sol b/contracts/features/IAggregationFeature.sol deleted file mode 100644 index d9503a9..0000000 --- a/contracts/features/IAggregationFeature.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -import { - BasicParams, - AggregationParams, - SwapType, - OrderInfo -} from "../interfaces/IBKStructsAndEnums.sol"; - -interface IAggregationFeature { - event Swap( - SwapType indexed swapType, - address indexed receiver, - uint feeAmount, - string featureName - ); - - event OrderInfoEvent( - bytes transferId, - uint dstChainId, - address sender, - address bridgeReceiver, - address tokenIn, - address desireToken, - uint amount - ); - - struct SwapDetail { - BasicParams basicParams; - AggregationParams aggregationParams; - OrderInfo orderInfo; - } - - function swap(SwapDetail calldata swapDetail) external; -} \ No newline at end of file diff --git a/contracts/features/IBridgeAggregationFeature.sol b/contracts/features/IBridgeAggregationFeature.sol deleted file mode 100644 index f562f31..0000000 --- a/contracts/features/IBridgeAggregationFeature.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.18; - -import {SignParams, AggregationParams} from "../interfaces/IBKStructsAndEnums.sol"; - -interface IBridgeAggregationFeature { - - enum BridgeType { - FREE, - ETH_OTHERS, - TOKEN_OTHERS - } - - struct BridgeBasicParams { - SignParams signParams; // 签名信息,bridgeType为free类型需要 - BridgeType bridgeType; // bridge类型 - bool feeTokenIsWhite; // 收取手续费的token是不是白名单币种,服务端传参 - address fromTokenAddress; // 源链fromToken地址 - address toTokenAddress; // 目标链toToken地址 - uint256 fromChainId; // 源链chainId - uint256 dstChainId; // 目标链chainId - uint256 amountInTotal; // amountInTotal = amountInForSwap + additionalFee - uint256 amountInForSwap; // amountIn扣除手续费,服务端计算 - uint256 additionalFee; // 附加费用,作为交易附带的value传递,如果没有,传0 - address receiver; // 目标链兑换接收者 - uint256 minAmountOut; // toToken在目标链接收到的minAmountOut - } - - struct BridgeDetail { - BridgeBasicParams basicParams; - AggregationParams aggregationParams; - } - - function bridge_agg(BridgeDetail calldata bridgeDetail) external; -} \ No newline at end of file diff --git a/contracts/interfaces/IBKCommon.sol b/contracts/interfaces/IBKCommon.sol deleted file mode 100644 index 5263c8a..0000000 --- a/contracts/interfaces/IBKCommon.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -interface IBKCommon { - function setOperator(address[] calldata _operators, bool _isOperator) external; - - function pause() external; - - function unpause() external; - - function rescueETH(address recipient) external; - - function rescueERC20(address asset, address recipient) external; -} \ No newline at end of file diff --git a/contracts/interfaces/IBKErrors.sol b/contracts/interfaces/IBKErrors.sol deleted file mode 100644 index a32bcd7..0000000 --- a/contracts/interfaces/IBKErrors.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -interface IBKErrors { - error InvalidMsgSig(); - error InsufficientEtherSupplied(); - error FeatureNotExist(); - error FeatureInActive(); - error InvalidCaller(); - error InvalidSigner(); - error InvalidNonce(bytes32 signMsg); - error InvalidZeroAddress(); - error InvalidFeeRate(uint256 feeRate); - error SwapEthBalanceNotEnough(); - error SwapTokenBalanceNotEnough(); - error SwapTokenApproveNotEnough(); - error SwapInsuffenceOutPut(); - error SwapTypeNotAvailable(); - error BurnToMuch(); - error IllegalCallTarget(); - error IllegalApproveTarget(); - error InvalidSwapAddress(address); - error CallException(address); -} \ No newline at end of file diff --git a/contracts/interfaces/IBKFees.sol b/contracts/interfaces/IBKFees.sol deleted file mode 100644 index 795751e..0000000 --- a/contracts/interfaces/IBKFees.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -interface IBKFees { - function checkIsSigner(bytes32 _nonceHash, bytes calldata _signature) external; - - function setSigner(address _signer) external; - - function getSigner() external view returns(address); - - function setFeeTo ( - address payable _feeTo, - address payable _altcoinsFeeTo, - uint _feeRate - ) external; - - function getFeeTo () external view returns( - address payable _feeTo, - address payable _altcoinsFeeTo, - uint _feeRate - ); -} diff --git a/contracts/interfaces/IBKRegistry.sol b/contracts/interfaces/IBKRegistry.sol deleted file mode 100644 index d2b726c..0000000 --- a/contracts/interfaces/IBKRegistry.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -interface IBKRegistry { - function setFeature( bytes4 _methodId, address _proxy, bool _isLib, bool _isActive) external; - - function getFeature(bytes4 _methodId) external view returns(address proxy, bool isLib); - - function setCallTarget(bytes4 _methodId, address[] calldata _targets, bool _isEnable) external; - - function isCallTarget(bytes4 _methodId, address _target) external view returns(bool); - - function setApproveTarget(bytes4 _methodId, address[] calldata _targets, bool _isEnable) external; - - function isApproveTarget(bytes4 _methodId, address _target) external view returns(bool); -} diff --git a/contracts/interfaces/IBKStructsAndEnums.sol b/contracts/interfaces/IBKStructsAndEnums.sol deleted file mode 100644 index e114c53..0000000 --- a/contracts/interfaces/IBKStructsAndEnums.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -struct OrderInfo{ - bytes transferId; - uint dstChainId; - address desireToken; - address bridgeReceiver; -} - -enum SwapType { - FREE, - ETH_TOKEN, - TOKEN_ETH, - TOKEN_TOKEN, - TOKEN_TO_WHITE, - WHITE_TO_TOKEN -} - -struct SignParams { - bytes32 nonceHash; - bytes signature; -} - -struct BasicParams { - SignParams signParams; - SwapType swapType; - address fromTokenAddress; - address toTokenAddress; - uint amountInTotal; - uint amountInForSwap; - address receiver; - uint minAmountOut; -} - -struct AggregationParams { - address approveTarget; - address callTarget; - bytes data; -} \ No newline at end of file diff --git a/contracts/interfaces/IBKSwap.sol b/contracts/interfaces/IBKSwap.sol deleted file mode 100644 index 0f9eeae..0000000 --- a/contracts/interfaces/IBKSwap.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -interface IBKSwap { - function setRegistry(address _bkRegistry) external; - - function bkRegistry() view external returns (address); - - function managerCaller(address _caller, bool _isCaller) external; - - function isCaller(address _caller) view external returns(bool); -} diff --git a/contracts/interfaces/IBKSwapRouter.sol b/contracts/interfaces/IBKSwapRouter.sol deleted file mode 100644 index 0780d8e..0000000 --- a/contracts/interfaces/IBKSwapRouter.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -interface IBKSwapRouter { - struct SwapParams { - address fromTokenAddress; - uint256 amountInTotal; - bytes data; - } - - function swap(SwapParams calldata swapParams) external; -} \ No newline at end of file diff --git a/contracts/interfaces/wombat/IWombatRouter.sol b/contracts/interfaces/wombat/IWombatRouter.sol deleted file mode 100644 index 0e3e6af..0000000 --- a/contracts/interfaces/wombat/IWombatRouter.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -interface IWombatRouter { - function getAmountOut( - address[] calldata _tokenPath, - address[] calldata _poolPath, - int256 _amountIn - ) external view returns (uint256 amountOut, uint256[] memory haircuts); - - function swapExactTokensForTokens( - address[] calldata tokenPath, - address[] calldata poolPath, - uint256 amountIn, - uint256 minimumamountOut, - address to, - uint256 deadline - ) external returns(uint256 amountOut); -} diff --git a/contracts/utils/TransferHelper.sol b/contracts/utils/TransferHelper.sol deleted file mode 100644 index bcedf1a..0000000 --- a/contracts/utils/TransferHelper.sol +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.17; - -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; - -library TransferHelper { - using SafeERC20 for IERC20; - - /// @notice Transfers tokens from the targeted address to the given destination - /// @notice Errors with 'STF' if transfer fails - /// @param token The contract address of the token to be transferred - /// @param from The originating address from which the tokens will be transferred - /// @param to The destination address of the transfer - /// @param value The amount to be transferred - function safeTransferFrom( - address token, - address from, - address to, - uint256 value - ) internal { - (bool success, bytes memory data) = token.call( - abi.encodeWithSelector( - IERC20.transferFrom.selector, - from, - to, - value - ) - ); - require( - success && (data.length == 0 || abi.decode(data, (bool))), - "STF" - ); - } - - /// @notice Transfers tokens from msg.sender to a recipient - /// @dev Errors with ST if transfer fails - /// @param token The contract address of the token which will be transferred - /// @param to The recipient of the transfer - /// @param value The value of the transfer - function safeTransfer( - address token, - address to, - uint256 value - ) internal { - (bool success, bytes memory data) = token.call( - abi.encodeWithSelector(IERC20.transfer.selector, to, value) - ); - require( - success && (data.length == 0 || abi.decode(data, (bool))), - "ST" - ); - } - - /// @notice Approves the stipulated contract to spend the given allowance in the given token - /// @dev Errors with 'SA' if transfer fails - /// @param token The contract address of the token to be approved - /// @param to The target of the approval - /// @param value The amount of the given token the target will be allowed to spend - function safeApprove( - address token, - address to, - uint256 value - ) internal { - (bool success, bytes memory data) = token.call( - abi.encodeWithSelector(IERC20.approve.selector, to, value) - ); - require( - success && (data.length == 0 || abi.decode(data, (bool))), - "SA" - ); - } - - /// @notice Transfers ETH to the recipient address - /// @dev Fails with `STE` - /// @param to The destination of the transfer - /// @param value The value to be transferred - function safeTransferETH(address to, uint256 value) internal { - (bool success, ) = to.call{value: value}(new bytes(0)); - require(success, "STE"); - } - - function approveMax( - IERC20 _token, - address _spender, - uint256 _amount - ) internal { - uint256 allowance = _token.allowance(address(this), address(_spender)); - if (allowance < _amount) { - if (allowance > 0) { - _token.safeApprove(address(_spender), 0); - } - _token.safeApprove(address(_spender), type(uint256).max); - } - } - - function isETH(address _tokenAddress) internal pure returns (bool) { - return - (_tokenAddress == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) || - (_tokenAddress == 0x0000000000000000000000000000000000000000); - } -}