Overview
MNT Balance
MNT Value
Less Than $0.01 (@ $1.26/MNT)Latest 25 from a total of 62 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Swap And Bridge | 75966516 | 265 days ago | IN | 0 MNT | 0.06880348 | ||||
| Swap And Bridge | 75871114 | 267 days ago | IN | 5.9 MNT | 0.03249848 | ||||
| Swap And Bridge | 75834034 | 268 days ago | IN | 67 MNT | 0.07879468 | ||||
| Swap And Call | 75667950 | 272 days ago | IN | 0.05 MNT | 0.03176803 | ||||
| Swap And Bridge | 75403374 | 278 days ago | IN | 5 MNT | 0.04996673 | ||||
| Swap And Bridge | 75349014 | 279 days ago | IN | 26 MNT | 0.0410681 | ||||
| Swap And Bridge | 74941555 | 288 days ago | IN | 10 MNT | 0.04295579 | ||||
| Swap And Bridge | 74818593 | 291 days ago | IN | 9 MNT | 0.04790472 | ||||
| Swap And Call | 74672587 | 295 days ago | IN | 30 MNT | 0.05073137 | ||||
| Swap And Bridge | 74498188 | 299 days ago | IN | 0 MNT | 0.08588679 | ||||
| Swap And Bridge | 74449136 | 300 days ago | IN | 18 MNT | 0.06256725 | ||||
| Swap And Bridge | 74371496 | 302 days ago | IN | 0 MNT | 0.04176082 | ||||
| Swap And Bridge | 74200361 | 306 days ago | IN | 0 MNT | 0.10518657 | ||||
| Swap And Bridge | 74155111 | 307 days ago | IN | 4 MNT | 0.060537 | ||||
| Swap And Bridge | 74154938 | 307 days ago | IN | 5 MNT | 0.0657706 | ||||
| Swap And Bridge | 74154575 | 307 days ago | IN | 3 MNT | 0.05205051 | ||||
| Swap And Bridge | 74154241 | 307 days ago | IN | 4 MNT | 0.06561783 | ||||
| Swap And Bridge | 74154122 | 307 days ago | IN | 5 MNT | 0.05847119 | ||||
| Swap And Bridge | 74145166 | 307 days ago | IN | 2 MNT | 0.02818121 | ||||
| Swap And Bridge | 74099047 | 308 days ago | IN | 0 MNT | 0.0085645 | ||||
| Swap And Bridge | 73982785 | 311 days ago | IN | 0 MNT | 0.02749196 | ||||
| Swap And Bridge | 73402937 | 324 days ago | IN | 3.2 MNT | 0.06298034 | ||||
| Swap And Bridge | 73245200 | 328 days ago | IN | 26 MNT | 0.10390328 | ||||
| Swap And Bridge | 73126194 | 330 days ago | IN | 0.95920423 MNT | 0.0906358 | ||||
| Swap And Call | 72988896 | 334 days ago | IN | 0 MNT | 0.01576605 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 75871114 | 267 days ago | 5.9 MNT | ||||
| 75834034 | 268 days ago | 67 MNT | ||||
| 75667950 | 272 days ago | 0.05 MNT | ||||
| 75403374 | 278 days ago | 5 MNT | ||||
| 75349014 | 279 days ago | 26 MNT | ||||
| 74976088 | 288 days ago | 0.68931 MNT | ||||
| 74976088 | 288 days ago | 0.68931 MNT | ||||
| 74941555 | 288 days ago | 10 MNT | ||||
| 74818593 | 291 days ago | 9 MNT | ||||
| 74672587 | 295 days ago | 30 MNT | ||||
| 74517512 | 298 days ago | 199.8 MNT | ||||
| 74517512 | 298 days ago | 199.8 MNT | ||||
| 74449136 | 300 days ago | 18 MNT | ||||
| 74155111 | 307 days ago | 4 MNT | ||||
| 74154938 | 307 days ago | 5 MNT | ||||
| 74154575 | 307 days ago | 3 MNT | ||||
| 74154241 | 307 days ago | 4 MNT | ||||
| 74154122 | 307 days ago | 5 MNT | ||||
| 74145166 | 307 days ago | 2 MNT | ||||
| 73854329 | 314 days ago | 5.994 MNT | ||||
| 73854329 | 314 days ago | 5.994 MNT | ||||
| 73492070 | 322 days ago | 63.936 MNT | ||||
| 73492070 | 322 days ago | 63.936 MNT | ||||
| 73402937 | 324 days ago | 3.2 MNT | ||||
| 73245200 | 328 days ago | 26 MNT |
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.20;
import "@openzeppelin/contracts/access/Ownable2Step.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@butternetwork/bridge/contracts/interface/IButterBridgeV3.sol";
import "@butternetwork/bridge/contracts/interface/IButterReceiver.sol";
import "./interface/IFeeManager.sol";
import "./abstract/SwapCall.sol";
import "./interface/IButterRouterV3.sol";
import "./abstract/FeeManager.sol";
contract ButterRouterV3 is SwapCall, FeeManager, ReentrancyGuard, IButterReceiver, IButterRouterV3 {
using SafeERC20 for IERC20;
using Address for address;
address public bridgeAddress;
IFeeManager public feeManager;
uint256 public gasForReFund = 80000;
// use to solve deep stack
struct SwapTemp {
address srcToken;
address swapToken;
uint256 srcAmount;
uint256 swapAmount;
bytes32 transferId;
address referrer;
address initiator;
address receiver;
address target;
uint256 callAmount;
uint256 fromChain;
uint256 toChain;
uint256 nativeBalance;
uint256 inputBalance;
bytes from;
}
event Approve(address indexed executor, bool indexed flag);
event SetFeeManager(address indexed _feeManager);
event CollectFee(
address indexed token,
address indexed receiver,
address indexed integrator,
uint256 routerAmount,
uint256 integratorAmount,
uint256 nativeAmount,
uint256 integratorNative,
bytes32 transferId
);
event SetBridgeAddress(address indexed _bridgeAddress);
event SetGasForReFund(uint256 indexed _gasForReFund);
constructor(address _bridgeAddress, address _owner, address _wToken) payable SwapCall(_wToken) FeeManager(_owner) {
_setBridgeAddress(_bridgeAddress);
}
function setAuthorization(address[] calldata _executors, bool _flag) external onlyOwner {
if (_executors.length == 0) revert Errors.EMPTY();
for (uint i = 0; i < _executors.length; i++) {
if (!_executors[i].isContract()) revert Errors.NOT_CONTRACT();
approved[_executors[i]] = _flag;
emit Approve(_executors[i], _flag);
}
}
function setGasForReFund(uint256 _gasForReFund) external onlyOwner {
gasForReFund = _gasForReFund;
emit SetGasForReFund(_gasForReFund);
}
function setBridgeAddress(address _bridgeAddress) public onlyOwner returns (bool) {
_setBridgeAddress(_bridgeAddress);
return true;
}
function setWToken(address _wToken) external onlyOwner {
_setWToken(_wToken);
}
function setFeeManager(address _feeManager) public onlyOwner {
if (!_feeManager.isContract()) revert Errors.NOT_CONTRACT();
feeManager = IFeeManager(_feeManager);
emit SetFeeManager(_feeManager);
}
function editFuncBlackList(bytes4 _func, bool _flag) external onlyOwner {
_editFuncBlackList(_func, _flag);
}
function swapAndBridge(
bytes32 _transferId,
address _initiator, // initiator address
address _srcToken,
uint256 _amount,
bytes calldata _swapData,
bytes calldata _bridgeData,
bytes calldata _permitData,
bytes calldata _feeData
) external payable override nonReentrant returns (bytes32 orderId) {
if ((_swapData.length + _bridgeData.length) == 0) revert Errors.DATA_EMPTY();
SwapTemp memory swapTemp;
swapTemp.initiator = _initiator;
swapTemp.srcToken = _srcToken;
swapTemp.srcAmount = _amount;
swapTemp.swapToken = _srcToken;
swapTemp.swapAmount = _amount;
swapTemp.transferId = _transferId;
(swapTemp.nativeBalance, swapTemp.inputBalance) = _transferIn(
swapTemp.srcToken,
swapTemp.srcAmount,
_permitData
);
bytes memory receiver;
FeeDetail memory fd;
(fd, swapTemp.swapAmount, swapTemp.referrer) = _collectFee(swapTemp.srcToken, swapTemp.srcAmount, _feeData);
if (_swapData.length != 0) {
SwapParam memory swapParam = abi.decode(_swapData, (SwapParam));
(swapTemp.swapToken, swapTemp.swapAmount) = _swap(
swapTemp.srcToken,
swapTemp.swapAmount,
swapTemp.inputBalance,
swapParam
);
if (_bridgeData.length == 0 && swapTemp.swapAmount != 0) {
receiver = abi.encodePacked(swapParam.receiver);
_transfer(swapTemp.swapToken, swapParam.receiver, swapTemp.swapAmount);
}
}
if (_bridgeData.length != 0) {
BridgeParam memory bridge = abi.decode(_bridgeData, (BridgeParam));
swapTemp.toChain = bridge.toChain;
receiver = bridge.receiver;
orderId = _doBridge(msg.sender, swapTemp.swapToken, swapTemp.swapAmount, bridge);
}
emit CollectFee(
swapTemp.srcToken,
fd.routerReceiver,
fd.integrator,
fd.routerTokenFee,
fd.integratorTokenFee,
fd.routerNativeFee,
fd.integratorNativeFee,
orderId
);
emit SwapAndBridge(
swapTemp.referrer,
swapTemp.initiator,
msg.sender,
swapTemp.transferId,
orderId,
swapTemp.srcToken,
swapTemp.swapToken,
swapTemp.srcAmount,
swapTemp.swapAmount,
swapTemp.toChain,
receiver
);
_afterCheck(swapTemp.nativeBalance);
}
function swapAndCall(
bytes32 _transferId,
address _initiator, // initiator address
address _srcToken,
uint256 _amount,
bytes calldata _swapData,
bytes calldata _callbackData,
bytes calldata _permitData,
bytes calldata _feeData
) external payable override nonReentrant {
SwapTemp memory swapTemp;
swapTemp.initiator = _initiator;
swapTemp.srcToken = _srcToken;
swapTemp.srcAmount = _amount;
swapTemp.transferId = _transferId;
(swapTemp.nativeBalance, swapTemp.inputBalance) = _transferIn(
swapTemp.srcToken,
swapTemp.srcAmount,
_permitData
);
if ((_swapData.length + _callbackData.length) == 0) revert Errors.DATA_EMPTY();
FeeDetail memory fd;
(fd, swapTemp.swapAmount, swapTemp.referrer) = _collectFee(swapTemp.srcToken, swapTemp.srcAmount, _feeData);
emit CollectFee(
swapTemp.srcToken,
fd.routerReceiver,
fd.integrator,
fd.routerTokenFee,
fd.integratorTokenFee,
fd.routerNativeFee,
fd.integratorNativeFee,
swapTemp.transferId
);
(
swapTemp.receiver,
swapTemp.target,
swapTemp.swapToken,
swapTemp.swapAmount,
swapTemp.callAmount
) = _doSwapAndCall(swapTemp.srcToken, swapTemp.swapAmount, swapTemp.inputBalance, _swapData, _callbackData);
if (swapTemp.swapAmount > swapTemp.callAmount) {
_transfer(swapTemp.swapToken, swapTemp.receiver, (swapTemp.swapAmount - swapTemp.callAmount));
}
emit SwapAndCall(
swapTemp.referrer,
swapTemp.initiator,
msg.sender,
swapTemp.transferId,
swapTemp.srcToken,
swapTemp.swapToken,
swapTemp.srcAmount,
swapTemp.swapAmount,
swapTemp.receiver,
swapTemp.target,
swapTemp.callAmount
);
_afterCheck(swapTemp.nativeBalance);
}
// _srcToken must erc20 Token or wToken
function onReceived(
bytes32 _orderId,
address _srcToken,
uint256 _amount,
uint256 _fromChain,
bytes calldata _from,
bytes calldata _swapAndCall
) external override nonReentrant {
SwapTemp memory swapTemp;
swapTemp.srcToken = _srcToken;
swapTemp.srcAmount = _amount;
swapTemp.swapToken = _srcToken;
swapTemp.swapAmount = _amount;
swapTemp.fromChain = _fromChain;
swapTemp.toChain = block.chainid;
swapTemp.from = _from;
if (msg.sender != bridgeAddress) revert Errors.BRIDGE_ONLY();
{
uint256 balance = _getBalance(swapTemp.srcToken, address(this));
if (balance < _amount) revert Errors.RECEIVE_LOW();
swapTemp.nativeBalance = address(this).balance;
swapTemp.inputBalance = balance - _amount;
}
(bytes memory _swapData, bytes memory _callbackData) = abi.decode(_swapAndCall, (bytes, bytes));
if ((_swapData.length + _callbackData.length) == 0) revert Errors.DATA_EMPTY();
bool result = true;
uint256 minExecGas = gasForReFund;
if (_swapData.length > 0) {
SwapParam memory swap = abi.decode(_swapData, (SwapParam));
swapTemp.receiver = swap.receiver;
if (gasleft() > minExecGas) {
try
this.remoteSwap{gas: gasleft() - minExecGas}(
swapTemp.srcToken,
swapTemp.srcAmount,
swapTemp.inputBalance,
swap
)
returns (address dstToken, uint256 dstAmount) {
swapTemp.swapToken = dstToken;
swapTemp.swapAmount = dstAmount;
} catch {
result = false;
}
}
}
if (_callbackData.length > 0) {
CallbackParam memory callParam = abi.decode(_callbackData, (CallbackParam));
if (swapTemp.receiver == address(0)) {
swapTemp.receiver = callParam.receiver;
}
if (result && gasleft() > minExecGas) {
try
this.remoteCall{gas: gasleft() - minExecGas}(callParam, swapTemp.swapToken, swapTemp.swapAmount)
returns (address target, uint256 callAmount) {
swapTemp.target = target;
swapTemp.callAmount = callAmount;
swapTemp.receiver = callParam.receiver;
} catch {}
}
}
if (swapTemp.swapAmount > swapTemp.callAmount) {
_transfer(swapTemp.swapToken, swapTemp.receiver, (swapTemp.swapAmount - swapTemp.callAmount));
}
emit RemoteSwapAndCall(
_orderId,
swapTemp.receiver,
swapTemp.target,
swapTemp.srcToken,
swapTemp.swapToken,
swapTemp.srcAmount,
swapTemp.swapAmount,
swapTemp.callAmount,
swapTemp.fromChain,
swapTemp.toChain,
swapTemp.from
);
_afterCheck(swapTemp.nativeBalance);
}
function getFee(
address _inputToken,
uint256 _inputAmount,
bytes calldata _feeData
) external view override returns (address feeToken, uint256 tokenFee, uint256 nativeFee, uint256 afterFeeAmount) {
IFeeManager.FeeDetail memory fd = _getFee(_inputToken, _inputAmount, _feeData);
feeToken = fd.feeToken;
if (_isNative(_inputToken)) {
tokenFee = 0;
nativeFee = fd.routerNativeFee + fd.routerTokenFee + fd.integratorTokenFee + fd.integratorNativeFee;
afterFeeAmount = _inputAmount - nativeFee;
} else {
tokenFee = fd.routerTokenFee + fd.integratorTokenFee;
nativeFee = fd.routerNativeFee + fd.integratorNativeFee;
afterFeeAmount = _inputAmount - tokenFee;
}
}
function _getFee(
address _inputToken,
uint256 _inputAmount,
bytes calldata _feeData
) internal view returns (FeeDetail memory fd) {
if (address(feeManager) == ZERO_ADDRESS) {
fd = this.getFeeDetail(_inputToken, _inputAmount, _feeData);
} else {
fd = feeManager.getFeeDetail(_inputToken, _inputAmount, _feeData);
}
}
function getInputBeforeFee(
address _token,
uint256 _amountAfterFee,
bytes calldata _feeData
) external view override returns (address _feeToken, uint256 _input, uint256 _fee) {
if (address(feeManager) == ZERO_ADDRESS) {
return this.getAmountBeforeFee(_token, _amountAfterFee, _feeData);
}
return feeManager.getAmountBeforeFee(_token, _amountAfterFee, _feeData);
}
function remoteSwap(
address _srcToken,
uint256 _amount,
uint256 _initBalance,
SwapParam memory swapParam
) external returns (address dstToken, uint256 dstAmount) {
if (msg.sender != address(this)) revert Errors.SELF_ONLY();
(dstToken, dstAmount) = _swap(_srcToken, _amount, _initBalance, swapParam);
}
function remoteCall(
CallbackParam memory _callbackParam,
address _callToken,
uint256 _amount
) external returns (address target, uint256 callAmount) {
if (msg.sender != address(this)) revert Errors.SELF_ONLY();
target = _callbackParam.target;
callAmount = _callBack(_amount, _callToken, _callbackParam);
}
function _doSwapAndCall(
address _srcToken,
uint256 _amount,
uint256 _initBalance,
bytes memory _swapData,
bytes memory _callbackData
) internal returns (address receiver, address target, address dstToken, uint256 swapOutAmount, uint256 callAmount) {
swapOutAmount = _amount;
dstToken = _srcToken;
if (_swapData.length > 0) {
SwapParam memory swapParam = abi.decode(_swapData, (SwapParam));
(dstToken, swapOutAmount) = _swap(_srcToken, _amount, _initBalance, swapParam);
receiver = swapParam.receiver;
}
if (_callbackData.length > 0) {
CallbackParam memory callbackParam = abi.decode(_callbackData, (CallbackParam));
callAmount = _callBack(swapOutAmount, dstToken, callbackParam);
receiver = callbackParam.receiver;
target = callbackParam.target;
}
}
function _doBridge(
address _sender,
address _token,
uint256 _amount,
BridgeParam memory _bridge
) internal returns (bytes32 _orderId) {
uint256 value;
address bridgeAddr = bridgeAddress;
if (_isNative(_token)) {
value = _amount + _bridge.nativeFee;
} else {
value = _bridge.nativeFee;
IERC20(_token).forceApprove(bridgeAddr, _amount);
}
_orderId = IButterBridgeV3(bridgeAddr).swapOutToken{value: value}(
_sender,
_token,
_bridge.receiver,
_amount,
_bridge.toChain,
_bridge.data
);
}
function _collectFee(
address _token,
uint256 _amount,
bytes calldata _feeData
) internal returns (FeeDetail memory fd, uint256 remain, address referrer) {
fd = _getFee(_token, _amount, _feeData);
referrer = fd.integrator;
if (_isNative(_token)) {
uint256 routerNative = fd.routerNativeFee + fd.routerTokenFee;
if (routerNative > 0) {
_transfer(_token, fd.routerReceiver, routerNative);
}
uint256 integratorNative = fd.integratorTokenFee + fd.integratorNativeFee;
if (integratorNative > 0) {
_transfer(_token, fd.integrator, integratorNative);
}
remain = _amount - routerNative - integratorNative;
} else {
if (fd.routerNativeFee > 0) {
_transfer(ZERO_ADDRESS, fd.routerReceiver, fd.routerNativeFee);
}
if (fd.routerTokenFee > 0) {
_transfer(_token, fd.routerReceiver, fd.routerTokenFee);
}
if (fd.integratorNativeFee > 0) {
_transfer(ZERO_ADDRESS, fd.integrator, fd.integratorNativeFee);
}
if (fd.integratorTokenFee > 0) {
_transfer(_token, fd.integrator, fd.integratorTokenFee);
}
remain = _amount - fd.routerTokenFee - fd.integratorTokenFee;
if (fd.routerNativeFee + fd.integratorNativeFee > msg.value) revert Errors.FEE_MISMATCH();
}
if (remain == 0) revert Errors.ZERO_IN();
}
function _setBridgeAddress(address _bridgeAddress) internal returns (bool) {
if (!_bridgeAddress.isContract()) revert Errors.NOT_CONTRACT();
bridgeAddress = _bridgeAddress;
emit SetBridgeAddress(_bridgeAddress);
return true;
}
function rescueFunds(address _token, uint256 _amount) external onlyOwner {
_transfer(_token, msg.sender, _amount);
}
receive() external payable {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IButterBridgeV3 {
struct BridgeParam {
uint256 gasLimit;
bytes refundAddress;
bytes swapData;
}
function swapOutToken(
address _sender, // user account send this transaction
address _token, // src token
bytes memory _to, // receiver account
uint256 _amount, // token amount
uint256 _toChain, // target chain id
bytes calldata _bridgeData
) external payable returns (bytes32 orderId);
function depositToken(address _token, address to, uint256 _amount) external payable;
function getNativeFee(address _token, uint256 _gasLimit, uint256 _toChain) external view returns (uint256);
event Relay(bytes32 orderId1, bytes32 orderId2);
event CollectFee(bytes32 indexed orderId, address indexed token, uint256 value);
event SwapOut(
bytes32 indexed orderId, // orderId
uint256 indexed tochain, // to chain
address indexed token, // token to across chain
uint256 amount, // amount to transfer
address from, // account send this transaction
address caller, // msg.sender call swapOutToken
bytes to, // account receiver on target chain
bytes outToken, // token bridge to target chain(token is native this maybe wtoken)
uint256 gasLimit, // gasLimit for call on target chain
uint256 messageFee // native amount for pass message
);
event SwapIn(
bytes32 indexed orderId, // orderId
uint256 indexed fromChain, // from chain
address indexed token, // token received on target chain
uint256 amount, // target token amount
address to, // account receiver on target chain
address outToken, //
bytes from // from chain account send this transaction
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IButterReceiver {
//_srcToken received token (wtoken or erc20 token)
function onReceived(
bytes32 _orderId,
address _srcToken,
uint256 _amount,
uint256 _fromChain,
bytes calldata _from,
bytes calldata _payload
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.0;
import "./Ownable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
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));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
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");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
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");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
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");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
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");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.20;
import "@openzeppelin/contracts/access/Ownable2Step.sol";
import "../interface/IFeeManager.sol";
import "../interface/IButterRouterV3.sol";
import "../lib/Errors.sol";
abstract contract FeeManager is Ownable2Step, IFeeManager {
uint256 constant FEE_DENOMINATOR = 10000;
uint256 public routerFeeRate;
uint256 public routerFixedFee;
address public feeReceiver;
uint256 public maxFeeRate; // referrer max fee rate
uint256 public maxNativeFee; // referrer max fixed native fee
event SetFee(address indexed receiver, uint256 indexed rate, uint256 indexed fixedf);
event SetReferrerMaxFee(uint256 indexed _maxFeeRate, uint256 indexed _maxNativeFee);
constructor(address _owner) payable {
if (_owner == address(0)) revert Errors.ZERO_ADDRESS();
_transferOwnership(_owner);
}
function setFee(address _feeReceiver, uint256 _feeRate, uint256 _fixedFee) external onlyOwner {
if (_feeReceiver == address(0)) revert Errors.ZERO_ADDRESS();
require(_feeRate < FEE_DENOMINATOR);
feeReceiver = _feeReceiver;
routerFeeRate = _feeRate;
routerFixedFee = _fixedFee;
emit SetFee(_feeReceiver, _feeRate, routerFixedFee);
}
function setReferrerMaxFee(uint256 _maxFeeRate, uint256 _maxNativeFee) external onlyOwner {
require(_maxFeeRate < FEE_DENOMINATOR);
maxFeeRate = _maxFeeRate;
maxNativeFee = _maxNativeFee;
emit SetReferrerMaxFee(_maxFeeRate, _maxNativeFee);
}
function getFeeDetail(
address _inputToken,
uint256 _inputAmount,
bytes calldata _feeData
) external view virtual override returns (FeeDetail memory feeDetail) {
IButterRouterV3.Fee memory fee = _checkFeeData(_feeData);
if (feeReceiver == address(0) && fee.referrer == address(0)) {
return feeDetail;
}
feeDetail.feeToken = _inputToken;
if (feeReceiver != address(0)) {
feeDetail.routerReceiver = feeReceiver;
feeDetail.routerNativeFee = routerFixedFee;
if (_inputToken == address(0)) {
feeDetail.routerNativeFee += (_inputAmount * routerFeeRate) / FEE_DENOMINATOR;
} else {
feeDetail.routerTokenFee = (_inputAmount * routerFeeRate) / FEE_DENOMINATOR;
}
}
if (fee.referrer != address(0)) {
feeDetail.integrator = fee.referrer;
if (fee.feeType == IButterRouterV3.FeeType.FIXED) {
feeDetail.integratorNativeFee = fee.rateOrNativeFee;
} else {
if (_inputToken == address(0)) {
feeDetail.integratorNativeFee = (_inputAmount * fee.rateOrNativeFee) / FEE_DENOMINATOR;
} else {
feeDetail.integratorTokenFee = (_inputAmount * fee.rateOrNativeFee) / FEE_DENOMINATOR;
}
}
}
return feeDetail;
}
function getAmountBeforeFee(
address _token,
uint256 _amountAfterFee,
bytes calldata _feeData
) external view virtual returns (address feeToken, uint256 beforeAmount, uint256 nativeFeeAmount) {
IButterRouterV3.Fee memory fee = _checkFeeData(_feeData);
if (feeReceiver == address(0) && fee.referrer == address(0)) {
return (address(0), _amountAfterFee, 0);
}
uint256 feeRate = 0;
if (feeReceiver != address(0)) {
nativeFeeAmount += routerFixedFee;
feeRate += routerFeeRate;
}
if (fee.referrer != address(0)) {
if (fee.feeType == IButterRouterV3.FeeType.FIXED) {
nativeFeeAmount += fee.rateOrNativeFee;
} else {
feeRate += fee.rateOrNativeFee;
}
}
if (_token == address(0) || _token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) {
beforeAmount = _amountAfterFee + nativeFeeAmount;
if (feeRate > 0) {
beforeAmount = (beforeAmount * FEE_DENOMINATOR) / (FEE_DENOMINATOR - feeRate) + 1;
}
} else {
if (feeRate > 0) {
beforeAmount = (_amountAfterFee * FEE_DENOMINATOR) / (FEE_DENOMINATOR - feeRate) + 1;
} else {
beforeAmount = _amountAfterFee;
}
}
}
function _checkFeeData(bytes calldata _feeData) internal view returns (IButterRouterV3.Fee memory fee) {
if (_feeData.length == 0) {
return fee;
}
fee = abi.decode(_feeData, (IButterRouterV3.Fee));
if (fee.feeType == IButterRouterV3.FeeType.PROPORTION) {
require(fee.rateOrNativeFee < maxFeeRate, "FeeManager: invalid feeRate");
} else {
require(fee.rateOrNativeFee < maxNativeFee, "FeeManager: invalid native fee");
}
return fee;
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.20;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "../lib/Errors.sol";
abstract contract SwapCall {
using SafeERC20 for IERC20;
using Address for address;
address internal constant ZERO_ADDRESS = address(0);
address internal constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
address public wToken;
// uint256 internal nativeBalanceBeforeExec;
// uint256 internal initInputTokenBalance;
mapping(address => bool) public approved;
mapping(bytes4 => bool) public funcBlackList;
event EditFuncBlackList(bytes4 _func, bool flag);
event SetWrappedToken(address indexed _wToken);
enum DexType {
AGG,
UNIV2,
UNIV3,
CURVE,
FILL,
MIX
}
struct CallbackParam {
address target;
address approveTo;
uint256 offset;
uint256 extraNativeAmount;
address receiver;
bytes data;
}
struct SwapParam {
address dstToken;
address receiver;
address leftReceiver;
uint256 minAmount;
SwapData[] swaps;
}
struct SwapData {
DexType dexType;
address callTo;
address approveTo;
uint256 fromAmount;
bytes callData;
}
constructor(address _wToken) payable {
_setWToken(_wToken);
//| a9059cbb | transfer(address,uint256)
funcBlackList[bytes4(0xa9059cbb)] = true;
//| 095ea7b3 | approve(address,uint256) |
funcBlackList[bytes4(0x095ea7b3)] = true;
//| 23b872dd | transferFrom(address,address,uint256) |
funcBlackList[bytes4(0x23b872dd)] = true;
//| 39509351 | increaseAllowance(address,uint256)
funcBlackList[bytes4(0x39509351)] = true;
//| a22cb465 | setApprovalForAll(address,bool) |
funcBlackList[bytes4(0xa22cb465)] = true;
//| 42842e0e | safeTransferFrom(address,address,uint256) |
funcBlackList[bytes4(0x42842e0e)] = true;
//| b88d4fde | safeTransferFrom(address,address,uint256,bytes) |
funcBlackList[bytes4(0xb88d4fde)] = true;
//| 9bd9bbc6 | send(address,uint256,bytes) |
funcBlackList[bytes4(0x9bd9bbc6)] = true;
//| fe9d9303 | burn(uint256,bytes) |
funcBlackList[bytes4(0xfe9d9303)] = true;
//| 959b8c3f | authorizeOperator
funcBlackList[bytes4(0x959b8c3f)] = true;
//| f242432a | safeTransferFrom(address,address,uint256,uint256,bytes) |
funcBlackList[bytes4(0xf242432a)] = true;
//| 2eb2c2d6 | safeBatchTransferFrom(address,address,uint256[],uint256[],bytes) |
funcBlackList[bytes4(0x2eb2c2d6)] = true;
}
function _editFuncBlackList(bytes4 _func, bool _flag) internal {
funcBlackList[_func] = _flag;
emit EditFuncBlackList(_func, _flag);
}
function _setWToken(address _wToken) internal {
if (!_wToken.isContract()) revert Errors.NOT_CONTRACT();
wToken = _wToken;
emit SetWrappedToken(_wToken);
}
function _transferIn(
address token,
uint256 amount,
bytes memory permitData
) internal returns (uint256 nativeBalanceBeforeExec, uint256 initInputTokenBalance) {
if (amount == 0) revert Errors.ZERO_IN();
if (permitData.length != 0) {
_permit(permitData);
}
nativeBalanceBeforeExec = address(this).balance - msg.value;
if (_isNative(token)) {
if (msg.value < amount) revert Errors.FEE_MISMATCH();
//extra value maybe used for call native or bridge native fee
initInputTokenBalance = address(this).balance - amount;
} else {
initInputTokenBalance = _getBalance(token, address(this));
SafeERC20.safeTransferFrom(IERC20(token), msg.sender, address(this), amount);
}
}
function _afterCheck(uint256 nativeBalanceBeforeExec) internal view {
if (address(this).balance < nativeBalanceBeforeExec) revert Errors.NATIVE_VALUE_OVERSPEND();
}
function _swap(
address _token,
uint256 _amount,
uint256 _initBalance,
SwapParam memory swapParam
) internal returns (address _dstToken, uint256 _dstAmount) {
_dstToken = swapParam.dstToken;
if (_token == _dstToken) revert Errors.SWAP_SAME_TOKEN();
uint256 finalTokenAmount = _getBalance(swapParam.dstToken, address(this));
_doSwap(_token, _amount, swapParam);
_dstAmount = _getBalance(swapParam.dstToken, address(this)) - finalTokenAmount;
if (_dstAmount < swapParam.minAmount) revert Errors.RECEIVE_LOW();
uint256 left = _getBalance(_token, address(this)) - _initBalance;
if (left != 0) {
_transfer(_token, swapParam.leftReceiver, left);
}
}
function _callBack(
uint256 _amount,
address _token,
CallbackParam memory callParam
) internal returns (uint256 _callAmount) {
_callAmount = _getBalance(_token, address(this));
uint256 offset = callParam.offset;
bytes memory callPayload = callParam.data;
if (offset > 35) {
//32 length + 4 funcSig
assembly {
mstore(add(callPayload, offset), _amount)
}
}
_checkApprove(callParam.target, callPayload);
bool _result;
if (_isNative(_token)) {
(_result, ) = callParam.target.call{value: _amount}(callPayload);
} else {
if (_amount != 0) IERC20(_token).safeIncreaseAllowance(callParam.approveTo, _amount);
// this contract not save money make sure send value can cover this
(_result, ) = callParam.target.call{value: callParam.extraNativeAmount}(callPayload);
if (_amount != 0) IERC20(_token).safeApprove(callParam.approveTo, 0);
}
if (!_result) revert Errors.CALL_BACK_FAIL();
_callAmount = _callAmount - _getBalance(_token, address(this));
}
function _checkApprove(address _callTo, bytes memory _calldata) private view {
address wTokenAddr = wToken;
if (_callTo != wTokenAddr && (!approved[_callTo])) revert Errors.NO_APPROVE();
bytes4 sig = _getFirst4Bytes(_calldata);
if (funcBlackList[sig]) revert Errors.CALL_FUNC_BLACK_LIST();
if (_callTo == wTokenAddr) {
if (sig != bytes4(0x2e1a7d4d) && sig != bytes4(0xd0e30db0)) revert Errors.CALL_FUNC_BLACK_LIST();
}
}
function _doSwap(address _token, uint256 _amount, SwapParam memory swapParam) internal {
uint256 len = swapParam.swaps.length;
if (len == 0) revert Errors.EMPTY();
(uint256 amountAdjust, uint256 firstAdjust, bool isUp) = _rebuildSwaps(_amount, len, swapParam.swaps);
SwapData[] memory _swaps = swapParam.swaps;
bool isNative = _isNative(_token);
for (uint i = 0; i < len; ) {
if (firstAdjust != 0) {
if (i == 0) {
isUp ? _swaps[i].fromAmount += firstAdjust : _swaps[i].fromAmount -= firstAdjust;
} else {
isUp ? _swaps[i].fromAmount += amountAdjust : _swaps[i].fromAmount -= amountAdjust;
}
}
if (!isNative) {
IERC20(_token).safeIncreaseAllowance(_swaps[i].approveTo, _swaps[i].fromAmount);
}
_execute(_swaps[i].dexType, isNative, _swaps[i].callTo, _token, _swaps[i].fromAmount, _swaps[i].callData);
if (!isNative) {
IERC20(_token).safeApprove(_swaps[i].approveTo, 0);
}
unchecked {
i++;
}
}
}
function _rebuildSwaps(
uint256 _amount,
uint256 _len,
SwapData[] memory _swaps
) private pure returns (uint256 amountAdjust, uint256 firstAdjust, bool isUp) {
uint256 total = 0;
for (uint256 i = 0; i < _len; i++) {
total += _swaps[i].fromAmount;
}
if (total > _amount) {
isUp = false;
uint256 margin = total - _amount;
amountAdjust = margin / _len;
firstAdjust = amountAdjust + (margin - amountAdjust * _len);
} else if (total < _amount) {
isUp = true;
uint256 margin = _amount - total;
amountAdjust = margin / _len;
firstAdjust = amountAdjust + (margin - amountAdjust * _len);
}
}
function _execute(
DexType _dexType,
bool _native,
address _router,
address _srcToken,
uint256 _amount,
bytes memory _swapData
) internal {
bool _result;
if (_dexType == DexType.FILL) {
(_result) = _makeAggFill(_router, _amount, _native, _swapData);
} else if (_dexType == DexType.MIX) {
(_result) = _makeMixSwap(_srcToken, _amount, _swapData);
} else {
revert Errors.UNSUPPORT_DEX_TYPE();
}
if (!_result) revert Errors.SWAP_FAIL();
}
struct MixSwap {
uint256 offset;
address srcToken;
address callTo;
address approveTo;
bytes callData;
}
function _makeMixSwap(address _srcToken, uint256 _amount, bytes memory _swapData) internal returns (bool _result) {
MixSwap[] memory mixSwaps = abi.decode(_swapData, (MixSwap[]));
for (uint256 i = 0; i < mixSwaps.length; i++) {
if (i != 0) {
_amount = _getBalance(mixSwaps[i].srcToken, address(this));
_srcToken = mixSwaps[i].srcToken;
}
bytes memory callData = mixSwaps[i].callData;
uint256 offset = mixSwaps[i].offset;
if (offset > 35) {
//32 length + 4 funcSig
assembly {
mstore(add(callData, offset), _amount)
}
}
_checkApprove(mixSwaps[i].callTo, callData);
if (_isNative(_srcToken)) {
(_result, ) = mixSwaps[i].callTo.call{value: _amount}(callData);
} else {
if (i != 0) {
IERC20(_srcToken).safeIncreaseAllowance(mixSwaps[i].approveTo, _amount);
}
(_result, ) = mixSwaps[i].callTo.call(callData);
if (i != 0) {
IERC20(_srcToken).safeApprove(mixSwaps[i].approveTo, 0);
}
}
if (!_result) {
break;
}
}
}
function _makeAggFill(
address _router,
uint256 _amount,
bool native,
bytes memory _swapData
) internal returns (bool _result) {
(uint256[] memory offsets, bytes memory callData) = abi.decode(_swapData, (uint256[], bytes));
uint256 len = offsets.length;
for (uint i = 0; i < len; i++) {
uint256 offset = offsets[i];
if (offset > 35) {
//32 length + 4 funcSig
assembly {
mstore(add(callData, offset), _amount)
}
}
}
_checkApprove(_router, callData);
if (native) {
(_result, ) = _router.call{value: _amount}(callData);
} else {
(_result, ) = _router.call(callData);
}
}
function _isNative(address token) internal pure returns (bool) {
return (token == ZERO_ADDRESS || token == NATIVE_ADDRESS);
}
function _getBalance(address _token, address _account) internal view returns (uint256) {
if (_isNative(_token)) {
return _account.balance;
} else {
return IERC20(_token).balanceOf(_account);
}
}
function _transfer(address _token, address _to, uint256 _amount) internal {
if (_isNative(_token)) {
Address.sendValue(payable(_to), _amount);
} else {
uint256 _chainId = block.chainid;
if (_chainId == 728126428 && _token == 0xa614f803B6FD780986A42c78Ec9c7f77e6DeD13C) {
// Tron USDT
_token.call(abi.encodeWithSelector(0xa9059cbb, _to, _amount));
} else {
IERC20(_token).safeTransfer(_to, _amount);
}
}
}
function _getFirst4Bytes(bytes memory data) internal pure returns (bytes4 outBytes4) {
if (data.length == 0) {
return 0x0;
}
assembly {
outBytes4 := mload(add(data, 32))
}
}
function _permit(bytes memory _data) internal {
(
address token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) = abi.decode(_data, (address, address, address, uint256, uint256, uint8, bytes32, bytes32));
SafeERC20.safePermit(IERC20Permit(token), owner, spender, value, deadline, v, r, s);
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
interface IButterRouterV3 {
enum FeeType {
FIXED,
PROPORTION
}
struct Fee {
FeeType feeType;
address referrer;
uint256 rateOrNativeFee;
}
struct BridgeParam {
uint256 toChain;
uint256 nativeFee;
bytes receiver;
bytes data;
}
event SwapAndBridge(
address indexed referrer,
address indexed initiator,
address indexed from,
bytes32 transferId,
bytes32 orderId,
address originToken,
address bridgeToken,
uint256 originAmount,
uint256 bridgeAmount,
uint256 toChain,
bytes to
);
event SwapAndCall(
address indexed referrer,
address indexed initiator,
address indexed from,
bytes32 transferId,
address originToken,
address swapToken,
uint256 originAmount,
uint256 swapAmount,
address receiver,
address target,
uint256 callAmount
);
event RemoteSwapAndCall(
bytes32 indexed orderId,
address indexed receiver,
address indexed target,
address originToken,
address swapToken,
uint256 originAmount,
uint256 swapAmount,
uint256 callAmount,
uint256 fromChain,
uint256 toChain,
bytes from
);
// 1. swap: _swapData.length > 0 and _bridgeData.length == 0
// 2. swap and call: _swapData.length > 0 and _callbackData.length > 0
function swapAndCall(
bytes32 _transferId,
address _initiator,
address _srcToken,
uint256 _amount,
bytes calldata _swapData,
bytes calldata _callbackData,
bytes calldata _permitData,
bytes calldata _feeData
) external payable;
// 1. bridge: _swapData.length == 0 and _bridgeData.length > 0
// 2. swap and bridge: _swapData.length > 0 and _bridgeData.length > 0
function swapAndBridge(
bytes32 _transferId,
address _initiator,
address _srcToken,
uint256 _amount,
bytes calldata _swapData,
bytes calldata _bridgeData,
bytes calldata _permitData,
bytes calldata _feeData
) external payable returns (bytes32 orderId);
function getFee(
address _inputToken,
uint256 _inputAmount,
bytes calldata _feeData
) external view returns (address feeToken, uint256 tokenFee, uint256 nativeFee, uint256 afterFeeAmount);
function getInputBeforeFee(
address _inputToken,
uint256 _afterFeeAmount,
bytes calldata _feeData
) external view returns (address feeToken, uint256 inputAmount, uint256 nativeFee);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
interface IFeeManager {
struct FeeDetail {
address feeToken;
address routerReceiver;
address integrator;
uint256 routerNativeFee;
uint256 integratorNativeFee;
uint256 routerTokenFee;
uint256 integratorTokenFee;
}
function getFeeDetail(
address inputToken,
uint256 inputAmount,
bytes calldata _feeData
) external view returns (FeeDetail memory feeDetail);
function getAmountBeforeFee(
address inputToken,
uint256 inputAmount,
bytes calldata _feeData
) external view returns (address feeToken, uint256 beforeAmount, uint256 nativeFeeAmount);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
library Errors {
error NOT_CONTRACT();
error SWAP_FAIL();
error CALL_BACK_FAIL();
error ZERO_IN();
error FEE_MISMATCH();
error FEE_LOWER();
error ZERO_ADDRESS();
error RECEIVE_LOW();
error CALL_AMOUNT_INVALID();
error BRIDGE_ONLY();
error DATA_EMPTY();
error NO_APPROVE();
error NATIVE_VALUE_OVERSPEND();
error EMPTY();
error UNSUPPORT_DEX_TYPE();
error SWAP_SAME_TOKEN();
error CANNOT_ADJUST();
error SELF_ONLY();
error CALL_FUNC_BLACK_LIST();
}{
"evmVersion": "london",
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_bridgeAddress","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_wToken","type":"address"}],"stateMutability":"payable","type":"constructor"},{"inputs":[],"name":"BRIDGE_ONLY","type":"error"},{"inputs":[],"name":"CALL_BACK_FAIL","type":"error"},{"inputs":[],"name":"CALL_FUNC_BLACK_LIST","type":"error"},{"inputs":[],"name":"DATA_EMPTY","type":"error"},{"inputs":[],"name":"EMPTY","type":"error"},{"inputs":[],"name":"FEE_MISMATCH","type":"error"},{"inputs":[],"name":"NATIVE_VALUE_OVERSPEND","type":"error"},{"inputs":[],"name":"NOT_CONTRACT","type":"error"},{"inputs":[],"name":"NO_APPROVE","type":"error"},{"inputs":[],"name":"RECEIVE_LOW","type":"error"},{"inputs":[],"name":"SELF_ONLY","type":"error"},{"inputs":[],"name":"SWAP_FAIL","type":"error"},{"inputs":[],"name":"SWAP_SAME_TOKEN","type":"error"},{"inputs":[],"name":"UNSUPPORT_DEX_TYPE","type":"error"},{"inputs":[],"name":"ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"ZERO_IN","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"executor","type":"address"},{"indexed":true,"internalType":"bool","name":"flag","type":"bool"}],"name":"Approve","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"integrator","type":"address"},{"indexed":false,"internalType":"uint256","name":"routerAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"integratorAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nativeAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"integratorNative","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"transferId","type":"bytes32"}],"name":"CollectFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes4","name":"_func","type":"bytes4"},{"indexed":false,"internalType":"bool","name":"flag","type":"bool"}],"name":"EditFuncBlackList","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","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":true,"internalType":"bytes32","name":"orderId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"swapToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"swapAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"callAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fromChain","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toChain","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"from","type":"bytes"}],"name":"RemoteSwapAndCall","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_bridgeAddress","type":"address"}],"name":"SetBridgeAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"uint256","name":"rate","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"fixedf","type":"uint256"}],"name":"SetFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_feeManager","type":"address"}],"name":"SetFeeManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_gasForReFund","type":"uint256"}],"name":"SetGasForReFund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_maxFeeRate","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_maxNativeFee","type":"uint256"}],"name":"SetReferrerMaxFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_wToken","type":"address"}],"name":"SetWrappedToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"address","name":"initiator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"bytes32","name":"transferId","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"orderId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"bridgeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bridgeAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toChain","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"to","type":"bytes"}],"name":"SwapAndBridge","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"address","name":"initiator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"bytes32","name":"transferId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"swapToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"swapAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"callAmount","type":"uint256"}],"name":"SwapAndCall","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_func","type":"bytes4"},{"internalType":"bool","name":"_flag","type":"bool"}],"name":"editFuncBlackList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeManager","outputs":[{"internalType":"contract IFeeManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"funcBlackList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasForReFund","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amountAfterFee","type":"uint256"},{"internalType":"bytes","name":"_feeData","type":"bytes"}],"name":"getAmountBeforeFee","outputs":[{"internalType":"address","name":"feeToken","type":"address"},{"internalType":"uint256","name":"beforeAmount","type":"uint256"},{"internalType":"uint256","name":"nativeFeeAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_inputToken","type":"address"},{"internalType":"uint256","name":"_inputAmount","type":"uint256"},{"internalType":"bytes","name":"_feeData","type":"bytes"}],"name":"getFee","outputs":[{"internalType":"address","name":"feeToken","type":"address"},{"internalType":"uint256","name":"tokenFee","type":"uint256"},{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"afterFeeAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_inputToken","type":"address"},{"internalType":"uint256","name":"_inputAmount","type":"uint256"},{"internalType":"bytes","name":"_feeData","type":"bytes"}],"name":"getFeeDetail","outputs":[{"components":[{"internalType":"address","name":"feeToken","type":"address"},{"internalType":"address","name":"routerReceiver","type":"address"},{"internalType":"address","name":"integrator","type":"address"},{"internalType":"uint256","name":"routerNativeFee","type":"uint256"},{"internalType":"uint256","name":"integratorNativeFee","type":"uint256"},{"internalType":"uint256","name":"routerTokenFee","type":"uint256"},{"internalType":"uint256","name":"integratorTokenFee","type":"uint256"}],"internalType":"struct IFeeManager.FeeDetail","name":"feeDetail","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amountAfterFee","type":"uint256"},{"internalType":"bytes","name":"_feeData","type":"bytes"}],"name":"getInputBeforeFee","outputs":[{"internalType":"address","name":"_feeToken","type":"address"},{"internalType":"uint256","name":"_input","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxNativeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"internalType":"address","name":"_srcToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_fromChain","type":"uint256"},{"internalType":"bytes","name":"_from","type":"bytes"},{"internalType":"bytes","name":"_swapAndCall","type":"bytes"}],"name":"onReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"address","name":"approveTo","type":"address"},{"internalType":"uint256","name":"offset","type":"uint256"},{"internalType":"uint256","name":"extraNativeAmount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct SwapCall.CallbackParam","name":"_callbackParam","type":"tuple"},{"internalType":"address","name":"_callToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"remoteCall","outputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"callAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_srcToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_initBalance","type":"uint256"},{"components":[{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"leftReceiver","type":"address"},{"internalType":"uint256","name":"minAmount","type":"uint256"},{"components":[{"internalType":"enum SwapCall.DexType","name":"dexType","type":"uint8"},{"internalType":"address","name":"callTo","type":"address"},{"internalType":"address","name":"approveTo","type":"address"},{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct SwapCall.SwapData[]","name":"swaps","type":"tuple[]"}],"internalType":"struct SwapCall.SwapParam","name":"swapParam","type":"tuple"}],"name":"remoteSwap","outputs":[{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"rescueFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"routerFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"routerFixedFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_executors","type":"address[]"},{"internalType":"bool","name":"_flag","type":"bool"}],"name":"setAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bridgeAddress","type":"address"}],"name":"setBridgeAddress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeReceiver","type":"address"},{"internalType":"uint256","name":"_feeRate","type":"uint256"},{"internalType":"uint256","name":"_fixedFee","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeManager","type":"address"}],"name":"setFeeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gasForReFund","type":"uint256"}],"name":"setGasForReFund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxFeeRate","type":"uint256"},{"internalType":"uint256","name":"_maxNativeFee","type":"uint256"}],"name":"setReferrerMaxFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wToken","type":"address"}],"name":"setWToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_transferId","type":"bytes32"},{"internalType":"address","name":"_initiator","type":"address"},{"internalType":"address","name":"_srcToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_swapData","type":"bytes"},{"internalType":"bytes","name":"_bridgeData","type":"bytes"},{"internalType":"bytes","name":"_permitData","type":"bytes"},{"internalType":"bytes","name":"_feeData","type":"bytes"}],"name":"swapAndBridge","outputs":[{"internalType":"bytes32","name":"orderId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_transferId","type":"bytes32"},{"internalType":"address","name":"_initiator","type":"address"},{"internalType":"address","name":"_srcToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_swapData","type":"bytes"},{"internalType":"bytes","name":"_callbackData","type":"bytes"},{"internalType":"bytes","name":"_permitData","type":"bytes"},{"internalType":"bytes","name":"_feeData","type":"bytes"}],"name":"swapAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405262013880600d55604051620053ab380380620053ab8339810160408190526200002d9162000418565b81816200003a81620002a0565b5060026020527fe1e73cc31923e6bcd7df033eac8d926dd327070e2255dea700a10acfabdef8c68054600160ff1991821681179092557fe35a139c3b94c056552c39ea59352e3458c2f4bf80c7cc1fa8131aa1536d11c180548216831790557f93043132120d961251ea6e8dbbd6f0f5ec18303f3dcf9ff833544e2c99ffe2ea80548216831790557fa82891a21dcbaf932ffd168b3de5be71a77172f68a75e6a28bc586fcc4c54b9f80548216831790557ff761277f7d8fd4508cc20d65fcf074f430077dd2d7ac9330f5d7f3ae6677dc1080548216831790557f063ee4a8a6581bb9c024bc06de349006da7b6941d99399873a4c8661180402dc80548216831790557fa8974dae24ddfded20eb0b277ec257b81d99ab1a9b97749cf8a0b418e0f2cf5c80548216831790557fa6afc65e3eb88af488764b72e01461c5e252915975b90bcef4390ac5030dd97180548216831790557f95e03a1175780d83ead22dfa661b326775afac6b0f1707dd3d891cf8a0ad556f80548216831790557fd1da40ac9743427d21c428e3c0e5e4496561f97a5a2cd1be0b74f92198dd93ab80548216831790557f01cb0e87ed407db17e65114eafd9fc2296f56be6b6ccc52258528879883a36c38054821683179055631759616b60e11b6000527fcdd1761221296cade29bc5e8a44093b6513834250a44de25064d79433d7cc25f80549091169091179055620002526200024c3390565b62000311565b6001600160a01b0381166200027a5760405163538ba4f960e01b815260040160405180910390fd5b620002858162000311565b506001600a5562000296836200032f565b5050505062000462565b6001600160a01b0381163b620002c9576040516308ebd80360e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b038316908117825560405190917f556b8b8772c1552cbcc67f9bb7c7fd60934af593e54ec7aa4e8b2683632675f891a250565b600480546001600160a01b03191690556200032c81620003a9565b50565b60006001600160a01b0382163b6200035a576040516308ebd80360e11b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0384169081179091556040517f53b7c37d01415b2804281f4684b0722e0b01fbd375bf502609f465e17ab4441e90600090a2506001919050565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200041357600080fd5b919050565b6000806000606084860312156200042e57600080fd5b6200043984620003fb565b92506200044960208501620003fb565b91506200045960408501620003fb565b90509250925092565b614f3980620004726000396000f3fe6080604052600436106101fd5760003560e01c806385c178301161010d578063c1b1660e116100a0578063d904371e1161006f578063d904371e14610678578063df5d452314610698578063e30c3978146106b8578063f2fde38b146106d6578063f5e53a64146106f657600080fd5b8063c1b1660e146105e8578063d0fb020314610608578063d7fc2da414610628578063d8b964e61461064857600080fd5b8063a3c573eb116100dc578063a3c573eb1461053e578063a73ceca71461055e578063b3f00674146105a8578063bce53d24146105c857600080fd5b806385c17830146104b55780638da5cb5b146104cb5780638dc060ff146104e95780639ccef96f146104ff57600080fd5b806352b2d5431161019057806378e3214f1161015f57806378e3214f1461039d57806379ba5097146103bd5780637ae69a98146103d25780637f5a22f914610417578063823991751461043757600080fd5b806352b2d5431461033f578063536f4cfe146103555780636e1537da14610375578063715018a61461038857600080fd5b80632344e655116101cc5780632344e655146102bb578063278fd202146102db578063472d35b9146102fb5780634e36b11c1461031b57600080fd5b80630babd86414610209578063119b82481461024657806311c4b7721461025b578063227c54121461027b57600080fd5b3661020457005b600080fd5b34801561021557600080fd5b50600054610229906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b610259610254366004613b52565b61070c565b005b34801561026757600080fd5b50610259610276366004613c89565b610a7a565b34801561028757600080fd5b506102ab610296366004613cc0565b60026020526000908152604090205460ff1681565b604051901515815260200161023d565b3480156102c757600080fd5b506102596102d6366004613ce2565b610a90565b3480156102e757600080fd5b506102596102f6366004613d80565b610e7d565b34801561030757600080fd5b50610259610316366004613da2565b610ece565b34801561032757600080fd5b50610331600d5481565b60405190815260200161023d565b34801561034b57600080fd5b5061033160065481565b34801561036157600080fd5b50610259610370366004613dbf565b610f48565b610331610383366004613b52565b610f83565b34801561039457600080fd5b506102596112f3565b3480156103a957600080fd5b506102596103b8366004613dd8565b611307565b3480156103c957600080fd5b5061025961131a565b3480156103de57600080fd5b506103f26103ed366004613e04565b611399565b604080516001600160a01b03909416845260208401929092529082015260600161023d565b34801561042357600080fd5b506102ab610432366004613da2565b61151c565b34801561044357600080fd5b50610457610452366004613e04565b61153a565b6040805182516001600160a01b039081168252602080850151821690830152838301511691810191909152606080830151908201526080808301519082015260a0808301519082015260c0918201519181019190915260e00161023d565b3480156104c157600080fd5b5061033160085481565b3480156104d757600080fd5b506003546001600160a01b0316610229565b3480156104f557600080fd5b5061033160055481565b34801561050b57600080fd5b5061051f61051a366004614131565b6116bd565b604080516001600160a01b03909316835260208301919091520161023d565b34801561054a57600080fd5b50600b54610229906001600160a01b031681565b34801561056a57600080fd5b5061057e610579366004613e04565b6116f9565b604080516001600160a01b039095168552602085019390935291830152606082015260800161023d565b3480156105b457600080fd5b50600754610229906001600160a01b031681565b3480156105d457600080fd5b5061051f6105e3366004614193565b6117af565b3480156105f457600080fd5b50610259610603366004614269565b6117eb565b34801561061457600080fd5b50600c54610229906001600160a01b031681565b34801561063457600080fd5b50610259610643366004613da2565b611882565b34801561065457600080fd5b506102ab610663366004613da2565b60016020526000908152604090205460ff1681565b34801561068457600080fd5b5061025961069336600461429e565b611893565b3480156106a457600080fd5b506103f26106b3366004613e04565b6119e9565b3480156106c457600080fd5b506004546001600160a01b0316610229565b3480156106e257600080fd5b506102596106f1366004613da2565b611afc565b34801561070257600080fd5b5061033160095481565b610714611b6d565b61071c6139e3565b6001600160a01b03808d1660c08301528b1680825260408083018c9052608083018f905280516020601f880181900481028201810190925286815261077f92918d91908990899081908401838280828437600092019190915250611bc692505050565b6101a08301526101808201526107958689614339565b6000036107b5576040516312cd5ab760e11b815260040160405180910390fd5b6107bd613a92565b6107d1826000015183604001518686611c66565b846060018560a001826001600160a01b03166001600160a01b03168152508281525082935050505080604001516001600160a01b031681602001516001600160a01b031683600001516001600160a01b03167ffe2e49614659d9447156c9e3846112ea8edda361dcd696be486f6f977ce854e58460a001518560c0015186606001518760800151896080015160405161088c959493929190948552602085019390935260408401919091526060830152608082015260a00190565b60405180910390a461092882600001518360600151846101a001518d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df792505050565b6101208701819052606087018290526001600160a01b039283166020880152928216610100870152921660e085015210156109845761098482602001518360e00151846101200151856060015161097f919061434c565b611e81565b336001600160a01b03168260c001516001600160a01b03168360a001516001600160a01b03167f60656aafa8d4c0a705aeb148b167d7db921d08852cd2261b270d5c7a2e655f83856080015186600001518760200151886040015189606001518a60e001518b61010001518c6101200151604051610a4a9897969594939291909788526001600160a01b039687166020890152948616604088015260608701939093526080860191909152831660a085015290911660c083015260e08201526101000190565b60405180910390a4610a60826101800151611f88565b5050610a6c6001600a55565b505050505050505050505050565b610a82611fa9565b610a8c8282612003565b5050565b610a98611b6d565b610aa06139e3565b6001600160a01b0388168082526040808301899052602080840192909252606083018990526101408301889052466101608401528051601f87018390048302810183019091528581529086908690819084018382808284376000920191909152505050506101c0820152600b546001600160a01b03163314610b35576040516303d6041760e41b815260040160405180910390fd5b6000610b45826000015130612067565b905087811015610b68576040516319af26f360e31b815260040160405180910390fd5b47610180830152610b79888261434c565b6101a083015250600080610b8f8486018661435f565b9150915080518251610ba19190614339565b600003610bc1576040516312cd5ab760e11b815260040160405180910390fd5b600d5482516001919015610ca557600084806020019051810190610be5919061442b565b60208101516001600160a01b031660e08801529050815a1115610ca35730639ccef96f835a610c14919061434c565b88516040808b01516101a08c015191516001600160e01b031960e087901b168152610c459392908890600401614604565b604080518083038160008887f193505050508015610c80575060408051601f3d908101601f19168201909252610c7d91810190614717565b60015b610c8d5760009250610ca3565b6001600160a01b03909116602088015260608701525b505b825115610d9c57600083806020019051810190610cc29190614745565b60e08701519091506001600160a01b0316610ceb5760808101516001600160a01b031660e08701525b828015610cf75750815a115b15610d9a573063bce53d24835a610d0e919061434c565b8389602001518a606001516040518563ffffffff1660e01b8152600401610d3793929190614800565b604080518083038160008887f193505050508015610d72575060408051601f3d908101601f19168201909252610d6f91810190614717565b60015b15610d9a576001600160a01b0391821661010089015261012088015260808201511660e08701525b505b84610120015185606001511115610dcf57610dcf85602001518660e00151876101200151886060015161097f919061434c565b8461010001516001600160a01b03168560e001516001600160a01b03168e7f593e4dbcb8f7312fc3bdd77e2095da131a6e1993f37752d12576d04e1f7253b4886000015189602001518a604001518b606001518c61012001518d61014001518e61016001518f6101c00151604051610e4e989796959493929190614871565b60405180910390a4610e64856101800151611f88565b5050505050610e736001600a55565b5050505050505050565b610e85611fa9565b6127108210610e9357600080fd5b60088290556009819055604051819083907f5b2f81a75439605ecd08ce07af893a489989a97d6d2008dff44c6827503ba82c90600090a35050565b610ed6611fa9565b6001600160a01b0381163b610efe576040516308ebd80360e11b815260040160405180910390fd5b600c80546001600160a01b0319166001600160a01b0383169081179091556040517f5d0517e3a4eabea892d9750138cd21d4a6cf3b935b43d0598df7055f463819b290600090a250565b610f50611fa9565b600d81905560405181907ff47543a7cab136b12cca0a2ecd728c9d1943f57b923b98db48725d2b76dd4da990600090a250565b6000610f8d611b6d565b610f978689614339565b600003610fb7576040516312cd5ab760e11b815260040160405180910390fd5b610fbf6139e3565b8c8160c001906001600160a01b031690816001600160a01b0316815250508b81600001906001600160a01b031690816001600160a01b0316815250508a8160400181815250508b81602001906001600160a01b031690816001600160a01b0316815250508a8160600181815250508d8160800181815250506110808160000151826040015188888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bc692505050565b6101a08301526101808201526060611096613a92565b6110aa836000015184604001518888611c66565b6001600160a01b031660a0860152606085015290508a1561116c5760006110d38c8e018e6148ca565b90506110ee84600001518560600151866101a00151846120fb565b60608601526001600160a01b03166020850152891580156111125750606084015115155b1561116a57602080820151604051611142920160609190911b6bffffffffffffffffffffffff1916815260140190565b604051602081830303815290604052925061116a846020015182602001518660600151611e81565b505b88156111ad5760006111808a8c018c6148fe565b80516101608601526040810151602086015160608701519195509192506111a9913391846121c4565b9450505b80604001516001600160a01b031681602001516001600160a01b031684600001516001600160a01b03167ffe2e49614659d9447156c9e3846112ea8edda361dcd696be486f6f977ce854e58460a001518560c00151866060015187608001518b60405161123c959493929190948552602085019390935260408401919091526060830152608082015260a00190565b60405180910390a4336001600160a01b03168360c001516001600160a01b03168460a001516001600160a01b03167fba828651bf4de06e53231285961e555fd7dfe17a3e39d64b09fbaa8ebc0166c6866080015188886000015189602001518a604001518b606001518c61016001518c6040516112c09897969594939291906149a2565b60405180910390a46112d6836101800151611f88565b5050506112e36001600a55565b9c9b505050505050505050505050565b6112fb611fa9565b61130560006122a4565b565b61130f611fa9565b610a8c823383611e81565b60045433906001600160a01b0316811461138d5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b611396816122a4565b50565b6000806000806113a986866122bd565b6007549091506001600160a01b03161580156113d0575060208101516001600160a01b0316155b156113e657600087600093509350935050611512565b6007546000906001600160a01b03161561141a576006546114079084614339565b9250600554816114179190614339565b90505b60208201516001600160a01b03161561146f57600082516001811115611442576114426145c2565b0361145d5760408201516114569084614339565b925061146f565b604082015161146c9082614339565b90505b6001600160a01b03891615806114a1575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b038a16145b156114ed576114b08389614339565b935080156114e8576114c48161271061434c565b6114d0612710866149ec565b6114da9190614a03565b6114e5906001614339565b93505b61150f565b801561150b576114ff8161271061434c565b6114d06127108a6149ec565b8793505b50505b9450945094915050565b6000611526611fa9565b61152f826123b7565b50600190505b919050565b611542613a92565b600061154e84846122bd565b6007549091506001600160a01b0316158015611575575060208101516001600160a01b0316155b1561158057506116b5565b6001600160a01b038087168352600754161561160c576007546001600160a01b039081166020840152600654606084015286166115eb57612710600554866115c891906149ec565b6115d29190614a03565b826060018181516115e39190614339565b90525061160c565b612710600554866115fc91906149ec565b6116069190614a03565b60a08301525b60208101516001600160a01b0316156116b35760208101516001600160a01b03166040830152600081516001811115611647576116476145c2565b0361165b57604081015160808301526116b3565b6001600160a01b0386166116905761271081604001518661167c91906149ec565b6116869190614a03565b60808301526116b3565b6127108160400151866116a391906149ec565b6116ad9190614a03565b60c08301525b505b949350505050565b6000803330146116e057604051632ee47ea160e11b815260040160405180910390fd5b6116ec868686866120fb565b9097909650945050505050565b600080600080600061170d89898989612430565b80519550905061171c89612539565b1561176a576000935080608001518160c001518260a0015183606001516117439190614339565b61174d9190614339565b6117579190614339565b9250611763838961434c565b91506117a3565b8060c001518160a0015161177e9190614339565b9350806080015181606001516117949190614339565b92506117a0848961434c565b91505b50945094509450949050565b6000803330146117d257604051632ee47ea160e11b815260040160405180910390fd5b845191506117e1838587612572565b9050935093915050565b6117f3611fa9565b6001600160a01b03831661181a5760405163538ba4f960e01b815260040160405180910390fd5b612710821061182857600080fd5b600780546001600160a01b0319166001600160a01b03851690811790915560058390556006829055604051829184917f17906aa05b055ced1cea92b104912638c3ec8c90eec152fca6f36fbd8becca1d90600090a4505050565b61188a611fa9565b611396816126fc565b61189b611fa9565b60008290036118bd57604051630239912560e01b815260040160405180910390fd5b60005b828110156119e3576119018484838181106118dd576118dd614a25565b90506020020160208101906118f29190613da2565b6001600160a01b03163b151590565b61191e576040516308ebd80360e11b815260040160405180910390fd5b816001600086868581811061193557611935614a25565b905060200201602081019061194a9190613da2565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905581151584848381811061198757611987614a25565b905060200201602081019061199c9190613da2565b6001600160a01b03167f1f478f1e5aee36a892d86e821aba410dc0934cb0ebd0241dd75370833884545360405160405180910390a3806119db81614a3b565b9150506118c0565b50505050565b600c54600090819081906001600160a01b0316611a7557604051630f5cd35360e31b81523090637ae69a9890611a29908a908a908a908a90600401614a54565b606060405180830381865afa158015611a46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6a9190614a9c565b925092509250611512565b600c54604051630f5cd35360e31b81526001600160a01b0390911690637ae69a9890611aab908a908a908a908a90600401614a54565b606060405180830381865afa158015611ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aec9190614a9c565b9250925092509450945094915050565b611b04611fa9565b600480546001600160a01b0383166001600160a01b03199091168117909155611b356003546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6002600a5403611bbf5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611384565b6002600a55565b60008083600003611bea5760405163090b95c560e31b815260040160405180910390fd5b825115611bfa57611bfa8361276c565b611c04344761434c565b9150611c0f85612539565b15611c465783341015611c3557604051637d6b3cdf60e11b815260040160405180910390fd5b611c3f844761434c565b9050611c5e565b611c508530612067565b9050611c5e853330876127b7565b935093915050565b611c6e613a92565b600080611c7d87878787612430565b925082604001519050611c8f87612539565b15611d0c5760008360a001518460600151611caa9190614339565b90508015611cc157611cc188856020015183611e81565b600084608001518560c00151611cd79190614339565b90508015611cee57611cee89866040015183611e81565b80611cf9838a61434c565b611d03919061434c565b93505050611dd6565b606083015115611d2a57611d2a600084602001518560600151611e81565b60a083015115611d4757611d478784602001518560a00151611e81565b608083015115611d6557611d65600084604001518560800151611e81565b60c083015115611d8257611d828784604001518560c00151611e81565b60c083015160a0840151611d96908861434c565b611da0919061434c565b91503483608001518460600151611db79190614339565b1115611dd657604051637d6b3cdf60e11b815260040160405180910390fd5b816000036115125760405163090b95c560e31b815260040160405180910390fd5b8151600090819087908790839015611e3a57600087806020019051810190611e1f919061442b565b9050611e2d8b8b8b846120fb565b6020909201519650935091505b855115611e7457600086806020019051810190611e579190614745565b9050611e64838583612572565b6080820151915191965090945090505b9550955095509550959050565b611e8a83612539565b15611e9e57611e998282612822565b505050565b46632b6653dc81148015611ece575073a614f803b6fd780986a42c78ec9c7f77e6ded13c6001600160a01b038516145b15611f7457604080516001600160a01b038581166024830152604480830186905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915191861691611f2a9190614ad3565b6000604051808303816000865af19150503d8060008114611f67576040519150601f19603f3d011682016040523d82523d6000602084013e611f6c565b606091505b5050506119e3565b6119e36001600160a01b038516848461293b565b8047101561139657604051630cfbd6ed60e01b815260040160405180910390fd5b6003546001600160a01b031633146113055760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611384565b6001600160e01b03198216600081815260026020908152604091829020805460ff19168515159081179091558251938452908301527fc4a5aadd92b2d0e7efaf25f9d44b0e6fca6c44da8e09fc3250cc12ef954cb60e910160405180910390a15050565b600061207283612539565b1561208857506001600160a01b038116316120f5565b6040516370a0823160e01b81526001600160a01b0383811660048301528416906370a0823190602401602060405180830381865afa1580156120ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f29190614aef565b90505b92915050565b805160006001600160a01b038083169087160361212e576040516001624cdd6d60e11b0319815260040160405180910390fd5b600061213e846000015130612067565b905061214b87878661296b565b8061215a856000015130612067565b612164919061434c565b9150836060015182101561218b576040516319af26f360e31b815260040160405180910390fd5b6000856121988930612067565b6121a2919061434c565b905080156121b9576121b988866040015183611e81565b505094509492505050565b600b5460009081906001600160a01b03166121de86612539565b156121f95760208401516121f29086614339565b9150612214565b602084015191506122146001600160a01b0387168287612bf0565b604080850151855160608701519251632e267e4160e21b81526001600160a01b0385169363b899f904938793612256938e938e93928e92909190600401614b08565b60206040518083038185885af1158015612274573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906122999190614aef565b979650505050505050565b600480546001600160a01b031916905561139681612c7f565b604080516060810182526000808252602082018190529181019190915281156120f5576122ec82840184614b5f565b9050600181516001811115612303576123036145c2565b036123625760085481604001511061235d5760405162461bcd60e51b815260206004820152601b60248201527f4665654d616e616765723a20696e76616c6964206665655261746500000000006044820152606401611384565b6120f5565b6009548160400151106120f55760405162461bcd60e51b815260206004820152601e60248201527f4665654d616e616765723a20696e76616c6964206e61746976652066656500006044820152606401611384565b60006001600160a01b0382163b6123e1576040516308ebd80360e11b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0384169081179091556040517f53b7c37d01415b2804281f4684b0722e0b01fbd375bf502609f465e17ab4441e90600090a2506001919050565b612438613a92565b600c546001600160a01b03166124b957604051638239917560e01b81523090638239917590612471908890889088908890600401614a54565b60e060405180830381865afa15801561248e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b29190614bcd565b90506116b5565b600c54604051638239917560e01b81526001600160a01b03909116906382399175906124ef908890889088908890600401614a54565b60e060405180830381865afa15801561250c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125309190614bcd565b95945050505050565b60006001600160a01b03821615806120f557506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b600061257e8330612067565b604083015160a084015191925090602382111561259b5785828201525b83516125a79082612cd1565b60006125b286612539565b156126215784600001516001600160a01b031687836040516125d49190614ad3565b60006040518083038185875af1925050503d8060008114612611576040519150601f19603f3d011682016040523d82523d6000602084013e612616565b606091505b5050809150506126ca565b8615612641576020850151612641906001600160a01b0388169089612dda565b84600001516001600160a01b03168560600151836040516126629190614ad3565b60006040518083038185875af1925050503d806000811461269f576040519150601f19603f3d011682016040523d82523d6000602084013e6126a4565b606091505b509091505086156126ca5760208501516126ca906001600160a01b038816906000612e87565b806126e857604051637588692960e01b815260040160405180910390fd5b6126f28630612067565b612299908561434c565b6001600160a01b0381163b612724576040516308ebd80360e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b038316908117825560405190917f556b8b8772c1552cbcc67f9bb7c7fd60934af593e54ec7aa4e8b2683632675f891a250565b6000806000806000806000808880602001905181019061278c9190614c6b565b975097509750975097509750975097506127ac8888888888888888612f9c565b505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526119e39085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613166565b804710156128725760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401611384565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146128bf576040519150601f19603f3d011682016040523d82523d6000602084013e6128c4565b606091505b5050905080611e995760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401611384565b6040516001600160a01b038316602482015260448101829052611e9990849063a9059cbb60e01b906064016127eb565b608081015151600081900361299357604051630239912560e01b815260040160405180910390fd5b60008060006129a78685876080015161323b565b6080880151929550909350915060006129bf89612539565b905060005b86811015612be4578415612abc5780600003612a4d5783612a1557848382815181106129f2576129f2614a25565b6020026020010151606001818151612a0a919061434c565b915081815250612a47565b84838281518110612a2857612a28614a25565b6020026020010151606001818151612a409190614339565b9150818152505b50612abc565b83612a885785838281518110612a6557612a65614a25565b6020026020010151606001818151612a7d919061434c565b915081815250612aba565b85838281518110612a9b57612a9b614a25565b6020026020010151606001818151612ab39190614339565b9150818152505b505b81612b1957612b19838281518110612ad657612ad6614a25565b602002602001015160400151848381518110612af457612af4614a25565b6020026020010151606001518c6001600160a01b0316612dda9092919063ffffffff16565b612b9b838281518110612b2e57612b2e614a25565b60200260200101516000015183858481518110612b4d57612b4d614a25565b6020026020010151602001518d878681518110612b6c57612b6c614a25565b602002602001015160600151888781518110612b8a57612b8a614a25565b602002602001015160800151613325565b81612bdc57612bdc838281518110612bb557612bb5614a25565b60200260200101516040015160008c6001600160a01b0316612e879092919063ffffffff16565b6001016129c4565b50505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052612c4184826133b7565b6119e3576040516001600160a01b038416602482015260006044820152612c7590859063095ea7b360e01b906064016127eb565b6119e38482613166565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000546001600160a01b039081169083168114801590612d0a57506001600160a01b03831660009081526001602052604090205460ff16155b15612d285760405163369370d960e01b815260040160405180910390fd5b6000612d338361345a565b6001600160e01b0319811660009081526002602052604090205490915060ff1615612d7157604051630d1a468960e01b815260040160405180910390fd5b816001600160a01b0316846001600160a01b0316036119e3576001600160e01b03198116632e1a7d4d60e01b14801590612dbc57506001600160e01b03198116630d0e30db60e41b14155b156119e357604051630d1a468960e01b815260040160405180910390fd5b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015612e2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e4e9190614aef565b90506119e38463095ea7b360e01b85612e678686614339565b6040516001600160a01b03909216602483015260448201526064016127eb565b801580612f015750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015612edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eff9190614aef565b155b612f6c5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401611384565b6040516001600160a01b038316602482015260448101829052611e9990849063095ea7b360e01b906064016127eb565b604051623f675f60e91b81526001600160a01b038881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015612fe5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130099190614aef565b60405163d505accf60e01b81526001600160a01b038a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b15801561307d57600080fd5b505af1158015613091573d6000803e3d6000fd5b5050604051623f675f60e91b81526001600160a01b038b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa1580156130dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131019190614aef565b905061310e826001614339565b8114612be45760405162461bcd60e51b815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f74207375636365656044820152601960fa1b6064820152608401611384565b60006131bb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134759092919063ffffffff16565b90508051600014806131dc5750808060200190518101906131dc9190614cf7565b611e995760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401611384565b6000808080805b868110156132875785818151811061325c5761325c614a25565b602002602001015160600151826132739190614339565b91508061327f81614a3b565b915050613242565b50868111156132d357600091508161329f888361434c565b90506132ab8782614a03565b94506132b787866149ec565b6132c1908261434c565b6132cb9086614339565b93505061331b565b8681101561331b576001915060006132eb828961434c565b90506132f78782614a03565b945061330387866149ec565b61330d908261434c565b6133179086614339565b9350505b5093509350939050565b6000600487600581111561333b5761333b6145c2565b036133535761334c85848885613484565b9050613390565b6005876005811115613367576133676145c2565b036133775761334c8484846135d1565b6040516318f9c3a760e11b815260040160405180910390fd5b806133ae57604051636ff55bbf60e01b815260040160405180910390fd5b50505050505050565b6000806000846001600160a01b0316846040516133d49190614ad3565b6000604051808303816000865af19150503d8060008114613411576040519150601f19603f3d011682016040523d82523d6000602084013e613416565b606091505b50915091508180156134405750805115806134405750808060200190518101906134409190614cf7565b80156125305750505050506001600160a01b03163b151590565b6000815160000361346d57506000919050565b506020015190565b60606116b5848460008561387a565b60008060008380602001905181019061349d9190614d14565b8151919350915060005b818110156134ef5760008482815181106134c3576134c3614a25565b6020026020010151905060238111156134dc5788818501525b50806134e781614a3b565b9150506134a7565b506134fa8883612cd1565b851561356657876001600160a01b031687836040516135199190614ad3565b60006040518083038185875af1925050503d8060008114613556576040519150601f19603f3d011682016040523d82523d6000602084013e61355b565b606091505b5050809450506135c6565b876001600160a01b03168260405161357e9190614ad3565b6000604051808303816000865af19150503d80600081146135bb576040519150601f19603f3d011682016040523d82523d6000602084013e6135c0565b606091505b50909450505b505050949350505050565b600080828060200190518101906135e89190614dc5565b905060005b81518110156138715780156136465761362382828151811061361157613611614a25565b60200260200101516020015130612067565b945081818151811061363757613637614a25565b60200260200101516020015195505b600082828151811061365a5761365a614a25565b6020026020010151608001519050600083838151811061367c5761367c614a25565b602002602001015160000151905060238111156136995786818301525b6136c08484815181106136ae576136ae614a25565b60200260200101516040015183612cd1565b6136c988612539565b15613751578383815181106136e0576136e0614a25565b6020026020010151604001516001600160a01b031687836040516137049190614ad3565b60006040518083038185875af1925050503d8060008114613741576040519150601f19603f3d011682016040523d82523d6000602084013e613746565b606091505b505080955050613850565b82156137925761379284848151811061376c5761376c614a25565b602002602001015160600151888a6001600160a01b0316612dda9092919063ffffffff16565b8383815181106137a4576137a4614a25565b6020026020010151604001516001600160a01b0316826040516137c79190614ad3565b6000604051808303816000865af19150503d8060008114613804576040519150601f19603f3d011682016040523d82523d6000602084013e613809565b606091505b509095505082156138505761385084848151811061382957613829614a25565b60200260200101516060015160008a6001600160a01b0316612e879092919063ffffffff16565b8461385c575050613871565b5050808061386990614a3b565b9150506135ed565b50509392505050565b6060824710156138db5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401611384565b600080866001600160a01b031685876040516138f79190614ad3565b60006040518083038185875af1925050503d8060008114613934576040519150601f19603f3d011682016040523d82523d6000602084013e613939565b606091505b509150915061229987838387606083156139b45782516000036139ad576001600160a01b0385163b6139ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611384565b50816116b5565b6116b583838151156139c95781518083602001fd5b8060405162461bcd60e51b81526004016113849190614ef0565b604051806101e0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000801916815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008152602001606081525090565b6040518060e0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b038116811461139657600080fd5b803561153581613aea565b60008083601f840112613b1c57600080fd5b5081356001600160401b03811115613b3357600080fd5b602083019150836020828501011115613b4b57600080fd5b9250929050565b6000806000806000806000806000806000806101008d8f031215613b7557600080fd5b8c359b50613b8560208e01613aff565b9a50613b9360408e01613aff565b995060608d013598506001600160401b0360808e01351115613bb457600080fd5b613bc48e60808f01358f01613b0a565b90985096506001600160401b0360a08e01351115613be157600080fd5b613bf18e60a08f01358f01613b0a565b90965094506001600160401b0360c08e01351115613c0e57600080fd5b613c1e8e60c08f01358f01613b0a565b90945092506001600160401b0360e08e01351115613c3b57600080fd5b613c4b8e60e08f01358f01613b0a565b81935080925050509295989b509295989b509295989b565b80356001600160e01b03198116811461153557600080fd5b801515811461139657600080fd5b60008060408385031215613c9c57600080fd5b613ca583613c63565b91506020830135613cb581613c7b565b809150509250929050565b600060208284031215613cd257600080fd5b613cdb82613c63565b9392505050565b60008060008060008060008060c0898b031215613cfe57600080fd5b883597506020890135613d1081613aea565b9650604089013595506060890135945060808901356001600160401b0380821115613d3a57600080fd5b613d468c838d01613b0a565b909650945060a08b0135915080821115613d5f57600080fd5b50613d6c8b828c01613b0a565b999c989b5096995094979396929594505050565b60008060408385031215613d9357600080fd5b50508035926020909101359150565b600060208284031215613db457600080fd5b8135613cdb81613aea565b600060208284031215613dd157600080fd5b5035919050565b60008060408385031215613deb57600080fd5b8235613df681613aea565b946020939093013593505050565b60008060008060608587031215613e1a57600080fd5b8435613e2581613aea565b93506020850135925060408501356001600160401b03811115613e4757600080fd5b613e5387828801613b0a565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715613e9757613e97613e5f565b60405290565b60405160c081016001600160401b0381118282101715613e9757613e97613e5f565b604051608081016001600160401b0381118282101715613e9757613e97613e5f565b604051601f8201601f191681016001600160401b0381118282101715613f0957613f09613e5f565b604052919050565b60006001600160401b03821115613f2a57613f2a613e5f565b5060051b60200190565b6006811061139657600080fd5b60006001600160401b03821115613f5a57613f5a613e5f565b50601f01601f191660200190565b600082601f830112613f7957600080fd5b8135613f8c613f8782613f41565b613ee1565b818152846020838601011115613fa157600080fd5b816020850160208301376000918101602001919091529392505050565b600060a08284031215613fd057600080fd5b613fd8613e75565b90508135613fe581613aea565b8152602082810135613ff681613aea565b82820152604083013561400881613aea565b6040830152606083810135818401526080808501356001600160401b038082111561403257600080fd5b818701915087601f83011261404657600080fd5b8135614054613f8782613f11565b81815260059190911b8301860190868101908a83111561407357600080fd5b8785015b8381101561411d5780358581111561408f5760008081fd5b860160a0818e03601f190112156140a65760008081fd5b6140ae613e75565b8a8201356140bb81613f34565b815260408201356140cb81613aea565b818c0152818a01356140dc81613aea565b6040820152818901358a82015260a0820135878111156140fc5760008081fd5b61410a8f8d83860101613f68565b828b015250845250918801918801614077565b5080868a0152505050505050505092915050565b6000806000806080858703121561414757600080fd5b843561415281613aea565b9350602085013592506040850135915060608501356001600160401b0381111561417b57600080fd5b61418787828801613fbe565b91505092959194509250565b6000806000606084860312156141a857600080fd5b83356001600160401b03808211156141bf57600080fd5b9085019060c082880312156141d357600080fd5b6141db613e9d565b82356141e681613aea565b815260208301356141f681613aea565b806020830152506040830135604082015260608301356060820152608083013561421f81613aea565b608082015260a08301358281111561423657600080fd5b61424289828601613f68565b60a083015250945061425991505060208501613aff565b9150604084013590509250925092565b60008060006060848603121561427e57600080fd5b833561428981613aea565b95602085013595506040909401359392505050565b6000806000604084860312156142b357600080fd5b83356001600160401b03808211156142ca57600080fd5b818601915086601f8301126142de57600080fd5b8135818111156142ed57600080fd5b8760208260051b850101111561430257600080fd5b6020928301955093505084013561431881613c7b565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b808201808211156120f5576120f5614323565b818103818111156120f5576120f5614323565b6000806040838503121561437257600080fd5b82356001600160401b038082111561438957600080fd5b61439586838701613f68565b935060208501359150808211156143ab57600080fd5b506143b885828601613f68565b9150509250929050565b60005b838110156143dd5781810151838201526020016143c5565b50506000910152565b600082601f8301126143f757600080fd5b8151614405613f8782613f41565b81815284602083860101111561441a57600080fd5b6116b58260208301602087016143c2565b6000602080838503121561443e57600080fd5b82516001600160401b038082111561445557600080fd5b9084019060a0828703121561446957600080fd5b614471613e75565b825161447c81613aea565b81528284015161448b81613aea565b81850152604083015161449d81613aea565b604082015260608381015190820152608080840151838111156144bf57600080fd5b80850194505087601f8501126144d457600080fd5b83516144e2613f8782613f11565b81815260059190911b8501860190868101908a83111561450157600080fd5b8787015b838110156145ad5780518781111561451d5760008081fd5b880160a0818e03601f190112156145345760008081fd5b61453c613e75565b8a82015161454981613f34565b8152604082015161455981613aea565b818c0152606082015161456b81613aea565b604082015281870151606082015260a08201518981111561458c5760008081fd5b61459a8f8d838601016143e6565b8289015250845250918801918801614505565b50928401929092525090979650505050505050565b634e487b7160e01b600052602160045260246000fd5b600081518084526145f08160208601602086016143c2565b601f01601f19169290920160200192915050565b6000608060018060a01b038088168452602087818601526040878187015260608481880152610120870184895116868901528389015160a0868216818b015286858c01511660c08b0152838b015160e08b0152878b01519150806101008b01528282518085526101409450848c019150848160051b8d0101945087840193506000805b828110156146ff578d870361013f1901845285518051600681106146b957634e487b7160e01b84526021600452602484fd5b8852808b01518c168b890152898101518c168a89015288810151898901528c01518c88018690526146ec868901826145d8565b9750509489019492890192600101614687565b50505050505080965050505050505095945050505050565b6000806040838503121561472a57600080fd5b825161473581613aea565b6020939093015192949293505050565b60006020828403121561475757600080fd5b81516001600160401b038082111561476e57600080fd5b9083019060c0828603121561478257600080fd5b61478a613e9d565b825161479581613aea565b815260208301516147a581613aea565b80602083015250604083015160408201526060830151606082015260808301516147ce81613aea565b608082015260a0830151828111156147e557600080fd5b6147f1878286016143e6565b60a08301525095945050505050565b60608152600060018060a01b03808651166060840152806020870151166080840152604086015160a0840152606086015160c08401528060808701511660e084015260a086015160c061010085015261485d6101208501826145d8565b959091166020840152505060400152919050565b600061010060018060a01b03808c168452808b166020850152508860408401528760608401528660808401528560a08401528460c08401528060e08401526148bb818401856145d8565b9b9a5050505050505050505050565b6000602082840312156148dc57600080fd5b81356001600160401b038111156148f257600080fd5b6116b584828501613fbe565b60006020828403121561491057600080fd5b81356001600160401b038082111561492757600080fd5b908301906080828603121561493b57600080fd5b614943613ebf565b823581526020830135602082015260408301358281111561496357600080fd5b61496f87828601613f68565b60408301525060608301358281111561498757600080fd5b61499387828601613f68565b60608301525095945050505050565b60006101008a835289602084015260018060a01b03808a1660408501528089166060850152508660808401528560a08401528460c08401528060e08401526148bb818401856145d8565b80820281158282048414176120f5576120f5614323565b600082614a2057634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b600060018201614a4d57614a4d614323565b5060010190565b6001600160a01b0385168152602081018490526060604082018190528101829052818360808301376000818301608090810191909152601f909201601f191601019392505050565b600080600060608486031215614ab157600080fd5b8351614abc81613aea565b602085015160409095015190969495509392505050565b60008251614ae58184602087016143c2565b9190910192915050565b600060208284031215614b0157600080fd5b5051919050565b6001600160a01b0387811682528616602082015260c060408201819052600090614b34908301876145d8565b85606084015284608084015282810360a0840152614b5281856145d8565b9998505050505050505050565b600060608284031215614b7157600080fd5b604051606081018181106001600160401b0382111715614b9357614b93613e5f565b604052823560028110614ba557600080fd5b81526020830135614bb581613aea565b60208201526040928301359281019290925250919050565b600060e08284031215614bdf57600080fd5b60405160e081018181106001600160401b0382111715614c0157614c01613e5f565b6040528251614c0f81613aea565b81526020830151614c1f81613aea565b60208201526040830151614c3281613aea565b80604083015250606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600080600080600080600080610100898b031215614c8857600080fd5b8851614c9381613aea565b60208a0151909850614ca481613aea565b60408a0151909750614cb581613aea565b80965050606089015194506080890151935060a089015160ff81168114614cdb57600080fd5b60c08a015160e0909a0151989b979a5095989497939692505050565b600060208284031215614d0957600080fd5b8151613cdb81613c7b565b60008060408385031215614d2757600080fd5b82516001600160401b0380821115614d3e57600080fd5b818501915085601f830112614d5257600080fd5b81516020614d62613f8783613f11565b82815260059290921b84018101918181019089841115614d8157600080fd5b948201945b83861015614d9f57855182529482019490820190614d86565b91880151919650909350505080821115614db857600080fd5b506143b8858286016143e6565b60006020808385031215614dd857600080fd5b82516001600160401b0380821115614def57600080fd5b818501915085601f830112614e0357600080fd5b8151614e11613f8782613f11565b81815260059190911b83018401908481019088831115614e3057600080fd5b8585015b83811015614ee357805185811115614e4c5760008081fd5b860160a0818c03601f1901811315614e645760008081fd5b614e6c613e75565b898301518152604080840151614e8181613aea565b828c0152606084810151614e9481613aea565b8083850152506080915081850151614eab81613aea565b90830152918301519188831115614ec25760008081fd5b614ed08e8c858701016143e6565b9082015285525050918601918601614e34565b5098975050505050505050565b602081526000613cdb60208301846145d856fea264697066735822122038becc5f4178fb79c9c9f7688f531bb6edfdc8469b83492031e677df022c3acf64736f6c63430008140033000000000000000000000000feb2b97e4efce787c08086dc16ab69e063911380000000000000000000000000df3f1ee5baf55055980887aad79f6fe6e3302d9300000000000000000000000078c1b0c915c4faa5fffa6cabf0219da63d7f4cb8
Deployed Bytecode
0x6080604052600436106101fd5760003560e01c806385c178301161010d578063c1b1660e116100a0578063d904371e1161006f578063d904371e14610678578063df5d452314610698578063e30c3978146106b8578063f2fde38b146106d6578063f5e53a64146106f657600080fd5b8063c1b1660e146105e8578063d0fb020314610608578063d7fc2da414610628578063d8b964e61461064857600080fd5b8063a3c573eb116100dc578063a3c573eb1461053e578063a73ceca71461055e578063b3f00674146105a8578063bce53d24146105c857600080fd5b806385c17830146104b55780638da5cb5b146104cb5780638dc060ff146104e95780639ccef96f146104ff57600080fd5b806352b2d5431161019057806378e3214f1161015f57806378e3214f1461039d57806379ba5097146103bd5780637ae69a98146103d25780637f5a22f914610417578063823991751461043757600080fd5b806352b2d5431461033f578063536f4cfe146103555780636e1537da14610375578063715018a61461038857600080fd5b80632344e655116101cc5780632344e655146102bb578063278fd202146102db578063472d35b9146102fb5780634e36b11c1461031b57600080fd5b80630babd86414610209578063119b82481461024657806311c4b7721461025b578063227c54121461027b57600080fd5b3661020457005b600080fd5b34801561021557600080fd5b50600054610229906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b610259610254366004613b52565b61070c565b005b34801561026757600080fd5b50610259610276366004613c89565b610a7a565b34801561028757600080fd5b506102ab610296366004613cc0565b60026020526000908152604090205460ff1681565b604051901515815260200161023d565b3480156102c757600080fd5b506102596102d6366004613ce2565b610a90565b3480156102e757600080fd5b506102596102f6366004613d80565b610e7d565b34801561030757600080fd5b50610259610316366004613da2565b610ece565b34801561032757600080fd5b50610331600d5481565b60405190815260200161023d565b34801561034b57600080fd5b5061033160065481565b34801561036157600080fd5b50610259610370366004613dbf565b610f48565b610331610383366004613b52565b610f83565b34801561039457600080fd5b506102596112f3565b3480156103a957600080fd5b506102596103b8366004613dd8565b611307565b3480156103c957600080fd5b5061025961131a565b3480156103de57600080fd5b506103f26103ed366004613e04565b611399565b604080516001600160a01b03909416845260208401929092529082015260600161023d565b34801561042357600080fd5b506102ab610432366004613da2565b61151c565b34801561044357600080fd5b50610457610452366004613e04565b61153a565b6040805182516001600160a01b039081168252602080850151821690830152838301511691810191909152606080830151908201526080808301519082015260a0808301519082015260c0918201519181019190915260e00161023d565b3480156104c157600080fd5b5061033160085481565b3480156104d757600080fd5b506003546001600160a01b0316610229565b3480156104f557600080fd5b5061033160055481565b34801561050b57600080fd5b5061051f61051a366004614131565b6116bd565b604080516001600160a01b03909316835260208301919091520161023d565b34801561054a57600080fd5b50600b54610229906001600160a01b031681565b34801561056a57600080fd5b5061057e610579366004613e04565b6116f9565b604080516001600160a01b039095168552602085019390935291830152606082015260800161023d565b3480156105b457600080fd5b50600754610229906001600160a01b031681565b3480156105d457600080fd5b5061051f6105e3366004614193565b6117af565b3480156105f457600080fd5b50610259610603366004614269565b6117eb565b34801561061457600080fd5b50600c54610229906001600160a01b031681565b34801561063457600080fd5b50610259610643366004613da2565b611882565b34801561065457600080fd5b506102ab610663366004613da2565b60016020526000908152604090205460ff1681565b34801561068457600080fd5b5061025961069336600461429e565b611893565b3480156106a457600080fd5b506103f26106b3366004613e04565b6119e9565b3480156106c457600080fd5b506004546001600160a01b0316610229565b3480156106e257600080fd5b506102596106f1366004613da2565b611afc565b34801561070257600080fd5b5061033160095481565b610714611b6d565b61071c6139e3565b6001600160a01b03808d1660c08301528b1680825260408083018c9052608083018f905280516020601f880181900481028201810190925286815261077f92918d91908990899081908401838280828437600092019190915250611bc692505050565b6101a08301526101808201526107958689614339565b6000036107b5576040516312cd5ab760e11b815260040160405180910390fd5b6107bd613a92565b6107d1826000015183604001518686611c66565b846060018560a001826001600160a01b03166001600160a01b03168152508281525082935050505080604001516001600160a01b031681602001516001600160a01b031683600001516001600160a01b03167ffe2e49614659d9447156c9e3846112ea8edda361dcd696be486f6f977ce854e58460a001518560c0015186606001518760800151896080015160405161088c959493929190948552602085019390935260408401919091526060830152608082015260a00190565b60405180910390a461092882600001518360600151846101a001518d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df792505050565b6101208701819052606087018290526001600160a01b039283166020880152928216610100870152921660e085015210156109845761098482602001518360e00151846101200151856060015161097f919061434c565b611e81565b336001600160a01b03168260c001516001600160a01b03168360a001516001600160a01b03167f60656aafa8d4c0a705aeb148b167d7db921d08852cd2261b270d5c7a2e655f83856080015186600001518760200151886040015189606001518a60e001518b61010001518c6101200151604051610a4a9897969594939291909788526001600160a01b039687166020890152948616604088015260608701939093526080860191909152831660a085015290911660c083015260e08201526101000190565b60405180910390a4610a60826101800151611f88565b5050610a6c6001600a55565b505050505050505050505050565b610a82611fa9565b610a8c8282612003565b5050565b610a98611b6d565b610aa06139e3565b6001600160a01b0388168082526040808301899052602080840192909252606083018990526101408301889052466101608401528051601f87018390048302810183019091528581529086908690819084018382808284376000920191909152505050506101c0820152600b546001600160a01b03163314610b35576040516303d6041760e41b815260040160405180910390fd5b6000610b45826000015130612067565b905087811015610b68576040516319af26f360e31b815260040160405180910390fd5b47610180830152610b79888261434c565b6101a083015250600080610b8f8486018661435f565b9150915080518251610ba19190614339565b600003610bc1576040516312cd5ab760e11b815260040160405180910390fd5b600d5482516001919015610ca557600084806020019051810190610be5919061442b565b60208101516001600160a01b031660e08801529050815a1115610ca35730639ccef96f835a610c14919061434c565b88516040808b01516101a08c015191516001600160e01b031960e087901b168152610c459392908890600401614604565b604080518083038160008887f193505050508015610c80575060408051601f3d908101601f19168201909252610c7d91810190614717565b60015b610c8d5760009250610ca3565b6001600160a01b03909116602088015260608701525b505b825115610d9c57600083806020019051810190610cc29190614745565b60e08701519091506001600160a01b0316610ceb5760808101516001600160a01b031660e08701525b828015610cf75750815a115b15610d9a573063bce53d24835a610d0e919061434c565b8389602001518a606001516040518563ffffffff1660e01b8152600401610d3793929190614800565b604080518083038160008887f193505050508015610d72575060408051601f3d908101601f19168201909252610d6f91810190614717565b60015b15610d9a576001600160a01b0391821661010089015261012088015260808201511660e08701525b505b84610120015185606001511115610dcf57610dcf85602001518660e00151876101200151886060015161097f919061434c565b8461010001516001600160a01b03168560e001516001600160a01b03168e7f593e4dbcb8f7312fc3bdd77e2095da131a6e1993f37752d12576d04e1f7253b4886000015189602001518a604001518b606001518c61012001518d61014001518e61016001518f6101c00151604051610e4e989796959493929190614871565b60405180910390a4610e64856101800151611f88565b5050505050610e736001600a55565b5050505050505050565b610e85611fa9565b6127108210610e9357600080fd5b60088290556009819055604051819083907f5b2f81a75439605ecd08ce07af893a489989a97d6d2008dff44c6827503ba82c90600090a35050565b610ed6611fa9565b6001600160a01b0381163b610efe576040516308ebd80360e11b815260040160405180910390fd5b600c80546001600160a01b0319166001600160a01b0383169081179091556040517f5d0517e3a4eabea892d9750138cd21d4a6cf3b935b43d0598df7055f463819b290600090a250565b610f50611fa9565b600d81905560405181907ff47543a7cab136b12cca0a2ecd728c9d1943f57b923b98db48725d2b76dd4da990600090a250565b6000610f8d611b6d565b610f978689614339565b600003610fb7576040516312cd5ab760e11b815260040160405180910390fd5b610fbf6139e3565b8c8160c001906001600160a01b031690816001600160a01b0316815250508b81600001906001600160a01b031690816001600160a01b0316815250508a8160400181815250508b81602001906001600160a01b031690816001600160a01b0316815250508a8160600181815250508d8160800181815250506110808160000151826040015188888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bc692505050565b6101a08301526101808201526060611096613a92565b6110aa836000015184604001518888611c66565b6001600160a01b031660a0860152606085015290508a1561116c5760006110d38c8e018e6148ca565b90506110ee84600001518560600151866101a00151846120fb565b60608601526001600160a01b03166020850152891580156111125750606084015115155b1561116a57602080820151604051611142920160609190911b6bffffffffffffffffffffffff1916815260140190565b604051602081830303815290604052925061116a846020015182602001518660600151611e81565b505b88156111ad5760006111808a8c018c6148fe565b80516101608601526040810151602086015160608701519195509192506111a9913391846121c4565b9450505b80604001516001600160a01b031681602001516001600160a01b031684600001516001600160a01b03167ffe2e49614659d9447156c9e3846112ea8edda361dcd696be486f6f977ce854e58460a001518560c00151866060015187608001518b60405161123c959493929190948552602085019390935260408401919091526060830152608082015260a00190565b60405180910390a4336001600160a01b03168360c001516001600160a01b03168460a001516001600160a01b03167fba828651bf4de06e53231285961e555fd7dfe17a3e39d64b09fbaa8ebc0166c6866080015188886000015189602001518a604001518b606001518c61016001518c6040516112c09897969594939291906149a2565b60405180910390a46112d6836101800151611f88565b5050506112e36001600a55565b9c9b505050505050505050505050565b6112fb611fa9565b61130560006122a4565b565b61130f611fa9565b610a8c823383611e81565b60045433906001600160a01b0316811461138d5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b611396816122a4565b50565b6000806000806113a986866122bd565b6007549091506001600160a01b03161580156113d0575060208101516001600160a01b0316155b156113e657600087600093509350935050611512565b6007546000906001600160a01b03161561141a576006546114079084614339565b9250600554816114179190614339565b90505b60208201516001600160a01b03161561146f57600082516001811115611442576114426145c2565b0361145d5760408201516114569084614339565b925061146f565b604082015161146c9082614339565b90505b6001600160a01b03891615806114a1575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b038a16145b156114ed576114b08389614339565b935080156114e8576114c48161271061434c565b6114d0612710866149ec565b6114da9190614a03565b6114e5906001614339565b93505b61150f565b801561150b576114ff8161271061434c565b6114d06127108a6149ec565b8793505b50505b9450945094915050565b6000611526611fa9565b61152f826123b7565b50600190505b919050565b611542613a92565b600061154e84846122bd565b6007549091506001600160a01b0316158015611575575060208101516001600160a01b0316155b1561158057506116b5565b6001600160a01b038087168352600754161561160c576007546001600160a01b039081166020840152600654606084015286166115eb57612710600554866115c891906149ec565b6115d29190614a03565b826060018181516115e39190614339565b90525061160c565b612710600554866115fc91906149ec565b6116069190614a03565b60a08301525b60208101516001600160a01b0316156116b35760208101516001600160a01b03166040830152600081516001811115611647576116476145c2565b0361165b57604081015160808301526116b3565b6001600160a01b0386166116905761271081604001518661167c91906149ec565b6116869190614a03565b60808301526116b3565b6127108160400151866116a391906149ec565b6116ad9190614a03565b60c08301525b505b949350505050565b6000803330146116e057604051632ee47ea160e11b815260040160405180910390fd5b6116ec868686866120fb565b9097909650945050505050565b600080600080600061170d89898989612430565b80519550905061171c89612539565b1561176a576000935080608001518160c001518260a0015183606001516117439190614339565b61174d9190614339565b6117579190614339565b9250611763838961434c565b91506117a3565b8060c001518160a0015161177e9190614339565b9350806080015181606001516117949190614339565b92506117a0848961434c565b91505b50945094509450949050565b6000803330146117d257604051632ee47ea160e11b815260040160405180910390fd5b845191506117e1838587612572565b9050935093915050565b6117f3611fa9565b6001600160a01b03831661181a5760405163538ba4f960e01b815260040160405180910390fd5b612710821061182857600080fd5b600780546001600160a01b0319166001600160a01b03851690811790915560058390556006829055604051829184917f17906aa05b055ced1cea92b104912638c3ec8c90eec152fca6f36fbd8becca1d90600090a4505050565b61188a611fa9565b611396816126fc565b61189b611fa9565b60008290036118bd57604051630239912560e01b815260040160405180910390fd5b60005b828110156119e3576119018484838181106118dd576118dd614a25565b90506020020160208101906118f29190613da2565b6001600160a01b03163b151590565b61191e576040516308ebd80360e11b815260040160405180910390fd5b816001600086868581811061193557611935614a25565b905060200201602081019061194a9190613da2565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905581151584848381811061198757611987614a25565b905060200201602081019061199c9190613da2565b6001600160a01b03167f1f478f1e5aee36a892d86e821aba410dc0934cb0ebd0241dd75370833884545360405160405180910390a3806119db81614a3b565b9150506118c0565b50505050565b600c54600090819081906001600160a01b0316611a7557604051630f5cd35360e31b81523090637ae69a9890611a29908a908a908a908a90600401614a54565b606060405180830381865afa158015611a46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6a9190614a9c565b925092509250611512565b600c54604051630f5cd35360e31b81526001600160a01b0390911690637ae69a9890611aab908a908a908a908a90600401614a54565b606060405180830381865afa158015611ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aec9190614a9c565b9250925092509450945094915050565b611b04611fa9565b600480546001600160a01b0383166001600160a01b03199091168117909155611b356003546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6002600a5403611bbf5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611384565b6002600a55565b60008083600003611bea5760405163090b95c560e31b815260040160405180910390fd5b825115611bfa57611bfa8361276c565b611c04344761434c565b9150611c0f85612539565b15611c465783341015611c3557604051637d6b3cdf60e11b815260040160405180910390fd5b611c3f844761434c565b9050611c5e565b611c508530612067565b9050611c5e853330876127b7565b935093915050565b611c6e613a92565b600080611c7d87878787612430565b925082604001519050611c8f87612539565b15611d0c5760008360a001518460600151611caa9190614339565b90508015611cc157611cc188856020015183611e81565b600084608001518560c00151611cd79190614339565b90508015611cee57611cee89866040015183611e81565b80611cf9838a61434c565b611d03919061434c565b93505050611dd6565b606083015115611d2a57611d2a600084602001518560600151611e81565b60a083015115611d4757611d478784602001518560a00151611e81565b608083015115611d6557611d65600084604001518560800151611e81565b60c083015115611d8257611d828784604001518560c00151611e81565b60c083015160a0840151611d96908861434c565b611da0919061434c565b91503483608001518460600151611db79190614339565b1115611dd657604051637d6b3cdf60e11b815260040160405180910390fd5b816000036115125760405163090b95c560e31b815260040160405180910390fd5b8151600090819087908790839015611e3a57600087806020019051810190611e1f919061442b565b9050611e2d8b8b8b846120fb565b6020909201519650935091505b855115611e7457600086806020019051810190611e579190614745565b9050611e64838583612572565b6080820151915191965090945090505b9550955095509550959050565b611e8a83612539565b15611e9e57611e998282612822565b505050565b46632b6653dc81148015611ece575073a614f803b6fd780986a42c78ec9c7f77e6ded13c6001600160a01b038516145b15611f7457604080516001600160a01b038581166024830152604480830186905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915191861691611f2a9190614ad3565b6000604051808303816000865af19150503d8060008114611f67576040519150601f19603f3d011682016040523d82523d6000602084013e611f6c565b606091505b5050506119e3565b6119e36001600160a01b038516848461293b565b8047101561139657604051630cfbd6ed60e01b815260040160405180910390fd5b6003546001600160a01b031633146113055760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611384565b6001600160e01b03198216600081815260026020908152604091829020805460ff19168515159081179091558251938452908301527fc4a5aadd92b2d0e7efaf25f9d44b0e6fca6c44da8e09fc3250cc12ef954cb60e910160405180910390a15050565b600061207283612539565b1561208857506001600160a01b038116316120f5565b6040516370a0823160e01b81526001600160a01b0383811660048301528416906370a0823190602401602060405180830381865afa1580156120ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f29190614aef565b90505b92915050565b805160006001600160a01b038083169087160361212e576040516001624cdd6d60e11b0319815260040160405180910390fd5b600061213e846000015130612067565b905061214b87878661296b565b8061215a856000015130612067565b612164919061434c565b9150836060015182101561218b576040516319af26f360e31b815260040160405180910390fd5b6000856121988930612067565b6121a2919061434c565b905080156121b9576121b988866040015183611e81565b505094509492505050565b600b5460009081906001600160a01b03166121de86612539565b156121f95760208401516121f29086614339565b9150612214565b602084015191506122146001600160a01b0387168287612bf0565b604080850151855160608701519251632e267e4160e21b81526001600160a01b0385169363b899f904938793612256938e938e93928e92909190600401614b08565b60206040518083038185885af1158015612274573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906122999190614aef565b979650505050505050565b600480546001600160a01b031916905561139681612c7f565b604080516060810182526000808252602082018190529181019190915281156120f5576122ec82840184614b5f565b9050600181516001811115612303576123036145c2565b036123625760085481604001511061235d5760405162461bcd60e51b815260206004820152601b60248201527f4665654d616e616765723a20696e76616c6964206665655261746500000000006044820152606401611384565b6120f5565b6009548160400151106120f55760405162461bcd60e51b815260206004820152601e60248201527f4665654d616e616765723a20696e76616c6964206e61746976652066656500006044820152606401611384565b60006001600160a01b0382163b6123e1576040516308ebd80360e11b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0384169081179091556040517f53b7c37d01415b2804281f4684b0722e0b01fbd375bf502609f465e17ab4441e90600090a2506001919050565b612438613a92565b600c546001600160a01b03166124b957604051638239917560e01b81523090638239917590612471908890889088908890600401614a54565b60e060405180830381865afa15801561248e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b29190614bcd565b90506116b5565b600c54604051638239917560e01b81526001600160a01b03909116906382399175906124ef908890889088908890600401614a54565b60e060405180830381865afa15801561250c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125309190614bcd565b95945050505050565b60006001600160a01b03821615806120f557506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b600061257e8330612067565b604083015160a084015191925090602382111561259b5785828201525b83516125a79082612cd1565b60006125b286612539565b156126215784600001516001600160a01b031687836040516125d49190614ad3565b60006040518083038185875af1925050503d8060008114612611576040519150601f19603f3d011682016040523d82523d6000602084013e612616565b606091505b5050809150506126ca565b8615612641576020850151612641906001600160a01b0388169089612dda565b84600001516001600160a01b03168560600151836040516126629190614ad3565b60006040518083038185875af1925050503d806000811461269f576040519150601f19603f3d011682016040523d82523d6000602084013e6126a4565b606091505b509091505086156126ca5760208501516126ca906001600160a01b038816906000612e87565b806126e857604051637588692960e01b815260040160405180910390fd5b6126f28630612067565b612299908561434c565b6001600160a01b0381163b612724576040516308ebd80360e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b038316908117825560405190917f556b8b8772c1552cbcc67f9bb7c7fd60934af593e54ec7aa4e8b2683632675f891a250565b6000806000806000806000808880602001905181019061278c9190614c6b565b975097509750975097509750975097506127ac8888888888888888612f9c565b505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526119e39085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613166565b804710156128725760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401611384565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146128bf576040519150601f19603f3d011682016040523d82523d6000602084013e6128c4565b606091505b5050905080611e995760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401611384565b6040516001600160a01b038316602482015260448101829052611e9990849063a9059cbb60e01b906064016127eb565b608081015151600081900361299357604051630239912560e01b815260040160405180910390fd5b60008060006129a78685876080015161323b565b6080880151929550909350915060006129bf89612539565b905060005b86811015612be4578415612abc5780600003612a4d5783612a1557848382815181106129f2576129f2614a25565b6020026020010151606001818151612a0a919061434c565b915081815250612a47565b84838281518110612a2857612a28614a25565b6020026020010151606001818151612a409190614339565b9150818152505b50612abc565b83612a885785838281518110612a6557612a65614a25565b6020026020010151606001818151612a7d919061434c565b915081815250612aba565b85838281518110612a9b57612a9b614a25565b6020026020010151606001818151612ab39190614339565b9150818152505b505b81612b1957612b19838281518110612ad657612ad6614a25565b602002602001015160400151848381518110612af457612af4614a25565b6020026020010151606001518c6001600160a01b0316612dda9092919063ffffffff16565b612b9b838281518110612b2e57612b2e614a25565b60200260200101516000015183858481518110612b4d57612b4d614a25565b6020026020010151602001518d878681518110612b6c57612b6c614a25565b602002602001015160600151888781518110612b8a57612b8a614a25565b602002602001015160800151613325565b81612bdc57612bdc838281518110612bb557612bb5614a25565b60200260200101516040015160008c6001600160a01b0316612e879092919063ffffffff16565b6001016129c4565b50505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052612c4184826133b7565b6119e3576040516001600160a01b038416602482015260006044820152612c7590859063095ea7b360e01b906064016127eb565b6119e38482613166565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000546001600160a01b039081169083168114801590612d0a57506001600160a01b03831660009081526001602052604090205460ff16155b15612d285760405163369370d960e01b815260040160405180910390fd5b6000612d338361345a565b6001600160e01b0319811660009081526002602052604090205490915060ff1615612d7157604051630d1a468960e01b815260040160405180910390fd5b816001600160a01b0316846001600160a01b0316036119e3576001600160e01b03198116632e1a7d4d60e01b14801590612dbc57506001600160e01b03198116630d0e30db60e41b14155b156119e357604051630d1a468960e01b815260040160405180910390fd5b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015612e2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e4e9190614aef565b90506119e38463095ea7b360e01b85612e678686614339565b6040516001600160a01b03909216602483015260448201526064016127eb565b801580612f015750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015612edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eff9190614aef565b155b612f6c5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401611384565b6040516001600160a01b038316602482015260448101829052611e9990849063095ea7b360e01b906064016127eb565b604051623f675f60e91b81526001600160a01b038881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015612fe5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130099190614aef565b60405163d505accf60e01b81526001600160a01b038a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b15801561307d57600080fd5b505af1158015613091573d6000803e3d6000fd5b5050604051623f675f60e91b81526001600160a01b038b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa1580156130dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131019190614aef565b905061310e826001614339565b8114612be45760405162461bcd60e51b815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f74207375636365656044820152601960fa1b6064820152608401611384565b60006131bb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134759092919063ffffffff16565b90508051600014806131dc5750808060200190518101906131dc9190614cf7565b611e995760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401611384565b6000808080805b868110156132875785818151811061325c5761325c614a25565b602002602001015160600151826132739190614339565b91508061327f81614a3b565b915050613242565b50868111156132d357600091508161329f888361434c565b90506132ab8782614a03565b94506132b787866149ec565b6132c1908261434c565b6132cb9086614339565b93505061331b565b8681101561331b576001915060006132eb828961434c565b90506132f78782614a03565b945061330387866149ec565b61330d908261434c565b6133179086614339565b9350505b5093509350939050565b6000600487600581111561333b5761333b6145c2565b036133535761334c85848885613484565b9050613390565b6005876005811115613367576133676145c2565b036133775761334c8484846135d1565b6040516318f9c3a760e11b815260040160405180910390fd5b806133ae57604051636ff55bbf60e01b815260040160405180910390fd5b50505050505050565b6000806000846001600160a01b0316846040516133d49190614ad3565b6000604051808303816000865af19150503d8060008114613411576040519150601f19603f3d011682016040523d82523d6000602084013e613416565b606091505b50915091508180156134405750805115806134405750808060200190518101906134409190614cf7565b80156125305750505050506001600160a01b03163b151590565b6000815160000361346d57506000919050565b506020015190565b60606116b5848460008561387a565b60008060008380602001905181019061349d9190614d14565b8151919350915060005b818110156134ef5760008482815181106134c3576134c3614a25565b6020026020010151905060238111156134dc5788818501525b50806134e781614a3b565b9150506134a7565b506134fa8883612cd1565b851561356657876001600160a01b031687836040516135199190614ad3565b60006040518083038185875af1925050503d8060008114613556576040519150601f19603f3d011682016040523d82523d6000602084013e61355b565b606091505b5050809450506135c6565b876001600160a01b03168260405161357e9190614ad3565b6000604051808303816000865af19150503d80600081146135bb576040519150601f19603f3d011682016040523d82523d6000602084013e6135c0565b606091505b50909450505b505050949350505050565b600080828060200190518101906135e89190614dc5565b905060005b81518110156138715780156136465761362382828151811061361157613611614a25565b60200260200101516020015130612067565b945081818151811061363757613637614a25565b60200260200101516020015195505b600082828151811061365a5761365a614a25565b6020026020010151608001519050600083838151811061367c5761367c614a25565b602002602001015160000151905060238111156136995786818301525b6136c08484815181106136ae576136ae614a25565b60200260200101516040015183612cd1565b6136c988612539565b15613751578383815181106136e0576136e0614a25565b6020026020010151604001516001600160a01b031687836040516137049190614ad3565b60006040518083038185875af1925050503d8060008114613741576040519150601f19603f3d011682016040523d82523d6000602084013e613746565b606091505b505080955050613850565b82156137925761379284848151811061376c5761376c614a25565b602002602001015160600151888a6001600160a01b0316612dda9092919063ffffffff16565b8383815181106137a4576137a4614a25565b6020026020010151604001516001600160a01b0316826040516137c79190614ad3565b6000604051808303816000865af19150503d8060008114613804576040519150601f19603f3d011682016040523d82523d6000602084013e613809565b606091505b509095505082156138505761385084848151811061382957613829614a25565b60200260200101516060015160008a6001600160a01b0316612e879092919063ffffffff16565b8461385c575050613871565b5050808061386990614a3b565b9150506135ed565b50509392505050565b6060824710156138db5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401611384565b600080866001600160a01b031685876040516138f79190614ad3565b60006040518083038185875af1925050503d8060008114613934576040519150601f19603f3d011682016040523d82523d6000602084013e613939565b606091505b509150915061229987838387606083156139b45782516000036139ad576001600160a01b0385163b6139ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611384565b50816116b5565b6116b583838151156139c95781518083602001fd5b8060405162461bcd60e51b81526004016113849190614ef0565b604051806101e0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000801916815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008152602001606081525090565b6040518060e0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b038116811461139657600080fd5b803561153581613aea565b60008083601f840112613b1c57600080fd5b5081356001600160401b03811115613b3357600080fd5b602083019150836020828501011115613b4b57600080fd5b9250929050565b6000806000806000806000806000806000806101008d8f031215613b7557600080fd5b8c359b50613b8560208e01613aff565b9a50613b9360408e01613aff565b995060608d013598506001600160401b0360808e01351115613bb457600080fd5b613bc48e60808f01358f01613b0a565b90985096506001600160401b0360a08e01351115613be157600080fd5b613bf18e60a08f01358f01613b0a565b90965094506001600160401b0360c08e01351115613c0e57600080fd5b613c1e8e60c08f01358f01613b0a565b90945092506001600160401b0360e08e01351115613c3b57600080fd5b613c4b8e60e08f01358f01613b0a565b81935080925050509295989b509295989b509295989b565b80356001600160e01b03198116811461153557600080fd5b801515811461139657600080fd5b60008060408385031215613c9c57600080fd5b613ca583613c63565b91506020830135613cb581613c7b565b809150509250929050565b600060208284031215613cd257600080fd5b613cdb82613c63565b9392505050565b60008060008060008060008060c0898b031215613cfe57600080fd5b883597506020890135613d1081613aea565b9650604089013595506060890135945060808901356001600160401b0380821115613d3a57600080fd5b613d468c838d01613b0a565b909650945060a08b0135915080821115613d5f57600080fd5b50613d6c8b828c01613b0a565b999c989b5096995094979396929594505050565b60008060408385031215613d9357600080fd5b50508035926020909101359150565b600060208284031215613db457600080fd5b8135613cdb81613aea565b600060208284031215613dd157600080fd5b5035919050565b60008060408385031215613deb57600080fd5b8235613df681613aea565b946020939093013593505050565b60008060008060608587031215613e1a57600080fd5b8435613e2581613aea565b93506020850135925060408501356001600160401b03811115613e4757600080fd5b613e5387828801613b0a565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715613e9757613e97613e5f565b60405290565b60405160c081016001600160401b0381118282101715613e9757613e97613e5f565b604051608081016001600160401b0381118282101715613e9757613e97613e5f565b604051601f8201601f191681016001600160401b0381118282101715613f0957613f09613e5f565b604052919050565b60006001600160401b03821115613f2a57613f2a613e5f565b5060051b60200190565b6006811061139657600080fd5b60006001600160401b03821115613f5a57613f5a613e5f565b50601f01601f191660200190565b600082601f830112613f7957600080fd5b8135613f8c613f8782613f41565b613ee1565b818152846020838601011115613fa157600080fd5b816020850160208301376000918101602001919091529392505050565b600060a08284031215613fd057600080fd5b613fd8613e75565b90508135613fe581613aea565b8152602082810135613ff681613aea565b82820152604083013561400881613aea565b6040830152606083810135818401526080808501356001600160401b038082111561403257600080fd5b818701915087601f83011261404657600080fd5b8135614054613f8782613f11565b81815260059190911b8301860190868101908a83111561407357600080fd5b8785015b8381101561411d5780358581111561408f5760008081fd5b860160a0818e03601f190112156140a65760008081fd5b6140ae613e75565b8a8201356140bb81613f34565b815260408201356140cb81613aea565b818c0152818a01356140dc81613aea565b6040820152818901358a82015260a0820135878111156140fc5760008081fd5b61410a8f8d83860101613f68565b828b015250845250918801918801614077565b5080868a0152505050505050505092915050565b6000806000806080858703121561414757600080fd5b843561415281613aea565b9350602085013592506040850135915060608501356001600160401b0381111561417b57600080fd5b61418787828801613fbe565b91505092959194509250565b6000806000606084860312156141a857600080fd5b83356001600160401b03808211156141bf57600080fd5b9085019060c082880312156141d357600080fd5b6141db613e9d565b82356141e681613aea565b815260208301356141f681613aea565b806020830152506040830135604082015260608301356060820152608083013561421f81613aea565b608082015260a08301358281111561423657600080fd5b61424289828601613f68565b60a083015250945061425991505060208501613aff565b9150604084013590509250925092565b60008060006060848603121561427e57600080fd5b833561428981613aea565b95602085013595506040909401359392505050565b6000806000604084860312156142b357600080fd5b83356001600160401b03808211156142ca57600080fd5b818601915086601f8301126142de57600080fd5b8135818111156142ed57600080fd5b8760208260051b850101111561430257600080fd5b6020928301955093505084013561431881613c7b565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b808201808211156120f5576120f5614323565b818103818111156120f5576120f5614323565b6000806040838503121561437257600080fd5b82356001600160401b038082111561438957600080fd5b61439586838701613f68565b935060208501359150808211156143ab57600080fd5b506143b885828601613f68565b9150509250929050565b60005b838110156143dd5781810151838201526020016143c5565b50506000910152565b600082601f8301126143f757600080fd5b8151614405613f8782613f41565b81815284602083860101111561441a57600080fd5b6116b58260208301602087016143c2565b6000602080838503121561443e57600080fd5b82516001600160401b038082111561445557600080fd5b9084019060a0828703121561446957600080fd5b614471613e75565b825161447c81613aea565b81528284015161448b81613aea565b81850152604083015161449d81613aea565b604082015260608381015190820152608080840151838111156144bf57600080fd5b80850194505087601f8501126144d457600080fd5b83516144e2613f8782613f11565b81815260059190911b8501860190868101908a83111561450157600080fd5b8787015b838110156145ad5780518781111561451d5760008081fd5b880160a0818e03601f190112156145345760008081fd5b61453c613e75565b8a82015161454981613f34565b8152604082015161455981613aea565b818c0152606082015161456b81613aea565b604082015281870151606082015260a08201518981111561458c5760008081fd5b61459a8f8d838601016143e6565b8289015250845250918801918801614505565b50928401929092525090979650505050505050565b634e487b7160e01b600052602160045260246000fd5b600081518084526145f08160208601602086016143c2565b601f01601f19169290920160200192915050565b6000608060018060a01b038088168452602087818601526040878187015260608481880152610120870184895116868901528389015160a0868216818b015286858c01511660c08b0152838b015160e08b0152878b01519150806101008b01528282518085526101409450848c019150848160051b8d0101945087840193506000805b828110156146ff578d870361013f1901845285518051600681106146b957634e487b7160e01b84526021600452602484fd5b8852808b01518c168b890152898101518c168a89015288810151898901528c01518c88018690526146ec868901826145d8565b9750509489019492890192600101614687565b50505050505080965050505050505095945050505050565b6000806040838503121561472a57600080fd5b825161473581613aea565b6020939093015192949293505050565b60006020828403121561475757600080fd5b81516001600160401b038082111561476e57600080fd5b9083019060c0828603121561478257600080fd5b61478a613e9d565b825161479581613aea565b815260208301516147a581613aea565b80602083015250604083015160408201526060830151606082015260808301516147ce81613aea565b608082015260a0830151828111156147e557600080fd5b6147f1878286016143e6565b60a08301525095945050505050565b60608152600060018060a01b03808651166060840152806020870151166080840152604086015160a0840152606086015160c08401528060808701511660e084015260a086015160c061010085015261485d6101208501826145d8565b959091166020840152505060400152919050565b600061010060018060a01b03808c168452808b166020850152508860408401528760608401528660808401528560a08401528460c08401528060e08401526148bb818401856145d8565b9b9a5050505050505050505050565b6000602082840312156148dc57600080fd5b81356001600160401b038111156148f257600080fd5b6116b584828501613fbe565b60006020828403121561491057600080fd5b81356001600160401b038082111561492757600080fd5b908301906080828603121561493b57600080fd5b614943613ebf565b823581526020830135602082015260408301358281111561496357600080fd5b61496f87828601613f68565b60408301525060608301358281111561498757600080fd5b61499387828601613f68565b60608301525095945050505050565b60006101008a835289602084015260018060a01b03808a1660408501528089166060850152508660808401528560a08401528460c08401528060e08401526148bb818401856145d8565b80820281158282048414176120f5576120f5614323565b600082614a2057634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b600060018201614a4d57614a4d614323565b5060010190565b6001600160a01b0385168152602081018490526060604082018190528101829052818360808301376000818301608090810191909152601f909201601f191601019392505050565b600080600060608486031215614ab157600080fd5b8351614abc81613aea565b602085015160409095015190969495509392505050565b60008251614ae58184602087016143c2565b9190910192915050565b600060208284031215614b0157600080fd5b5051919050565b6001600160a01b0387811682528616602082015260c060408201819052600090614b34908301876145d8565b85606084015284608084015282810360a0840152614b5281856145d8565b9998505050505050505050565b600060608284031215614b7157600080fd5b604051606081018181106001600160401b0382111715614b9357614b93613e5f565b604052823560028110614ba557600080fd5b81526020830135614bb581613aea565b60208201526040928301359281019290925250919050565b600060e08284031215614bdf57600080fd5b60405160e081018181106001600160401b0382111715614c0157614c01613e5f565b6040528251614c0f81613aea565b81526020830151614c1f81613aea565b60208201526040830151614c3281613aea565b80604083015250606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600080600080600080600080610100898b031215614c8857600080fd5b8851614c9381613aea565b60208a0151909850614ca481613aea565b60408a0151909750614cb581613aea565b80965050606089015194506080890151935060a089015160ff81168114614cdb57600080fd5b60c08a015160e0909a0151989b979a5095989497939692505050565b600060208284031215614d0957600080fd5b8151613cdb81613c7b565b60008060408385031215614d2757600080fd5b82516001600160401b0380821115614d3e57600080fd5b818501915085601f830112614d5257600080fd5b81516020614d62613f8783613f11565b82815260059290921b84018101918181019089841115614d8157600080fd5b948201945b83861015614d9f57855182529482019490820190614d86565b91880151919650909350505080821115614db857600080fd5b506143b8858286016143e6565b60006020808385031215614dd857600080fd5b82516001600160401b0380821115614def57600080fd5b818501915085601f830112614e0357600080fd5b8151614e11613f8782613f11565b81815260059190911b83018401908481019088831115614e3057600080fd5b8585015b83811015614ee357805185811115614e4c5760008081fd5b860160a0818c03601f1901811315614e645760008081fd5b614e6c613e75565b898301518152604080840151614e8181613aea565b828c0152606084810151614e9481613aea565b8083850152506080915081850151614eab81613aea565b90830152918301519188831115614ec25760008081fd5b614ed08e8c858701016143e6565b9082015285525050918601918601614e34565b5098975050505050505050565b602081526000613cdb60208301846145d856fea264697066735822122038becc5f4178fb79c9c9f7688f531bb6edfdc8469b83492031e677df022c3acf64736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000feb2b97e4efce787c08086dc16ab69e063911380000000000000000000000000df3f1ee5baf55055980887aad79f6fe6e3302d9300000000000000000000000078c1b0c915c4faa5fffa6cabf0219da63d7f4cb8
-----Decoded View---------------
Arg [0] : _bridgeAddress (address): 0xfeB2b97e4Efce787c08086dC16Ab69E063911380
Arg [1] : _owner (address): 0xdf3f1Ee5BAF55055980887AaD79F6fE6e3302D93
Arg [2] : _wToken (address): 0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000feb2b97e4efce787c08086dc16ab69e063911380
Arg [1] : 000000000000000000000000df3f1ee5baf55055980887aad79f6fe6e3302d93
Arg [2] : 00000000000000000000000078c1b0c915c4faa5fffa6cabf0219da63d7f4cb8
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 83.84% | $3,411.38 | 0.2419 | $825.17 | |
| BSC | 8.74% | $949.99 | 0.0905 | $86 | |
| BASE | 7.20% | $3,410.64 | 0.0208 | $70.89 | |
| BASE | 0.02% | $0.00 | 0.00005422 | $0.00 | |
| LINEA | 0.11% | $3,411.38 | 0.0003203 | $1.09 | |
| POL | 0.07% | $1 | 0.6472 | $0.6472 | |
| POL | 0.03% | $0.168654 | 1.5815 | $0.266724 | |
| ARB | <0.01% | $3,412.29 | 0.000000000000000659 | <$0.000001 | |
| OP | <0.01% | $3,410.97 | 0.00000000000000008 | <$0.000001 | |
| BLAST | <0.01% | $3,411.19 | 0.00000000000000003 | <$0.000001 | |
| SCROLL | <0.01% | $3,411.38 | 0.000000000000000005 | <$0.000001 | |
| MANTLE | <0.01% | $1.26 | 0.000000000000000003 | <$0.000001 |
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.