编译器
0.8.18+commit.87f61d96
文件 1 的 21:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success,) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage)
internal
returns (bytes memory)
{
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage)
internal
returns (bytes memory)
{
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(address target, bytes memory data, string memory errorMessage)
internal
view
returns (bytes memory)
{
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(address target, bytes memory data, string memory errorMessage)
internal
returns (bytes memory)
{
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(bool success, bytes memory returndata, string memory errorMessage)
internal
pure
returns (bytes memory)
{
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 21:BKBridgeAccess.sol
pragma solidity ^0.8.18;
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 '@openzeppelin/contracts/utils/cryptography/ECDSA.sol';
import './libs/TransferHelper.sol';
import './interfaces/IBKBridgeAccess.sol';
import './interfaces/IBKBridgeErrors.sol';
contract BKBridgeAccess is IBKBridgeAccess, IBKBridgeErrors, Ownable, Pausable, ReentrancyGuard {
using ECDSA for bytes32;
using SafeERC20 for IERC20;
address public safe;
address public operator;
address public signer;
address public vault;
address public vaultToken;
mapping(address => bool) public isRelayer;
mapping(address => bool) public isRouter;
mapping(uint256 => uint256) private nonceBitmap;
event RescueETH(address recipient, uint256 amount);
event RescueERC20(address asset, address recipient, uint256 amount);
event SetSafe(address newSafe);
event SetOperator(address newOperator);
event SetSigner(address newSigner);
event SetVault(address newVault);
event SetVaultToken(address newValutToken);
event SetRelayers(address[] relayers, bool isTrue);
event SetRouters(address[] routers, bool isTrue);
modifier onlyOperator() {
_checkOperator();
_;
}
modifier onlySender(address _orderSender) {
_checkSender(_orderSender);
_;
}
modifier onlyRelayer() {
_checkRelayer();
_;
}
function setAccess(AccessType _accessType, bytes calldata _inputs) external onlyOwner {
if (_accessType > AccessType.SET_ROUTERS) {
revert AccessTypeNotAvailable();
}
if (_accessType <= AccessType.SET_VAULT_TOKEN) {
address addr = abi.decode(_inputs, (address));
_checkZero(addr);
if (_accessType == AccessType.SET_SAFE) {
safe = addr;
emit SetSafe(addr);
} else if (_accessType == AccessType.SET_OPERATOR) {
operator = addr;
emit SetOperator(addr);
} else if (_accessType == AccessType.SET_SINGER) {
signer = addr;
emit SetSigner(addr);
} else if (_accessType == AccessType.SET_VAULT) {
vault = addr;
emit SetVault(addr);
} else if (_accessType == AccessType.SET_VAULT_TOKEN) {
vaultToken = addr;
emit SetVaultToken(addr);
}
} else {
(address[] memory addrs, bool isTrue) = abi.decode(_inputs, (address[], bool));
bool isSetRelayer = _accessType == AccessType.SET_RELAYERS;
uint256 length = addrs.length;
for (uint256 i = 0; i < length;) {
address addr = addrs[i];
_checkZero(addr);
if (isSetRelayer) {
isRelayer[addr] = isTrue;
} else {
isRouter[addr] = isTrue;
}
unchecked {
++i;
}
}
if (isSetRelayer) {
emit SetRelayers(addrs, isTrue);
} else {
emit SetRouters(addrs, isTrue);
}
}
}
function checkBridgeReady() external view returns (bool) {
if (safe == address(0)) {
revert NotSafe();
} else if (operator == address(0)) {
revert NotOperator();
} else if (signer == address(0)) {
revert NotSigner();
} else if (vault == address(0)) {
revert NotVault();
} else if (vaultToken == address(0)) {
revert NotVaultToken();
}
return true;
}
function pause() external onlyOperator {
_pause();
}
function unpause() external onlyOperator {
_unpause();
}
function rescueERC20(address asset) external onlyOperator {
_checkZero(safe);
uint256 amount = IERC20(asset).balanceOf(address(this));
TransferHelper.safeTransfer(asset, safe, amount);
emit RescueERC20(asset, safe, amount);
}
function rescueETH() external onlyOperator {
_checkZero(safe);
uint256 amount = address(this).balance;
TransferHelper.safeTransferETH(safe, amount);
emit RescueETH(safe, amount);
}
function _checkOperator() internal view {
if (msg.sender != operator) {
revert NotOperator();
}
}
function _checkSender(address orderSender) internal view {
if (msg.sender != orderSender) {
revert NotSender();
}
}
function _checkRelayer() internal view {
if (!isRelayer[msg.sender]) {
revert NotRelayer();
}
}
function _checkZero(address _address) internal pure {
if (_address == address(0)) {
revert InvalidAddress();
}
}
function _checkVaultToken(address _vaultToken) internal view {
if (_vaultToken != vaultToken) {
revert NotVaultToken();
}
}
function _checkVaultReceiver(address _vaultReceiver) internal view {
if (_vaultReceiver != vault) {
revert NotVault();
}
}
function _checkSwapReceiver(address _targetReceiver, address _swapReceiver) internal pure {
if (_targetReceiver != _swapReceiver) {
revert SwapReceiverMisMatch();
}
}
function _checkRouter(address _router) internal view {
if (!isRouter[_router]) {
revert NotRouter();
}
}
function _checkSigner(uint256 _nonce, bytes calldata _signature, bytes32 _transferId, uint256 _dstChainId) internal {
_useUnorderedNonce(_nonce);
bytes32 msgHash = keccak256(abi.encodePacked(_nonce, block.chainid, address(this), msg.sender, _transferId, _dstChainId));
bytes32 finalMsgHash = msgHash.toEthSignedMessageHash();
address signer_ = finalMsgHash.recover(_signature);
if (signer_ != signer) {
revert NotSigner();
}
}
function _useUnorderedNonce(uint256 nonce) internal {
(uint256 wordPos, uint256 bitPos) = bitmapPositions(nonce);
uint256 bit = 1 << bitPos;
uint256 flipped = nonceBitmap[wordPos] ^= bit;
if (flipped & bit == 0) revert InvalidNonce();
}
function bitmapPositions(uint256 nonce) internal pure returns (uint256 wordPos, uint256 bitPos) {
wordPos = uint248(nonce >> 8);
bitPos = uint8(nonce);
}
}
文件 3 的 21:BKBridgeHandler.sol
pragma solidity ^0.8.18;
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '../interfaces/swap/IBKSwap.sol';
import '../interfaces/swap/IBKSwapRouter.sol';
import './TransferHelper.sol';
import './BKBridgeKey.sol';
import '../interfaces/IBKBridgeErrors.sol';
import {OrderInfo, SignInfo, SwapV1Info, SwapV2Info, HandlerCallBack} from '../interfaces/IBKBridgeParams.sol';
library BKBridgeHandler {
using SafeERC20 for IERC20;
uint256 private constant _INEXIST = 0;
uint256 private constant _SEND = 1;
uint256 private constant _RELAY = 2;
uint256 private constant _CANCEL = 3;
uint256 private constant _REFUND = 4;
function send(
OrderInfo calldata _orderInfo,
mapping(bytes32 => uint256) storage orderStatus,
mapping(bytes32 => uint256) storage orderAmount
) external returns (HandlerCallBack memory callback) {
bytes32 key = BKBridgeKey.keyOf(_orderInfo);
if (orderStatus[key] != _INEXIST) {
revert IBKBridgeErrors.OrderAlreadyExist();
}
IERC20 iVaultToken = IERC20(_orderInfo.srcToken);
uint256 vaultBeforeBalance = iVaultToken.balanceOf(_orderInfo.vaultReceiver);
orderAmount[key] = _orderInfo.amount;
orderStatus[key] = _SEND;
TransferHelper.safeTransferFrom(_orderInfo.srcToken, msg.sender, _orderInfo.vaultReceiver, _orderInfo.amount);
if (iVaultToken.balanceOf(_orderInfo.vaultReceiver) - vaultBeforeBalance != _orderInfo.amount) {
revert IBKBridgeErrors.WrongVaultReceiveToken();
}
callback.amount = _orderInfo.amount;
callback.status = _SEND;
}
function sendV1(
OrderInfo calldata _orderInfo,
SwapV1Info calldata _swapV1Info,
mapping(bytes32 => uint256) storage orderStatus,
mapping(bytes32 => uint256) storage orderAmount
) external returns (HandlerCallBack memory callback) {
address swapTokenOut = _swapV1Info.path[_swapV1Info.path.length - 1];
bytes32 key = BKBridgeKey.keyOf(_orderInfo);
if (orderStatus[key] != _INEXIST) {
revert IBKBridgeErrors.OrderAlreadyExist();
}
IERC20 iSwapTokenOut = IERC20(swapTokenOut);
uint256 vaultBeforeBalance = iSwapTokenOut.balanceOf(_orderInfo.vaultReceiver);
orderStatus[key] = _SEND;
_bridgeForSwapV1(_swapV1Info);
uint256 valutTokenAmount = iSwapTokenOut.balanceOf(_orderInfo.vaultReceiver) - vaultBeforeBalance;
if (valutTokenAmount < _swapV1Info.minAmountOut) {
revert IBKBridgeErrors.WrongVaultReceiveToken();
}
orderAmount[key] = valutTokenAmount;
callback.amount = valutTokenAmount;
callback.status = _SEND;
}
function sendV2(
OrderInfo calldata _orderInfo,
SwapV2Info calldata _swapV2Info,
mapping(bytes32 => uint256) storage orderStatus,
mapping(bytes32 => uint256) storage orderAmount
) external returns (HandlerCallBack memory callback) {
bytes32 key = BKBridgeKey.keyOf(_orderInfo);
if (orderStatus[key] != _INEXIST) {
revert IBKBridgeErrors.OrderAlreadyExist();
}
IERC20 iSwapTokenOut = IERC20(_swapV2Info.toTokenAddress);
uint256 vaultBeforeBalance = iSwapTokenOut.balanceOf(_orderInfo.vaultReceiver);
orderStatus[key] = _SEND;
_bridgeForSwapV2(_swapV2Info);
uint256 valutTokenAmount = iSwapTokenOut.balanceOf(_orderInfo.vaultReceiver) - vaultBeforeBalance;
if (valutTokenAmount < _swapV2Info.minAmountOut) {
revert IBKBridgeErrors.WrongVaultReceiveToken();
}
orderAmount[key] = valutTokenAmount;
callback.amount = valutTokenAmount;
callback.status = _SEND;
}
function relay(OrderInfo calldata _orderInfo, uint256 _relayAmount, mapping(bytes32 => uint256) storage orderStatus)
external
returns (HandlerCallBack memory callback)
{
bytes32 key = BKBridgeKey.keyOf(_orderInfo);
if (orderStatus[key] != _INEXIST) {
revert IBKBridgeErrors.OrderAlreadyExist();
}
IERC20 iVaultToken = IERC20(_orderInfo.dstToken);
uint256 vaultBeforeBalance = iVaultToken.balanceOf(msg.sender);
orderStatus[key] = _RELAY;
TransferHelper.safeTransferFrom(_orderInfo.dstToken, msg.sender, _orderInfo.receiver, _relayAmount);
if (vaultBeforeBalance - iVaultToken.balanceOf(msg.sender) != _relayAmount) {
revert IBKBridgeErrors.WrongRelayAmount();
}
callback.amount = _relayAmount;
callback.status = _RELAY;
}
function relayV1(
OrderInfo calldata _orderInfo,
SwapV1Info calldata _swapV1Info,
uint256 _relayAmount,
mapping(bytes32 => uint256) storage orderStatus
) external returns (HandlerCallBack memory callback) {
address swapTokenIn = _swapV1Info.path[0];
bytes32 key = BKBridgeKey.keyOf(_orderInfo);
if (orderStatus[key] != _INEXIST) {
revert IBKBridgeErrors.OrderAlreadyExist();
}
IERC20 iSwapTokenIn = IERC20(swapTokenIn);
uint256 vaultBeforeBalance = iSwapTokenIn.balanceOf(msg.sender);
address SwapTokenOutAddress = _swapV1Info.path[_swapV1Info.path.length - 1];
uint256 receiverBeforeBalance;
if(TransferHelper.isETH(SwapTokenOutAddress)) {
receiverBeforeBalance = _orderInfo.receiver.balance;
} else {
receiverBeforeBalance = IERC20(SwapTokenOutAddress).balanceOf(_orderInfo.receiver);
}
orderStatus[key] = _RELAY;
_bridgeForSwapV1(_swapV1Info);
uint256 valutTokenAmount = vaultBeforeBalance - iSwapTokenIn.balanceOf(msg.sender);
if (_relayAmount != valutTokenAmount) {
revert IBKBridgeErrors.WrongRelayAmount();
}
if(TransferHelper.isETH(SwapTokenOutAddress)) {
if ((_orderInfo.receiver.balance - receiverBeforeBalance) < _swapV1Info.minAmountOut) {
revert IBKBridgeErrors.SwapInsuffenceOutPut();
}
} else {
if ((IERC20(SwapTokenOutAddress).balanceOf(_orderInfo.receiver) - receiverBeforeBalance) < _swapV1Info.minAmountOut) {
revert IBKBridgeErrors.SwapInsuffenceOutPut();
}
}
callback.amount = _relayAmount;
callback.status = _RELAY;
}
function relayV2(
OrderInfo calldata _orderInfo,
SwapV2Info calldata _swapV2Info,
uint256 _relayAmount,
mapping(bytes32 => uint256) storage orderStatus
) external returns (HandlerCallBack memory callback) {
bytes32 key = BKBridgeKey.keyOf(_orderInfo);
if (orderStatus[key] != _INEXIST) {
revert IBKBridgeErrors.OrderAlreadyExist();
}
IERC20 iSwapTokenIn = IERC20(_swapV2Info.fromTokenAddress);
uint256 vaultBeforeBalance = iSwapTokenIn.balanceOf(msg.sender);
address SwapTokenOutAddress = _swapV2Info.toTokenAddress;
uint256 receiverBeforeBalance;
if(TransferHelper.isETH(SwapTokenOutAddress)) {
receiverBeforeBalance = _orderInfo.receiver.balance;
} else {
receiverBeforeBalance = IERC20(SwapTokenOutAddress).balanceOf(_orderInfo.receiver);
}
orderStatus[key] = _RELAY;
_bridgeForSwapV2(_swapV2Info);
uint256 valutTokenAmount = vaultBeforeBalance - iSwapTokenIn.balanceOf(msg.sender);
if (_relayAmount != valutTokenAmount) {
revert IBKBridgeErrors.WrongRelayAmount();
}
if(TransferHelper.isETH(SwapTokenOutAddress)) {
if ((_orderInfo.receiver.balance - receiverBeforeBalance) < _swapV2Info.minAmountOut) {
revert IBKBridgeErrors.SwapInsuffenceOutPut();
}
} else {
if ((IERC20(SwapTokenOutAddress).balanceOf(_orderInfo.receiver) - receiverBeforeBalance) < _swapV2Info.minAmountOut) {
revert IBKBridgeErrors.SwapInsuffenceOutPut();
}
}
callback.amount = _relayAmount;
callback.status = _RELAY;
}
function cancel(OrderInfo calldata _orderInfo, mapping(bytes32 => uint256) storage orderStatus)
external
returns (HandlerCallBack memory callback)
{
bytes32 key = BKBridgeKey.keyOf(_orderInfo);
if (orderStatus[key] != _INEXIST) {
revert IBKBridgeErrors.OrderAlreadyExist();
}
orderStatus[key] = _CANCEL;
callback.amount = 0;
callback.status = _CANCEL;
}
function refund(
OrderInfo calldata _orderInfo,
uint256 _refundAmount,
address _vaultToken,
mapping(bytes32 => uint256) storage orderStatus,
mapping(bytes32 => uint256) storage orderAmount
) external returns (HandlerCallBack memory callback) {
bytes32 key = BKBridgeKey.keyOf(_orderInfo);
if (orderStatus[key] != _SEND) {
revert IBKBridgeErrors.OrderNotSend();
}
if (_refundAmount > orderAmount[key]) {
revert IBKBridgeErrors.WrongRefundAmount();
}
orderAmount[key] = 0;
orderStatus[key] = _REFUND;
TransferHelper.safeTransferFrom(_vaultToken, msg.sender, _orderInfo.sender, _refundAmount);
callback.amount = _refundAmount;
callback.status = _REFUND;
}
function _bridgeForSwapV1(SwapV1Info calldata _swapV1Info) internal {
address swapTokenIn = _swapV1Info.path[0];
if (TransferHelper.isETH(swapTokenIn)) {
if (msg.value < _swapV1Info.amountIn) {
revert IBKBridgeErrors.EthBalanceNotEnough();
}
} else {
TransferHelper.safeTransferFrom(swapTokenIn, msg.sender, address(this), _swapV1Info.amountIn);
TransferHelper.approveMax(IERC20(swapTokenIn), _swapV1Info.bkSwapV1Router, _swapV1Info.amountIn);
}
IBKSwap(_swapV1Info.bkSwapV1Router).swap{value: msg.value}(
payable(_swapV1Info.handlerAddress),
_swapV1Info.router,
_swapV1Info.path,
_swapV1Info.poolFee,
_swapV1Info.amountIn,
_swapV1Info.minAmountOut,
_swapV1Info.to
);
}
function _bridgeForSwapV2(SwapV2Info calldata _swapV2Info) internal {
address swapTokenIn = _swapV2Info.fromTokenAddress;
if (TransferHelper.isETH(swapTokenIn)) {
if (msg.value < _swapV2Info.amountInTotal) {
revert IBKBridgeErrors.EthBalanceNotEnough();
}
} else {
TransferHelper.safeTransferFrom(swapTokenIn, msg.sender, address(this), _swapV2Info.amountInTotal);
TransferHelper.approveMax(IERC20(swapTokenIn), _swapV2Info.bkSwapV2Router, _swapV2Info.amountInTotal);
}
IBKSwapRouter(_swapV2Info.bkSwapV2Router).swap{value: msg.value}(
IBKSwapRouter.SwapParams(_swapV2Info.fromTokenAddress, _swapV2Info.amountInTotal, _swapV2Info.data)
);
}
}
文件 4 的 21:BKBridgeKey.sol
pragma solidity ^0.8.18;
import {OrderInfo} from '../interfaces/IBKBridgeParams.sol';
library BKBridgeKey {
bytes16 internal constant BRIDGE_SALT0 = 'BitKeep bridge';
bytes16 internal constant BRIDGE_SALT1 = 'Version 1.0.0';
function keyOf(OrderInfo calldata _orderInfo) internal pure returns (bytes32 key) {
key = keccak256(
abi.encodePacked(
_orderInfo.transferId,
_orderInfo.vaultReceiver,
_orderInfo.sender,
_orderInfo.receiver,
_orderInfo.srcToken,
BRIDGE_SALT0,
_orderInfo.dstToken,
_orderInfo.srcChainId,
_orderInfo.dstChainId,
BRIDGE_SALT1,
_orderInfo.amount,
_orderInfo.timestamp
)
);
}
}
文件 5 的 21:BKBridgeRouter.sol
pragma solidity ^0.8.18;
import './libs/BKBridgeHandler.sol';
import './interfaces/IBKBridgeRouter.sol';
import './BKBridgeAccess.sol';
contract BKBridgeRouter is IBKBridgeRouter, BKBridgeAccess {
mapping(bytes32 => uint256) public orderStatus;
mapping(bytes32 => uint256) public orderAmount;
event BKBridge(
uint256 indexed orderStatus,
bytes32 indexed transferId,
address vaultReceiver,
address sender,
address receiver,
address srcToken,
address dstToken,
uint256 srcChainId,
uint256 dstChainId,
uint256 amount,
uint256 timestamp
);
constructor(address _owner) BKBridgeAccess() {
_checkZero(_owner);
_transferOwnership(_owner);
}
receive() external payable {}
function send(SignInfo calldata _signInfo, OrderInfo calldata _orderInfo)
external
payable
whenNotPaused
nonReentrant
onlySender(_orderInfo.sender)
{
_checkSigner(_signInfo.nonce, _signInfo.signature, _orderInfo.transferId, _orderInfo.dstChainId);
_checkVaultReceiver(_orderInfo.vaultReceiver);
_checkVaultToken(_orderInfo.srcToken);
HandlerCallBack memory _callback = BKBridgeHandler.send(_orderInfo, orderStatus, orderAmount);
_emitEvent(_orderInfo, _callback);
}
function sendV1(SignInfo calldata _signInfo, OrderInfo calldata _orderInfo, SwapV1Info calldata _swapV1Info)
external
payable
whenNotPaused
nonReentrant
onlySender(_orderInfo.sender)
{
_checkSigner(_signInfo.nonce, _signInfo.signature, _orderInfo.transferId, _orderInfo.dstChainId);
_checkVaultReceiver(_orderInfo.vaultReceiver);
_checkVaultToken(_swapV1Info.path[_swapV1Info.path.length - 1]);
_checkRouter(_swapV1Info.bkSwapV1Router);
_checkSwapReceiver(vault, _swapV1Info.to);
HandlerCallBack memory _callback = BKBridgeHandler.sendV1(_orderInfo, _swapV1Info, orderStatus, orderAmount);
_emitEvent(_orderInfo, _callback);
}
function sendV2(SignInfo calldata _signInfo, OrderInfo calldata _orderInfo, SwapV2Info calldata _swapV2Info)
external
payable
whenNotPaused
nonReentrant
onlySender(_orderInfo.sender)
{
_checkSigner(_signInfo.nonce, _signInfo.signature, _orderInfo.transferId, _orderInfo.dstChainId);
_checkVaultReceiver(_orderInfo.vaultReceiver);
_checkVaultToken(_swapV2Info.toTokenAddress);
_checkRouter(_swapV2Info.bkSwapV2Router);
_checkSwapReceiver(vault, _swapV2Info.to);
HandlerCallBack memory _callback = BKBridgeHandler.sendV2(_orderInfo, _swapV2Info, orderStatus, orderAmount);
_emitEvent(_orderInfo, _callback);
}
function relay(SignInfo calldata _signInfo, OrderInfo calldata _orderInfo, uint256 _relayAmount)
external
payable
whenNotPaused
nonReentrant
onlyRelayer
{
_checkSigner(_signInfo.nonce, _signInfo.signature, _orderInfo.transferId, _orderInfo.dstChainId);
_checkVaultReceiver(_orderInfo.vaultReceiver);
_checkVaultToken(_orderInfo.dstToken);
HandlerCallBack memory _callback = BKBridgeHandler.relay(_orderInfo, _relayAmount, orderStatus);
_emitEvent(_orderInfo, _callback);
}
function relayV1(
SignInfo calldata _signInfo,
OrderInfo calldata _orderInfo,
SwapV1Info calldata _swapV1Info,
uint256 _relayAmount
) external payable whenNotPaused nonReentrant onlyRelayer {
_checkSigner(_signInfo.nonce, _signInfo.signature, _orderInfo.transferId, _orderInfo.dstChainId);
_checkVaultReceiver(_orderInfo.vaultReceiver);
_checkVaultToken(_swapV1Info.path[0]);
_checkRouter(_swapV1Info.bkSwapV1Router);
_checkSwapReceiver(_orderInfo.receiver, _swapV1Info.to);
HandlerCallBack memory _callback = BKBridgeHandler.relayV1(_orderInfo, _swapV1Info, _relayAmount, orderStatus);
_emitEvent(_orderInfo, _callback);
}
function relayV2(
SignInfo calldata _signInfo,
OrderInfo calldata _orderInfo,
SwapV2Info calldata _swapV2Info,
uint256 _relayAmount
) external payable whenNotPaused nonReentrant onlyRelayer {
_checkSigner(_signInfo.nonce, _signInfo.signature, _orderInfo.transferId, _orderInfo.dstChainId);
_checkVaultReceiver(_orderInfo.vaultReceiver);
_checkVaultToken(_swapV2Info.fromTokenAddress);
_checkRouter(_swapV2Info.bkSwapV2Router);
_checkSwapReceiver(_orderInfo.receiver, _swapV2Info.to);
HandlerCallBack memory _callback = BKBridgeHandler.relayV2(_orderInfo, _swapV2Info, _relayAmount, orderStatus);
_emitEvent(_orderInfo, _callback);
}
function cancel(SignInfo calldata _signInfo, OrderInfo calldata _orderInfo)
external
payable
whenNotPaused
nonReentrant
onlyRelayer
{
_checkSigner(_signInfo.nonce, _signInfo.signature, _orderInfo.transferId, _orderInfo.dstChainId);
HandlerCallBack memory _callback = BKBridgeHandler.cancel(_orderInfo, orderStatus);
_emitEvent(_orderInfo, _callback);
}
function refund(SignInfo calldata _signInfo, OrderInfo calldata _orderInfo, uint256 _refundAmount)
external
payable
whenNotPaused
nonReentrant
onlyRelayer
{
_checkSigner(_signInfo.nonce, _signInfo.signature, _orderInfo.transferId, _orderInfo.dstChainId);
HandlerCallBack memory _callback =
BKBridgeHandler.refund(_orderInfo, _refundAmount, vaultToken, orderStatus, orderAmount);
_emitEvent(_orderInfo, _callback);
}
function _emitEvent(OrderInfo calldata _orderInfo, HandlerCallBack memory _callback) internal {
emit BKBridge(
_callback.status,
_orderInfo.transferId,
_orderInfo.vaultReceiver,
_orderInfo.sender,
_orderInfo.receiver,
_orderInfo.srcToken,
_orderInfo.dstToken,
block.chainid,
_orderInfo.dstChainId,
_callback.amount,
_orderInfo.timestamp
);
}
}
文件 6 的 21:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 7 的 21:ECDSA.sol
pragma solidity ^0.8.0;
import "../Strings.sol";
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return;
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}
文件 8 的 21:IBKBridgeAccess.sol
pragma solidity ^0.8.18;
import {AccessType} from './IBKBridgeParams.sol';
interface IBKBridgeAccess {
function setAccess(AccessType _accessType, bytes calldata _inputs) external;
function checkBridgeReady() external view returns (bool);
function pause() external;
function unpause() external;
function rescueETH() external;
function rescueERC20(address asset) external;
}
文件 9 的 21:IBKBridgeErrors.sol
pragma solidity ^0.8.18;
interface IBKBridgeErrors {
error AccessTypeNotAvailable();
error TransferFailed();
error InvalidAddress();
error InvalidNonce();
error NotSafe();
error NotOperator();
error NotSigner();
error NotVault();
error NotVaultToken();
error NotSender();
error NotRelayer();
error NotRouter();
error OrderAlreadyExist();
error OrderNotSend();
error OrderAlreadySend();
error EthBalanceNotEnough();
error WrongVaultReceiveToken();
error WrongRefundAmount();
error WrongRelayAmount();
error SwapInsuffenceOutPut();
error SwapReceiverMisMatch();
}
文件 10 的 21:IBKBridgeParams.sol
pragma solidity ^0.8.18;
enum AccessType {
SET_SAFE,
SET_OPERATOR,
SET_SINGER,
SET_VAULT,
SET_VAULT_TOKEN,
SET_RELAYERS,
SET_ROUTERS
}
struct SignInfo {
uint256 nonce;
bytes signature;
}
struct OrderInfo {
address vaultReceiver;
bytes32 transferId;
address sender;
address receiver;
address srcToken;
address dstToken;
uint256 srcChainId;
uint256 dstChainId;
uint256 amount;
uint256 timestamp;
}
struct SwapV1Info {
address bkSwapV1Router;
address handlerAddress;
address router;
address[] path;
uint24[] poolFee;
uint256 amountIn;
uint256 minAmountOut;
address to;
}
struct SwapV2Info {
address bkSwapV2Router;
address fromTokenAddress;
address toTokenAddress;
address to;
uint256 amountInTotal;
uint256 minAmountOut;
bytes data;
}
struct HandlerCallBack {
uint256 amount;
uint256 status;
}
文件 11 的 21:IBKBridgeRouter.sol
pragma solidity ^0.8.18;
import {SignInfo, OrderInfo, SwapV1Info, SwapV2Info, HandlerCallBack} from './IBKBridgeParams.sol';
interface IBKBridgeRouter {
function orderStatus(bytes32 _key) external view returns (uint256);
function orderAmount(bytes32 _key) external view returns (uint256);
function send(SignInfo calldata _signInfo, OrderInfo calldata _orderInfo) external payable;
function sendV1(SignInfo calldata _signInfo, OrderInfo calldata _orderInfo, SwapV1Info calldata _swapV1Info)
external
payable;
function sendV2(SignInfo calldata _signInfo, OrderInfo calldata _orderInfo, SwapV2Info calldata _swapV2Info)
external
payable;
function relay(SignInfo calldata _signInfo, OrderInfo calldata _orderInfo, uint256 _relayAmount) external payable;
function relayV1(
SignInfo calldata _signInfo,
OrderInfo calldata _orderInfo,
SwapV1Info calldata _swapV1Info,
uint256 _relayAmount
) external payable;
function relayV2(
SignInfo calldata _signInfo,
OrderInfo calldata _orderInfo,
SwapV2Info calldata _swapV2Info,
uint256 _relayAmount
) external payable;
function cancel(SignInfo calldata _signInfo, OrderInfo calldata _orderInfo) external payable;
function refund(SignInfo calldata _signInfo, OrderInfo calldata _orderInfo, uint256 _refundAmount)
external
payable;
}
文件 12 的 21:IBKSwap.sol
pragma solidity ^0.8.17;
interface IBKSwap {
function swap(
address payable _handlerAddress,
address _router,
address[] memory _path,
uint24[] memory _poolFee,
uint256 _amountIn,
uint256 _minAmountOut,
address _to
) external payable returns (uint256);
}
文件 13 的 21:IBKSwapRouter.sol
pragma solidity ^0.8.17;
interface IBKSwapRouter {
struct SwapParams {
address fromTokenAddress;
uint256 amountInTotal;
bytes data;
}
function swap(SwapParams calldata swapParams) external payable;
}
文件 14 的 21:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 15 的 21:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 16 的 21:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_paused = false;
}
modifier whenNotPaused() {
_requireNotPaused();
_;
}
modifier whenPaused() {
_requirePaused();
_;
}
function paused() public view virtual returns (bool) {
return _paused;
}
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 17 的 21:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 18 的 21:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 19 的 21:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
文件 20 的 21:TransferHelper.sol
pragma solidity ^0.8.18;
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
library TransferHelper {
using SafeERC20 for IERC20;
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');
}
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');
}
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');
}
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);
}
}
文件 21 的 21:draft-IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
{
"compilationTarget": {
"contracts/BKBridgeRouter.sol": "BKBridgeRouter"
},
"evmVersion": "paris",
"libraries": {
"contracts/libs/BKBridgeHandler.sol:BKBridgeHandler": "0xa5237a040ee649a4f670102fc6aab87c235b6428"
},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessTypeNotAvailable","type":"error"},{"inputs":[],"name":"EthBalanceNotEnough","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"NotOperator","type":"error"},{"inputs":[],"name":"NotRelayer","type":"error"},{"inputs":[],"name":"NotRouter","type":"error"},{"inputs":[],"name":"NotSafe","type":"error"},{"inputs":[],"name":"NotSender","type":"error"},{"inputs":[],"name":"NotSigner","type":"error"},{"inputs":[],"name":"NotVault","type":"error"},{"inputs":[],"name":"NotVaultToken","type":"error"},{"inputs":[],"name":"OrderAlreadyExist","type":"error"},{"inputs":[],"name":"OrderAlreadySend","type":"error"},{"inputs":[],"name":"OrderNotSend","type":"error"},{"inputs":[],"name":"SwapInsuffenceOutPut","type":"error"},{"inputs":[],"name":"SwapReceiverMisMatch","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"WrongRefundAmount","type":"error"},{"inputs":[],"name":"WrongRelayAmount","type":"error"},{"inputs":[],"name":"WrongVaultReceiveToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"orderStatus","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"transferId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"vaultReceiver","type":"address"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"srcToken","type":"address"},{"indexed":false,"internalType":"address","name":"dstToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"srcChainId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dstChainId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"BKBridge","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":false,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RescueERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"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":"newOperator","type":"address"}],"name":"SetOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"relayers","type":"address[]"},{"indexed":false,"internalType":"bool","name":"isTrue","type":"bool"}],"name":"SetRelayers","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"routers","type":"address[]"},{"indexed":false,"internalType":"bool","name":"isTrue","type":"bool"}],"name":"SetRouters","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newSafe","type":"address"}],"name":"SetSafe","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newSigner","type":"address"}],"name":"SetSigner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newVault","type":"address"}],"name":"SetVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newValutToken","type":"address"}],"name":"SetVaultToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SignInfo","name":"_signInfo","type":"tuple"},{"components":[{"internalType":"address","name":"vaultReceiver","type":"address"},{"internalType":"bytes32","name":"transferId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct OrderInfo","name":"_orderInfo","type":"tuple"}],"name":"cancel","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"checkBridgeReady","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isRelayer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isRouter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"orderAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"orderStatus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SignInfo","name":"_signInfo","type":"tuple"},{"components":[{"internalType":"address","name":"vaultReceiver","type":"address"},{"internalType":"bytes32","name":"transferId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct OrderInfo","name":"_orderInfo","type":"tuple"},{"internalType":"uint256","name":"_refundAmount","type":"uint256"}],"name":"refund","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SignInfo","name":"_signInfo","type":"tuple"},{"components":[{"internalType":"address","name":"vaultReceiver","type":"address"},{"internalType":"bytes32","name":"transferId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct OrderInfo","name":"_orderInfo","type":"tuple"},{"internalType":"uint256","name":"_relayAmount","type":"uint256"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SignInfo","name":"_signInfo","type":"tuple"},{"components":[{"internalType":"address","name":"vaultReceiver","type":"address"},{"internalType":"bytes32","name":"transferId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct OrderInfo","name":"_orderInfo","type":"tuple"},{"components":[{"internalType":"address","name":"bkSwapV1Router","type":"address"},{"internalType":"address","name":"handlerAddress","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint24[]","name":"poolFee","type":"uint24[]"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"internalType":"struct SwapV1Info","name":"_swapV1Info","type":"tuple"},{"internalType":"uint256","name":"_relayAmount","type":"uint256"}],"name":"relayV1","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SignInfo","name":"_signInfo","type":"tuple"},{"components":[{"internalType":"address","name":"vaultReceiver","type":"address"},{"internalType":"bytes32","name":"transferId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct OrderInfo","name":"_orderInfo","type":"tuple"},{"components":[{"internalType":"address","name":"bkSwapV2Router","type":"address"},{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amountInTotal","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct SwapV2Info","name":"_swapV2Info","type":"tuple"},{"internalType":"uint256","name":"_relayAmount","type":"uint256"}],"name":"relayV2","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"rescueERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rescueETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"safe","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SignInfo","name":"_signInfo","type":"tuple"},{"components":[{"internalType":"address","name":"vaultReceiver","type":"address"},{"internalType":"bytes32","name":"transferId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct OrderInfo","name":"_orderInfo","type":"tuple"}],"name":"send","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SignInfo","name":"_signInfo","type":"tuple"},{"components":[{"internalType":"address","name":"vaultReceiver","type":"address"},{"internalType":"bytes32","name":"transferId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct OrderInfo","name":"_orderInfo","type":"tuple"},{"components":[{"internalType":"address","name":"bkSwapV1Router","type":"address"},{"internalType":"address","name":"handlerAddress","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint24[]","name":"poolFee","type":"uint24[]"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"internalType":"struct SwapV1Info","name":"_swapV1Info","type":"tuple"}],"name":"sendV1","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SignInfo","name":"_signInfo","type":"tuple"},{"components":[{"internalType":"address","name":"vaultReceiver","type":"address"},{"internalType":"bytes32","name":"transferId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct OrderInfo","name":"_orderInfo","type":"tuple"},{"components":[{"internalType":"address","name":"bkSwapV2Router","type":"address"},{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amountInTotal","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct SwapV2Info","name":"_swapV2Info","type":"tuple"}],"name":"sendV2","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"enum AccessType","name":"_accessType","type":"uint8"},{"internalType":"bytes","name":"_inputs","type":"bytes"}],"name":"setAccess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]