//SPDX-License-Identifier: Unlicense
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);
        }
    }
}
[{"inputs":[{"internalType":"address","name":"_bkRegistry","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BurnToMuch","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"CallException","type":"error"},{"inputs":[],"name":"FeatureInActive","type":"error"},{"inputs":[],"name":"FeatureNotExist","type":"error"},{"inputs":[],"name":"IllegalApproveTarget","type":"error"},{"inputs":[],"name":"IllegalCallTarget","type":"error"},{"inputs":[],"name":"InsufficientEtherSupplied","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[{"internalType":"uint256","name":"feeRate","type":"uint256"}],"name":"InvalidFeeRate","type":"error"},{"inputs":[],"name":"InvalidMsgSig","type":"error"},{"inputs":[{"internalType":"bytes32","name":"signMsg","type":"bytes32"}],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"InvalidSwapAddress","type":"error"},{"inputs":[],"name":"InvalidZeroAddress","type":"error"},{"inputs":[],"name":"SwapEthBalanceNotEnough","type":"error"},{"inputs":[],"name":"SwapInsuffenceOutPut","type":"error"},{"inputs":[],"name":"SwapTokenApproveNotEnough","type":"error"},{"inputs":[],"name":"SwapTokenBalanceNotEnough","type":"error"},{"inputs":[],"name":"SwapTypeNotAvailable","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bool","name":"isCaller","type":"bool"}],"name":"ManagerCaller","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"RescueERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RescueETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"isOperator","type":"bool"}],"name":"SetOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"address","name":"bkRegistry","type":"address"}],"name":"SetRegistry","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"bkRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_caller","type":"address"},{"internalType":"bool","name":"_isCaller","type":"bool"}],"name":"managerCaller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"rescueERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"rescueETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_operators","type":"address[]"},{"internalType":"bool","name":"_isOperator","type":"bool"}],"name":"setOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bkRegistry","type":"address"}],"name":"setRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]