Overview
ETH Balance
ETH Value
$0.00Latest 20 from a total of 20 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Swap And Call | 30786259 | 15 days ago | IN | 0.0001 ETH | 0.00000003 | ||||
| Swap And Call | 30786169 | 15 days ago | IN | 0 ETH | 0.00000006 | ||||
| Swap And Bridge | 29840074 | 26 days ago | IN | 0.05 ETH | 0.00000001 | ||||
| Swap And Bridge | 29840014 | 26 days ago | IN | 0 ETH | 0.00000001 | ||||
| Swap And Bridge | 29839951 | 26 days ago | IN | 0 ETH | 0.00000001 | ||||
| Swap And Bridge | 29838990 | 26 days ago | IN | 0.0003 ETH | 0.00000001 | ||||
| Swap And Call | 29837988 | 26 days ago | IN | 0.0001 ETH | 0.00000028 | ||||
| Swap And Call | 29837920 | 26 days ago | IN | 0.0001 ETH | 0.0000003 | ||||
| Swap And Bridge | 29837054 | 26 days ago | IN | 0.0002 ETH | 0.00000054 | ||||
| Swap And Bridge | 29779568 | 26 days ago | IN | 0.0001 ETH | 0.00000043 | ||||
| Swap And Bridge | 29761200 | 27 days ago | IN | 0 ETH | 0.00000001 | ||||
| Swap And Call | 29688113 | 27 days ago | IN | 0 ETH | 0.00000057 | ||||
| Swap And Call | 29687989 | 27 days ago | IN | 0.0001 ETH | 0.00000053 | ||||
| Swap And Call | 29687525 | 28 days ago | IN | 0.0001 ETH | 0.00000055 | ||||
| Approve Token | 29682283 | 28 days ago | IN | 0 ETH | 0 | ||||
| Approve Token | 29682280 | 28 days ago | IN | 0 ETH | 0 | ||||
| Approve Token | 29682271 | 28 days ago | IN | 0 ETH | 0 | ||||
| Set Referrer Max... | 29681797 | 28 days ago | IN | 0 ETH | 0 | ||||
| Set Fee | 29681793 | 28 days ago | IN | 0 ETH | 0.00000005 | ||||
| Set Authorizatio... | 29681786 | 28 days ago | IN | 0 ETH | 0 |
Latest 14 internal transactions
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 30786259 | 15 days ago | 0.0001 ETH | ||||
| 30786169 | 15 days ago | 0.00019076 ETH | ||||
| 30786169 | 15 days ago | 0.00019076 ETH | ||||
| 29840074 | 26 days ago | 0.05 ETH | ||||
| 29838990 | 26 days ago | 0.0003 ETH | ||||
| 29837988 | 26 days ago | 0.0001 ETH | ||||
| 29837920 | 26 days ago | 0.0001 ETH | ||||
| 29837054 | 26 days ago | 0.0002 ETH | ||||
| 29779568 | 26 days ago | 0.0001 ETH | ||||
| 29688113 | 27 days ago | 0.00009798 ETH | ||||
| 29688113 | 27 days ago | 0.00009798 ETH | ||||
| 29687989 | 27 days ago | 0.0001 ETH | ||||
| 29687525 | 28 days ago | 0.0001 ETH | ||||
| 29681782 | 28 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
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 "./interface/IFeeManager.sol";
import "./abstract/SwapCallV2.sol";
import "./interface/IButterRouterV3.sol";
import "./abstract/FeeManager.sol";
contract ButterRouterV31 is SwapCallV2, FeeManager, ReentrancyGuard, IButterRouterV3 {
using SafeERC20 for IERC20;
using Address for address;
address public bridgeAddress;
IFeeManager public feeManager;
// 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 toChain;
uint256 nativeBalance;
uint256 inputBalance;
}
event Approve(address indexed executor, bool indexed flag);
event SetFeeManager(address indexed _feeManager);
event ApproveToken(IERC20 token, address spender, uint256 amount);
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);
constructor(
address _bridgeAddress,
address _owner,
address _wToken
) payable SwapCallV2(_wToken) FeeManager(_owner) {
if (!_bridgeAddress.isContract()) revert Errors.NOT_CONTRACT();
// bridgeAddress = _bridgeAddress;
_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 approveToken(IERC20 token, address spender, uint256 amount) external onlyOwner {
token.forceApprove(spender, amount);
emit ApproveToken(token, spender, amount);
}
function setBridgeAddress(address _bridgeAddress) public onlyOwner returns (bool) {
_setBridgeAddress(_bridgeAddress);
return true;
}
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) {
uint256 bridge_len = _bridgeData.length;
if (bridge_len == 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
);
if (_swapData.length != 0) {
(swapTemp.swapToken, swapTemp.swapAmount, ) = _swap(
swapTemp.srcToken,
swapTemp.swapAmount,
swapTemp.inputBalance,
_swapData
);
}
swapTemp.referrer = _getReferrerFromFeeData(_feeData);
bytes memory receiver;
(orderId, swapTemp.toChain, receiver) = _doBridge(
msg.sender,
swapTemp.swapToken,
swapTemp.swapAmount,
_bridgeData
);
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);
if (fd.integratorNativeFee + fd.integratorTokenFee + fd.routerNativeFee + fd.routerTokenFee > 0) {
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);
}
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;
(tokenFee, nativeFee, afterFeeAmount) = _calculateFee(_inputToken, _inputAmount, fd);
}
function _calculateFee(
address _inputToken,
uint256 _inputAmount,
IFeeManager.FeeDetail memory fd
) internal pure returns (uint256 tokenFee, uint256 nativeFee, uint256 afterFeeAmount) {
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 = _getFeeDetailInternal(_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 _doSwapAndCall(
address _srcToken,
uint256 _amount,
uint256 _initBalance,
bytes calldata _swapData,
bytes calldata _callbackData
) internal returns (address receiver, address target, address dstToken, uint256 swapOutAmount, uint256 callAmount) {
swapOutAmount = _amount;
dstToken = _srcToken;
if (_swapData.length > 0) {
(dstToken, swapOutAmount, receiver) = _swap(_srcToken, _amount, _initBalance, _swapData);
}
if (_callbackData.length > 0) {
(callAmount, receiver, target) = _callBack(swapOutAmount, dstToken, _callbackData);
}
}
function _doBridge(
address _sender,
address _token,
uint256 _amount,
bytes calldata _bridgeData
) internal returns (bytes32 orderId, uint256 toChain, bytes memory receiver) {
BridgeParam memory _bridge = abi.decode(_bridgeData, (BridgeParam));
toChain = _bridge.toChain;
receiver = _bridge.receiver;
address bridge = bridgeAddress;
// not approve (approved by function approveToken)
//uint256 value = _bridge.nativeFee + _approveToken(_token, bridge, _amount);
uint256 value = _isNative(_token) ? (_bridge.nativeFee + _amount) : _bridge.nativeFee;
orderId = IButterBridgeV3(bridge).swapOutToken{value: value}(
_sender,
_token,
receiver,
_amount,
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 {
if (!_bridgeAddress.isContract()) revert Errors.NOT_CONTRACT();
bridgeAddress = _bridgeAddress;
emit SetBridgeAddress(_bridgeAddress);
}
function _transferIn(
address token,
uint256 amount,
bytes calldata permitData
) internal returns (uint256 nativeBalanceBeforeExec, uint256 initInputTokenBalance) {
if (amount == 0) revert Errors.ZERO_IN();
address self = address(this);
if (permitData.length != 0) {
_permit(permitData);
}
nativeBalanceBeforeExec = self.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 = self.balance - amount;
} else {
initInputTokenBalance = _getBalance(token, self);
SafeERC20.safeTransferFrom(IERC20(token), msg.sender, self, amount);
}
}
function _getReferrerFromFeeData(bytes calldata feeData) internal pure returns (address referrer) {
if (feeData.length < 64) return referrer;
assembly {
referrer := calldataload(add(feeData.offset, 32))
}
}
function _permit(bytes calldata _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);
}
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
// 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: MIT
pragma solidity ^0.8.0;
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) {
return _getFeeDetailInternal(_inputToken, _inputAmount, _feeData);
}
function _getFeeDetailInternal(
address _inputToken,
uint256 _inputAmount,
bytes calldata _feeData
) internal view 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: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "../lib/Errors.sol";
abstract contract SwapCallV2 {
using SafeERC20 for IERC20;
using Address for address;
address internal constant ZERO_ADDRESS = address(0);
address internal constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
address immutable wToken;
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 {
if (!_wToken.isContract()) revert Errors.NOT_CONTRACT();
wToken = _wToken;
// _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 _afterCheck(uint256 nativeBalanceBeforeExec) internal view {
if (address(this).balance < nativeBalanceBeforeExec) revert Errors.NATIVE_VALUE_OVERSPEND();
}
function _swap(
address _token,
uint256 _amount,
uint256 _initBalance,
bytes calldata _swapData
) internal returns (address dstToken, uint256 dstAmount, address receiver) {
SwapParam memory swapParam = abi.decode(_swapData, (SwapParam));
receiver = swapParam.receiver;
dstToken = swapParam.dstToken;
if (_token == dstToken) revert Errors.SWAP_SAME_TOKEN();
address self = address(this);
uint256 finalTokenAmount = _getBalance(dstToken, self);
_doSwap(_token, _amount, swapParam.swaps);
dstAmount = _getBalance(dstToken, self) - finalTokenAmount;
if (dstAmount < swapParam.minAmount) revert Errors.RECEIVE_LOW();
uint256 left = _getBalance(_token, self) - _initBalance;
if (left != 0) {
_transfer(_token, swapParam.leftReceiver, left);
}
}
function _callBack(
uint256 _amount,
address _token,
bytes calldata _callbackData
) internal returns (uint256 callAmount, address receiver, address target) {
CallbackParam memory callParam = abi.decode(_callbackData, (CallbackParam));
receiver = callParam.receiver;
target = callParam.target;
address self = address(this);
callAmount = _getBalance(_token, self);
uint256 offset = callParam.offset;
bytes memory callPayload = callParam.data;
if (offset > 35) {
//32 length + 4 funcSig
assembly {
mstore(add(callPayload, offset), _amount)
}
}
bytes4 sig;
assembly {
sig := mload(add(callPayload, 32))
}
_checkApproval(target, sig);
uint256 value = callParam.extraNativeAmount + _approveToken(_token, callParam.approveTo, _amount);
(bool result, ) = target.call{value: value}(callPayload);
if (!result) revert Errors.CALL_BACK_FAIL();
callAmount = callAmount - _getBalance(_token, self);
}
function _checkApproval(address _callTo, bytes4 sig) private view {
address wTokenAddr = wToken;
if (_callTo != wTokenAddr && (!approved[_callTo])) revert Errors.NO_APPROVE();
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, SwapData[] memory _swaps) internal {
uint256 len = _swaps.length;
if (len == 0) revert Errors.EMPTY();
(uint256 amountAdjust, uint256 firstAdjust, bool isUp) = _rebuildSwaps(_amount, len, _swaps);
bool needAdjust = (firstAdjust != 0);
for (uint i = 0; i < len; ) {
SwapData memory swap = _swaps[i];
uint256 amount = swap.fromAmount;
if (needAdjust) {
if (i == 0) {
isUp ? amount += firstAdjust : amount -= firstAdjust;
} else {
isUp ? amount += amountAdjust : amount -= amountAdjust;
}
}
bool result;
DexType dexType = swap.dexType;
if (dexType == DexType.FILL) {
result = _makeAggFill(_token, swap.callTo, amount, swap.callData);
} else if (dexType == DexType.MIX) {
result = _makeMixSwap(_token, amount, swap.callData);
} else {
revert Errors.UNSUPPORT_DEX_TYPE();
}
if (!result) revert Errors.SWAP_FAIL();
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; ) {
total += _swaps[i].fromAmount;
unchecked {
++i;
}
}
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);
}
}
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[]));
uint256 length = mixSwaps.length;
address self = address(this);
for (uint256 i = 0; i < length; ) {
MixSwap memory mix = mixSwaps[i];
if (i != 0) {
_srcToken = mix.srcToken;
_amount = _getBalance(_srcToken, self);
}
bytes memory callData = mix.callData;
uint256 offset = mix.offset;
if (offset > 35) {
//32 length + 4 funcSig
assembly {
mstore(add(callData, offset), _amount)
}
}
bytes4 sig;
assembly {
sig := mload(add(callData, 32))
}
address target = mix.callTo;
_checkApproval(target, sig);
uint256 value = _approveToken(_srcToken, mix.approveTo, _amount);
(result, ) = target.call{value: value}(callData);
if (!result) break;
unchecked {
++i;
}
}
}
function _makeAggFill(
address _token,
address _router,
uint256 _amount,
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; ) {
uint256 offset = offsets[i];
if (offset > 35) {
//32 length + 4 funcSig
assembly {
mstore(add(callData, offset), _amount)
}
}
unchecked {
++i;
}
}
bytes4 sig;
assembly {
sig := mload(add(callData, 32))
}
_checkApproval(_router, sig);
uint256 value = _approveToken(_token, _router, _amount);
(result, ) = _router.call{value: value}(callData);
}
function _approveToken(address token, address spender, uint256 amount) internal returns (uint256 value) {
if (_isNative(token)) {
value = amount;
} else {
uint256 allowance = IERC20(token).allowance(address(this), spender);
if (allowance < amount) {
IERC20(token).forceApprove(spender, amount);
}
}
}
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);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IButterRouterV3
* @notice Interface for Butter Network Router V3 - Cross-chain swap and bridge aggregator
* @dev This interface defines the core functionality for token swapping, cross-chain bridging,
* and callback execution within the Butter Network ecosystem
*/
interface IButterRouterV3 {
/**
* @notice Enumeration of fee calculation types
* @dev FIXED: A fixed amount native token fee regardless of transaction size
* PROPORTION: A percentage-based fee calculated from transaction amount
*/
enum FeeType {
FIXED, // Fixed fee amount
PROPORTION // Proportional fee based on transaction amount
}
/**
* @notice Fee configuration structure for referrer/integrator fees
* @param feeType Type of fee calculation (FIXED or PROPORTION)
* @param referrer Address of the referrer/integrator who will receive the fee
* @param rateOrNativeFee Fee rate (for PROPORTION) or fixed native fee amount (for FIXED)
*/
struct Fee {
FeeType feeType; // Fee calculation method
address referrer; // Referrer/integrator address
uint256 rateOrNativeFee; // Fee rate (basis points) or fixed amount
}
/**
* @notice Bridge parameters for cross-chain operations
* @param toChain Destination chain ID for cross-chain transfer
* @param nativeFee Native token fee required for bridge operation
* @param receiver Encoded receiver address on destination chain
* @param data Additional bridge-specific data for cross-chain execution
*/
struct BridgeParam {
uint256 toChain; // Target blockchain chain ID
uint256 nativeFee; // Bridge fee in native tokens
bytes receiver; // Destination address (encoded)
bytes data; // Bridge-specific execution data
}
/**
* @notice Emitted when tokens are swapped and bridged to another chain
* @param referrer Address of the referrer/integrator
* @param initiator Address that initiated the transaction
* @param from Address that sent the tokens
* @param transferId Unique identifier for the transfer
* @param orderId Bridge order ID returned from bridge contract
* @param originToken Address of the original input token
* @param bridgeToken Address of the token being bridged
* @param originAmount Amount of original tokens input
* @param bridgeAmount Amount of tokens being bridged
* @param toChain Destination chain ID
* @param to Encoded receiver address on destination chain
*/
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
);
/**
* @notice Emitted when tokens are swapped and a callback is executed
* @param referrer Address of the referrer/integrator
* @param initiator Address that initiated the transaction
* @param from Address that sent the tokens
* @param transferId Unique identifier for the transfer
* @param originToken Address of the original input token
* @param swapToken Address of the token received from swap
* @param originAmount Amount of original tokens input
* @param swapAmount Amount of tokens received from swap
* @param receiver Address that will receive remaining tokens
* @param target Address of the contract called for callback
* @param callAmount Amount of tokens used in the callback
*/
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
);
/**
* @notice Emitted when a remote swap and call is executed (from bridge)
* @param orderId Bridge order ID that triggered this execution
* @param receiver Address that will receive remaining tokens
* @param target Address of the contract called for callback
* @param originToken Address of the original bridged token
* @param swapToken Address of the token received from swap
* @param originAmount Amount of original bridged tokens
* @param swapAmount Amount of tokens received from swap
* @param callAmount Amount of tokens used in the callback
* @param fromChain Source chain ID where tokens were bridged from
* @param toChain Current chain ID where execution is happening
* @param from Encoded address that initiated the bridge on source chain
*/
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
);
/**
* @notice Executes token swap and optional callback function
* @dev Supports two operations:
* 1. Pure swap: _swapData.length > 0 and _callbackData.length == 0
* 2. Swap and call: _swapData.length > 0 and _callbackData.length > 0
* @param _transferId Unique identifier for this transfer
* @param _initiator Address that initiated this transaction
* @param _srcToken Address of the source token to swap from
* @param _amount Amount of source tokens to swap
* @param _swapData Encoded swap parameters (SwapParam struct)
* @param _callbackData Encoded callback parameters (CallbackParam struct), empty for pure swap
* @param _permitData EIP-2612 permit signature data for gasless approval (optional)
* @param _feeData Encoded fee configuration (Fee struct)
*/
function swapAndCall(
bytes32 _transferId,
address _initiator,
address _srcToken,
uint256 _amount,
bytes calldata _swapData,
bytes calldata _callbackData,
bytes calldata _permitData,
bytes calldata _feeData
) external payable;
/**
* @notice Executes token swap and cross-chain bridge operation
* @dev Supports two operations:
* 1. Pure bridge: _swapData.length == 0 and _bridgeData.length > 0
* 2. Swap and bridge: _swapData.length > 0 and _bridgeData.length > 0
* @param _transferId Unique identifier for this transfer
* @param _initiator Address that initiated this transaction
* @param _srcToken Address of the source token to swap from
* @param _amount Amount of source tokens to process
* @param _swapData Encoded swap parameters (SwapParam struct), empty for pure bridge
* @param _bridgeData Encoded bridge parameters (BridgeParam struct)
* @param _permitData EIP-2612 permit signature data for gasless approval (optional)
* @param _feeData Encoded fee configuration (Fee struct)
* @return orderId Unique bridge order ID returned from bridge contract
*/
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);
/**
* @notice Calculates fees for a given transaction
* @param _inputToken Address of the input token
* @param _inputAmount Amount of input tokens
* @param _feeData Encoded fee configuration (Fee struct)
* @return feeToken Address of the token used for fee payment
* @return tokenFee Amount of token fees to be charged
* @return nativeFee Amount of native token fees to be charged
* @return afterFeeAmount Amount remaining after fee deduction
*/
function getFee(
address _inputToken,
uint256 _inputAmount,
bytes calldata _feeData
) external view returns (address feeToken, uint256 tokenFee, uint256 nativeFee, uint256 afterFeeAmount);
/**
* @notice Calculates the required input amount to achieve a desired output after fees
* @param _inputToken Address of the input token
* @param _afterFeeAmount Desired amount after fee deduction
* @param _feeData Encoded fee configuration (Fee struct)
* @return feeToken Address of the token used for fee payment
* @return inputAmount Required input amount to achieve desired output
* @return nativeFee Amount of native token fees required
*/
function getInputBeforeFee(
address _inputToken,
uint256 _afterFeeAmount,
bytes calldata _feeData
) external view returns (address feeToken, uint256 inputAmount, uint256 nativeFee);
}// SPDX-License-Identifier: MIT
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.0;
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();
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
}
}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":"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":"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":false,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ApproveToken","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":"_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":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveToken","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":[{"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":[],"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":[],"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":"_maxFeeRate","type":"uint256"},{"internalType":"uint256","name":"_maxNativeFee","type":"uint256"}],"name":"setReferrerMaxFee","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"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60a06040526040516200401e3803806200401e8339810160408190526200002691620003e3565b81816001600160a01b0381163b62000051576040516308ebd80360e11b815260040160405180910390fd5b6001600160a01b0316608052600160208190527f22e6613cccf9bbcab95eb0ca2576d52ca25c9df9cdd033ef0c884bd5f77c6b08805460ff1990811683179091557fdc83fc47acfa10aad2fb4b3ba164cfab7d821ba31fc3fa6106fbbc3e06e24ecd80548216831790557fce0bd6e656eb7c8d50ede2dcd48631717efe69613db35062e41aebd62ba38b5880548216831790557f63ac0de42ce407851e5a32ea18a840840698690522dafa8b19af51a3f9f776d880548216831790557fb7bb635797f8b82434bbbb3b236f6d0327dea0b55ace7b62d81825e2f9e7172480548216831790557fa9f056a98923f1e624660382482b9e4c740e3f263192c36632ccad1b4fcd621080548216831790557fc0466170f46bdc8859cdc09e56cdd7f39816b8251372ac4f0d3ac34d526539be80548216831790557f9fe100309a1f9e787d3d66393d3cc17fa671ebf9a345e9e528d41adf7b4e492680548216831790557f9deaf2b004475d835bd7f5260bae3e41fa5021050045f1764b9c35219ad74b3080548216831790557f4a982d3e17b62bc77b70659979697be0e0c42e254b31aa4a0345ce8a5fb9afde80548216831790557f57644f975fe7cc13dd7361969d38188b142ebeb31215d6270a81d61e886fbc518054821683179055631759616b60e11b6000527f3d3d7394da34ef234b62c6e28c686978e1a7a6e440aac94fd0190e814e094db5805490911690911790556200026d33620002e3565b6001600160a01b038116620002955760405163538ba4f960e01b815260040160405180910390fd5b620002a081620002e3565b5060016009556001600160a01b0383163b620002cf576040516308ebd80360e11b815260040160405180910390fd5b620002da8362000301565b5050506200042d565b600380546001600160a01b0319169055620002fe8162000374565b50565b6001600160a01b0381163b6200032a576040516308ebd80360e11b815260040160405180910390fd5b600a80546001600160a01b0319166001600160a01b0383169081179091556040517f53b7c37d01415b2804281f4684b0722e0b01fbd375bf502609f465e17ab4441e90600090a250565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b0381168114620003de57600080fd5b919050565b600080600060608486031215620003f957600080fd5b6200040484620003c6565b92506200041460208501620003c6565b91506200042460408501620003c6565b90509250925092565b608051613bd562000449600039600061269b0152613bd56000f3fe6080604052600436106101bb5760003560e01c80638da5cb5b116100ec578063d8b964e61161008a578063df5d452311610064578063df5d45231461057d578063e30c39781461059d578063f2fde38b146105bb578063f5e53a64146105db57600080fd5b8063d8b964e61461050d578063d904371e1461053d578063da3e33971461055d57600080fd5b8063a73ceca7116100c6578063a73ceca714610463578063b3f00674146104ad578063c1b1660e146104cd578063d0fb0203146104ed57600080fd5b80638da5cb5b146103fb5780638dc060ff1461042d578063a3c573eb1461044357600080fd5b8063715018a6116101595780637ae69a98116101335780637ae69a98146103025780637f5a22f914610347578063823991751461036757806385c17830146103e557600080fd5b8063715018a6146102b857806378e3214f146102cd57806379ba5097146102ed57600080fd5b8063278fd20211610195578063278fd20214610241578063472d35b91461026157806352b2d543146102815780636e1537da146102a557600080fd5b8063119b8248146101c757806311c4b772146101dc578063227c5412146101fc57600080fd5b366101c257005b600080fd5b6101da6101d5366004612daa565b6105f1565b005b3480156101e857600080fd5b506101da6101f7366004612ee1565b6108e2565b34801561020857600080fd5b5061022c610217366004612f18565b60016020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b34801561024d57600080fd5b506101da61025c366004612f33565b6108f8565b34801561026d57600080fd5b506101da61027c366004612f55565b610949565b34801561028d57600080fd5b5061029760055481565b604051908152602001610238565b6102976102b3366004612daa565b6109c3565b3480156102c457600080fd5b506101da610ba1565b3480156102d957600080fd5b506101da6102e8366004612f72565b610bb5565b3480156102f957600080fd5b506101da610bc8565b34801561030e57600080fd5b5061032261031d366004612f9e565b610c47565b604080516001600160a01b039094168452602084019290925290820152606001610238565b34801561035357600080fd5b5061022c610362366004612f55565b610dca565b34801561037357600080fd5b50610387610382366004612f9e565b610de6565b6040805182516001600160a01b039081168252602080850151821690830152838301511691810191909152606080830151908201526080808301519082015260a0808301519082015260c0918201519181019190915260e001610238565b3480156103f157600080fd5b5061029760075481565b34801561040757600080fd5b506002546001600160a01b03165b6040516001600160a01b039091168152602001610238565b34801561043957600080fd5b5061029760045481565b34801561044f57600080fd5b50600a54610415906001600160a01b031681565b34801561046f57600080fd5b5061048361047e366004612f9e565b610e05565b604080516001600160a01b0390951685526020850193909352918301526060820152608001610238565b3480156104b957600080fd5b50600654610415906001600160a01b031681565b3480156104d957600080fd5b506101da6104e8366004612ff9565b610e3d565b3480156104f957600080fd5b50600b54610415906001600160a01b031681565b34801561051957600080fd5b5061022c610528366004612f55565b60006020819052908152604090205460ff1681565b34801561054957600080fd5b506101da61055836600461302e565b610ed4565b34801561056957600080fd5b506101da6105783660046130b3565b611029565b34801561058957600080fd5b50610322610598366004612f9e565b611095565b3480156105a957600080fd5b506003546001600160a01b0316610415565b3480156105c757600080fd5b506101da6105d6366004612f55565b6111a8565b3480156105e757600080fd5b5061029760085481565b6105f9611219565b610601612c7e565b6001600160a01b03808d1660c08301528b16808252604082018b9052608082018e9052610630908b8787611272565b610180830152610160820152610646868961310a565b600003610666576040516312cd5ab760e11b815260040160405180910390fd5b61066e612cea565b610682826000015183604001518686611329565b6001600160a01b031660a0808601919091526060808601929092528201519082015160c083015160808401519394506000936106be919061310a565b6106c8919061310a565b6106d2919061310a565b11156107745780604001516001600160a01b031681602001516001600160a01b031683600001516001600160a01b03167ffe2e49614659d9447156c9e3846112ea8edda361dcd696be486f6f977ce854e58460a001518560c0015186606001518760800151896080015160405161076b959493929190948552602085019390935260408401919091526060830152608082015260a00190565b60405180910390a45b610790826000015183606001518461018001518d8d8d8d6114ba565b6101208701819052606087018290526001600160a01b039283166020880152928216610100870152921660e085015210156107ec576107ec82602001518360e0015184610120015185606001516107e7919061311d565b611504565b336001600160a01b03168260c001516001600160a01b03168360a001516001600160a01b03167f60656aafa8d4c0a705aeb148b167d7db921d08852cd2261b270d5c7a2e655f83856080015186600001518760200151886040015189606001518a60e001518b61010001518c61012001516040516108b29897969594939291909788526001600160a01b039687166020890152948616604088015260608701939093526080860191909152831660a085015290911660c083015260e08201526101000190565b60405180910390a46108c882610160015161160b565b50506108d46001600955565b505050505050505050505050565b6108ea61162c565b6108f48282611686565b5050565b61090061162c565b612710821061090e57600080fd5b60078290556008819055604051819083907f5b2f81a75439605ecd08ce07af893a489989a97d6d2008dff44c6827503ba82c90600090a35050565b61095161162c565b6001600160a01b0381163b610979576040516308ebd80360e11b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0383169081179091556040517f5d0517e3a4eabea892d9750138cd21d4a6cf3b935b43d0598df7055f463819b290600090a250565b60006109cd611219565b8560008190036109f0576040516312cd5ab760e11b815260040160405180910390fd5b6109f8612c7e565b8d8160c001906001600160a01b031690816001600160a01b0316815250508c81600001906001600160a01b031690816001600160a01b0316815250508b8160400181815250508c81602001906001600160a01b031690816001600160a01b0316815250508b8160600181815250508e816080018181525050610a84816000015182604001518989611272565b6101808301526101608201528915610ac557610ab0816000015182606001518361018001518e8e6116ea565b5060608301526001600160a01b031660208201525b610acf85856117ce565b6001600160a01b031660a082015260208101516060808301519091610af8913391908d8d6117e5565b610140850182905260c085015160a08601516080870151875160208901516040808b015160608c01519151999d5096995033986001600160a01b039687169895909616967fba828651bf4de06e53231285961e555fd7dfe17a3e39d64b09fbaa8ebc0166c696610b6e968f959493918d90613180565b60405180910390a4610b8482610160015161160b565b505050610b916001600955565b9c9b505050505050505050505050565b610ba961162c565b610bb360006118cb565b565b610bbd61162c565b6108f4823383611504565b60035433906001600160a01b03168114610c3b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b610c44816118cb565b50565b600080600080610c5786866118e4565b6006549091506001600160a01b0316158015610c7e575060208101516001600160a01b0316155b15610c9457600087600093509350935050610dc0565b6006546000906001600160a01b031615610cc857600554610cb5908461310a565b925060045481610cc5919061310a565b90505b60208201516001600160a01b031615610d1d57600082516001811115610cf057610cf06131d9565b03610d0b576040820151610d04908461310a565b9250610d1d565b6040820151610d1a908261310a565b90505b6001600160a01b0389161580610d4f575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b038a16145b15610d9b57610d5e838961310a565b93508015610d9657610d728161271061311d565b610d7e612710866131ef565b610d889190613206565b610d9390600161310a565b93505b610dbd565b8015610db957610dad8161271061311d565b610d7e6127108a6131ef565b8793505b50505b9450945094915050565b6000610dd461162c565b610ddd826119de565b5060015b919050565b610dee612cea565b610dfa85858585611a50565b90505b949350505050565b6000806000806000610e1989898989611bd2565b805195509050610e2a898983611c74565b969b919a50985094965093945050505050565b610e4561162c565b6001600160a01b038316610e6c5760405163538ba4f960e01b815260040160405180910390fd5b6127108210610e7a57600080fd5b600680546001600160a01b0319166001600160a01b03851690811790915560048390556005829055604051829184917f17906aa05b055ced1cea92b104912638c3ec8c90eec152fca6f36fbd8becca1d90600090a4505050565b610edc61162c565b6000829003610efe57604051630239912560e01b815260040160405180910390fd5b60005b8281101561102357610f42848483818110610f1e57610f1e613228565b9050602002016020810190610f339190612f55565b6001600160a01b03163b151590565b610f5f576040516308ebd80360e11b815260040160405180910390fd5b81600080868685818110610f7557610f75613228565b9050602002016020810190610f8a9190612f55565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055811515848483818110610fc757610fc7613228565b9050602002016020810190610fdc9190612f55565b6001600160a01b03167f1f478f1e5aee36a892d86e821aba410dc0934cb0ebd0241dd75370833884545360405160405180910390a38061101b8161323e565b915050610f01565b50505050565b61103161162c565b6110456001600160a01b0384168383611d12565b604080516001600160a01b038086168252841660208201529081018290527feded619173dbb378903f97d44ecec898a1c4876f445ae551e063113aef58b4719060600160405180910390a1505050565b600b54600090819081906001600160a01b031661112157604051630f5cd35360e31b81523090637ae69a98906110d5908a908a908a908a90600401613257565b606060405180830381865afa1580156110f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611116919061329f565b925092509250610dc0565b600b54604051630f5cd35360e31b81526001600160a01b0390911690637ae69a9890611157908a908a908a908a90600401613257565b606060405180830381865afa158015611174573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611198919061329f565b9250925092509450945094915050565b6111b061162c565b600380546001600160a01b0383166001600160a01b031990911681179091556111e16002546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60026009540361126b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c32565b6002600955565b600080846000036112965760405163090b95c560e31b815260040160405180910390fd5b3083156112a7576112a78585611dd4565b6112bb346001600160a01b0383163161311d565b92506112c687611e15565b1561130757853410156112ec57604051637d6b3cdf60e11b815260040160405180910390fd5b611300866001600160a01b0383163161311d565b915061131f565b6113118782611e4e565b915061131f87338389611ee0565b5094509492505050565b611331612cea565b60008061134087878787611bd2565b92508260400151905061135287611e15565b156113cf5760008360a00151846060015161136d919061310a565b905080156113845761138488856020015183611504565b600084608001518560c0015161139a919061310a565b905080156113b1576113b189866040015183611504565b806113bc838a61311d565b6113c6919061311d565b93505050611499565b6060830151156113ed576113ed600084602001518560600151611504565b60a08301511561140a5761140a8784602001518560a00151611504565b60808301511561142857611428600084604001518560800151611504565b60c083015115611445576114458784604001518560c00151611504565b60c083015160a0840151611459908861311d565b611463919061311d565b9150348360800151846060015161147a919061310a565b111561149957604051637d6b3cdf60e11b815260040160405180910390fd5b81600003610dc05760405163090b95c560e31b815260040160405180910390fd5b60008088888287156114db576114d38c8c8c8c8c6116ea565b965090935091505b85156114f5576114ed82848989611f18565b909650945090505b97509750975097509792505050565b61150d83611e15565b156115215761151c8282612036565b505050565b46632b6653dc81148015611551575073a614f803b6fd780986a42c78ec9c7f77e6ded13c6001600160a01b038516145b156115f757604080516001600160a01b038581166024830152604480830186905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151918616916115ad91906132d6565b6000604051808303816000865af19150503d80600081146115ea576040519150601f19603f3d011682016040523d82523d6000602084013e6115ef565b606091505b505050611023565b6110236001600160a01b038516848461214f565b80471015610c4457604051630cfbd6ed60e01b815260040160405180910390fd5b6002546001600160a01b03163314610bb35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c32565b6001600160e01b03198216600081815260016020908152604091829020805460ff19168515159081179091558251938452908301527fc4a5aadd92b2d0e7efaf25f9d44b0e6fca6c44da8e09fc3250cc12ef954cb60e910160405180910390a15050565b60008080806116fb85870187613444565b602081015181519550925090506001600160a01b03808516908a1603611737576040516001624cdd6d60e11b0319815260040160405180910390fd5b3060006117448683611e4e565b90506117558b8b856080015161217f565b806117608784611e4e565b61176a919061311d565b94508260600151851015611791576040516319af26f360e31b815260040160405180910390fd5b60008961179e8d85611e4e565b6117a8919061311d565b905080156117bf576117bf8c856040015183611504565b50505050955095509592505050565b6000604082106117df575060208201355b92915050565b6000806060816117f7858701876135e0565b80516040820151600a5491955093509091506001600160a01b0316600061181d8a611e15565b61182b57826020015161183b565b88836020015161183b919061310a565b9050816001600160a01b031663b899f904828d8d888e8b8a606001516040518863ffffffff1660e01b815260040161187896959493929190613684565b60206040518083038185885af1158015611896573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906118bb91906136db565b9550505050955095509592505050565b600380546001600160a01b0319169055610c4481612301565b604080516060810182526000808252602082018190529181019190915281156117df57611913828401846136f4565b905060018151600181111561192a5761192a6131d9565b03611989576007548160400151106119845760405162461bcd60e51b815260206004820152601b60248201527f4665654d616e616765723a20696e76616c6964206665655261746500000000006044820152606401610c32565b6117df565b6008548160400151106117df5760405162461bcd60e51b815260206004820152601e60248201527f4665654d616e616765723a20696e76616c6964206e61746976652066656500006044820152606401610c32565b6001600160a01b0381163b611a06576040516308ebd80360e11b815260040160405180910390fd5b600a80546001600160a01b0319166001600160a01b0383169081179091556040517f53b7c37d01415b2804281f4684b0722e0b01fbd375bf502609f465e17ab4441e90600090a250565b611a58612cea565b6000611a6484846118e4565b6006549091506001600160a01b0316158015611a8b575060208101516001600160a01b0316155b15611a965750610dfd565b6001600160a01b0380871683526006541615611b22576006546001600160a01b03908116602084015260055460608401528616611b015761271060045486611ade91906131ef565b611ae89190613206565b82606001818151611af9919061310a565b905250611b22565b61271060045486611b1291906131ef565b611b1c9190613206565b60a08301525b60208101516001600160a01b031615611bc95760208101516001600160a01b03166040830152600081516001811115611b5d57611b5d6131d9565b03611b715760408101516080830152611bc9565b6001600160a01b038616611ba657612710816040015186611b9291906131ef565b611b9c9190613206565b6080830152611bc9565b612710816040015186611bb991906131ef565b611bc39190613206565b60c08301525b50949350505050565b611bda612cea565b600b546001600160a01b0316611bfd57611bf685858585611a50565b9050610dfd565b600b54604051638239917560e01b81526001600160a01b0390911690638239917590611c33908890889088908890600401613257565b60e060405180830381865afa158015611c50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfa9190613762565b6000806000611c8286611e15565b15611cd0576000925083608001518460c001518560a001518660600151611ca9919061310a565b611cb3919061310a565b611cbd919061310a565b9150611cc9828661311d565b9050611d09565b8360c001518460a00151611ce4919061310a565b925083608001518460600151611cfa919061310a565b9150611d06838661311d565b90505b93509350939050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052611d638482612353565b611023576040516001600160a01b038416602482015260006044820152611dca90859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526123fa565b61102384826123fa565b600080808080808080611de9898b018b613800565b97509750975097509750975097509750611e0988888888888888886124cf565b50505050505050505050565b60006001600160a01b03821615806117df57506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b6000611e5983611e15565b15611e6f57506001600160a01b038116316117df565b6040516370a0823160e01b81526001600160a01b0383811660048301528416906370a0823190602401602060405180830381865afa158015611eb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed991906136db565b90506117df565b6040516001600160a01b03808516602483015283166044820152606481018290526110239085906323b872dd60e01b90608401611d93565b6000808080611f2985870187613889565b608081015181519094509250905030611f428882611e4e565b604083015160a0840151919650906023821115611f5f578a828201525b6020810151611f6e8682612699565b6000611f7f8c87602001518f6127b1565b8660600151611f8e919061310a565b90506000876001600160a01b03168285604051611fab91906132d6565b60006040518083038185875af1925050503d8060008114611fe8576040519150601f19603f3d011682016040523d82523d6000602084013e611fed565b606091505b505090508061200f57604051637588692960e01b815260040160405180910390fd5b6120198d87611e4e565b612023908b61311d565b9950505050505050509450945094915050565b804710156120865760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610c32565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146120d3576040519150601f19603f3d011682016040523d82523d6000602084013e6120d8565b606091505b505090508061151c5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610c32565b6040516001600160a01b03831660248201526044810182905261151c90849063a9059cbb60e01b90606401611d93565b805160008190036121a357604051630239912560e01b815260040160405180910390fd5b60008060006121b3868587612863565b9194509250905081151560005b858110156122f65760008782815181106121dc576121dc613228565b60200260200101519050600081606001519050831561224f578260000361222857846122145761220c868261311d565b905080612222565b61221e868261310a565b9050805b5061224f565b8461223f57612237878261311d565b90508061224d565b612249878261310a565b9050805b505b81516000906004816005811115612268576122686131d9565b03612288576122818d8560200151858760800151612943565b91506122c9565b600581600581111561229c5761229c6131d9565b036122b0576122818d848660800151612a2f565b6040516318f9c3a760e11b815260040160405180910390fd5b816122e757604051636ff55bbf60e01b815260040160405180910390fd5b846001019450505050506121c0565b505050505050505050565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000806000846001600160a01b03168460405161237091906132d6565b6000604051808303816000865af19150503d80600081146123ad576040519150601f19603f3d011682016040523d82523d6000602084013e6123b2565b606091505b50915091508180156123dc5750805115806123dc5750808060200190518101906123dc9190613944565b80156123f157506001600160a01b0385163b15155b95945050505050565b600061244f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612b5b9092919063ffffffff16565b90508051600014806124705750808060200190518101906124709190613944565b61151c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610c32565b604051623f675f60e91b81526001600160a01b038881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015612518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061253c91906136db565b60405163d505accf60e01b81526001600160a01b038a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b1580156125b057600080fd5b505af11580156125c4573d6000803e3d6000fd5b5050604051623f675f60e91b81526001600160a01b038b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015612610573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263491906136db565b905061264182600161310a565b8114611e095760405162461bcd60e51b815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f74207375636365656044820152601960fa1b6064820152608401610c32565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03838116908216148015906126ef57506001600160a01b03831660009081526020819052604090205460ff16155b1561270d5760405163369370d960e01b815260040160405180910390fd5b6001600160e01b0319821660009081526001602052604090205460ff161561274857604051630d1a468960e01b815260040160405180910390fd5b806001600160a01b0316836001600160a01b03160361151c576001600160e01b03198216632e1a7d4d60e01b1480159061279357506001600160e01b03198216630d0e30db60e41b14155b1561151c57604051630d1a468960e01b815260040160405180910390fd5b60006127bc84611e15565b156127c857508061285c565b604051636eb1769f60e11b81523060048201526001600160a01b0384811660248301526000919086169063dd62ed3e90604401602060405180830381865afa158015612818573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061283c91906136db565b90508281101561285a5761285a6001600160a01b0386168585611d12565b505b9392505050565b6000808080805b868110156128a55785818151811061288457612884613228565b6020026020010151606001518261289b919061310a565b915060010161286a565b50868111156128f15760009150816128bd888361311d565b90506128c98782613206565b94506128d587866131ef565b6128df908261311d565b6128e9908661310a565b935050612939565b8681101561293957600191506000612909828961311d565b90506129158782613206565b945061292187866131ef565b61292b908261311d565b612935908661310a565b9350505b5093509350939050565b60008060008380602001905181019061295c91906139a6565b8151919350915060005b818110156129a457600084828151811061298257612982613228565b60200260200101519050602381111561299b5787818501525b50600101612966565b5060208201516129b48882612699565b60006129c18a8a8a6127b1565b9050886001600160a01b031681856040516129dc91906132d6565b60006040518083038185875af1925050503d8060008114612a19576040519150601f19603f3d011682016040523d82523d6000602084013e612a1e565b606091505b50909b9a5050505050505050505050565b60008082806020019051810190612a469190613a61565b80519091503060005b82811015612b50576000848281518110612a6b57612a6b613228565b6020026020010151905081600014612a915780602001519850612a8e8984611e4e565b97505b608081015181516023811115612aa75789818301525b60208201516040840151612abb8183612699565b6000612acc8e87606001518f6127b1565b9050816001600160a01b03168186604051612ae791906132d6565b60006040518083038185875af1925050503d8060008114612b24576040519150601f19603f3d011682016040523d82523d6000602084013e612b29565b606091505b5050809b50508a612b3f57505050505050612b50565b866001019650505050505050612a4f565b505050509392505050565b6060610dfd848460008585600080866001600160a01b03168587604051612b8291906132d6565b60006040518083038185875af1925050503d8060008114612bbf576040519150601f19603f3d011682016040523d82523d6000602084013e612bc4565b606091505b5091509150612bd587838387612be0565b979650505050505050565b60608315612c4f578251600003612c48576001600160a01b0385163b612c485760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c32565b5081610dfd565b610dfd8383815115612c645781518083602001fd5b8060405162461bcd60e51b8152600401610c329190613b8c565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081019190915290565b6040518060e0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b0381168114610c4457600080fd5b8035610de181612d42565b60008083601f840112612d7457600080fd5b5081356001600160401b03811115612d8b57600080fd5b602083019150836020828501011115612da357600080fd5b9250929050565b6000806000806000806000806000806000806101008d8f031215612dcd57600080fd5b8c359b50612ddd60208e01612d57565b9a50612deb60408e01612d57565b995060608d013598506001600160401b0360808e01351115612e0c57600080fd5b612e1c8e60808f01358f01612d62565b90985096506001600160401b0360a08e01351115612e3957600080fd5b612e498e60a08f01358f01612d62565b90965094506001600160401b0360c08e01351115612e6657600080fd5b612e768e60c08f01358f01612d62565b90945092506001600160401b0360e08e01351115612e9357600080fd5b612ea38e60e08f01358f01612d62565b81935080925050509295989b509295989b509295989b565b80356001600160e01b031981168114610de157600080fd5b8015158114610c4457600080fd5b60008060408385031215612ef457600080fd5b612efd83612ebb565b91506020830135612f0d81612ed3565b809150509250929050565b600060208284031215612f2a57600080fd5b61285c82612ebb565b60008060408385031215612f4657600080fd5b50508035926020909101359150565b600060208284031215612f6757600080fd5b813561285c81612d42565b60008060408385031215612f8557600080fd5b8235612f9081612d42565b946020939093013593505050565b60008060008060608587031215612fb457600080fd5b8435612fbf81612d42565b93506020850135925060408501356001600160401b03811115612fe157600080fd5b612fed87828801612d62565b95989497509550505050565b60008060006060848603121561300e57600080fd5b833561301981612d42565b95602085013595506040909401359392505050565b60008060006040848603121561304357600080fd5b83356001600160401b038082111561305a57600080fd5b818601915086601f83011261306e57600080fd5b81358181111561307d57600080fd5b8760208260051b850101111561309257600080fd5b602092830195509350508401356130a881612ed3565b809150509250925092565b6000806000606084860312156130c857600080fd5b83356130d381612d42565b925060208401356130e381612d42565b929592945050506040919091013590565b634e487b7160e01b600052601160045260246000fd5b808201808211156117df576117df6130f4565b818103818111156117df576117df6130f4565b60005b8381101561314b578181015183820152602001613133565b50506000910152565b6000815180845261316c816020860160208601613130565b601f01601f19169290920160200192915050565b60006101008a835289602084015260018060a01b03808a1660408501528089166060850152508660808401528560a08401528460c08401528060e08401526131ca81840185613154565b9b9a5050505050505050505050565b634e487b7160e01b600052602160045260246000fd5b80820281158282048414176117df576117df6130f4565b60008261322357634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b600060018201613250576132506130f4565b5060010190565b6001600160a01b0385168152602081018490526060604082018190528101829052818360808301376000818301608090810191909152601f909201601f191601019392505050565b6000806000606084860312156132b457600080fd5b83516132bf81612d42565b602085015160409095015190969495509392505050565b600082516132e8818460208701613130565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b038111828210171561332a5761332a6132f2565b60405290565b604051608081016001600160401b038111828210171561332a5761332a6132f2565b60405160c081016001600160401b038111828210171561332a5761332a6132f2565b604051601f8201601f191681016001600160401b038111828210171561339c5761339c6132f2565b604052919050565b60006001600160401b038211156133bd576133bd6132f2565b5060051b60200190565b60006001600160401b038211156133e0576133e06132f2565b50601f01601f191660200190565b600082601f8301126133ff57600080fd5b813561341261340d826133c7565b613374565b81815284602083860101111561342757600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561345757600080fd5b82356001600160401b038082111561346e57600080fd5b9084019060a0828703121561348257600080fd5b61348a613308565b823561349581612d42565b8152828401356134a481612d42565b8185015260408301356134b681612d42565b604082015260608381013590820152608080840135838111156134d857600080fd5b80850194505087601f8501126134ed57600080fd5b83356134fb61340d826133a4565b81815260059190911b8501860190868101908a83111561351a57600080fd5b8787015b838110156135cb578035878111156135365760008081fd5b880160a0818e03601f1901121561354d5760008081fd5b613555613308565b8a820135600681106135675760008081fd5b8152604082013561357781612d42565b818c0152606082013561358981612d42565b604082015281870135606082015260a0820135898111156135aa5760008081fd5b6135b88f8d838601016133ee565b828901525084525091880191880161351e565b50928401929092525090979650505050505050565b6000602082840312156135f257600080fd5b81356001600160401b038082111561360957600080fd5b908301906080828603121561361d57600080fd5b613625613330565b823581526020830135602082015260408301358281111561364557600080fd5b613651878286016133ee565b60408301525060608301358281111561366957600080fd5b613675878286016133ee565b60608301525095945050505050565b6001600160a01b0387811682528616602082015260c0604082018190526000906136b090830187613154565b85606084015284608084015282810360a08401526136ce8185613154565b9998505050505050505050565b6000602082840312156136ed57600080fd5b5051919050565b60006060828403121561370657600080fd5b604051606081018181106001600160401b0382111715613728576137286132f2565b60405282356002811061373a57600080fd5b8152602083013561374a81612d42565b60208201526040928301359281019290925250919050565b600060e0828403121561377457600080fd5b60405160e081018181106001600160401b0382111715613796576137966132f2565b60405282516137a481612d42565b815260208301516137b481612d42565b602082015260408301516137c781612d42565b80604083015250606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600080600080600080600080610100898b03121561381d57600080fd5b883561382881612d42565b9750602089013561383881612d42565b9650604089013561384881612d42565b9550606089013594506080890135935060a089013560ff8116811461386c57600080fd5b979a969950949793969295929450505060c08201359160e0013590565b60006020828403121561389b57600080fd5b81356001600160401b03808211156138b257600080fd5b9083019060c082860312156138c657600080fd5b6138ce613352565b82356138d981612d42565b815260208301356138e981612d42565b806020830152506040830135604082015260608301356060820152608083013561391281612d42565b608082015260a08301358281111561392957600080fd5b613935878286016133ee565b60a08301525095945050505050565b60006020828403121561395657600080fd5b815161285c81612ed3565b600082601f83011261397257600080fd5b815161398061340d826133c7565b81815284602083860101111561399557600080fd5b610dfd826020830160208701613130565b600080604083850312156139b957600080fd5b82516001600160401b03808211156139d057600080fd5b818501915085601f8301126139e457600080fd5b815160206139f461340d836133a4565b82815260059290921b84018101918181019089841115613a1357600080fd5b948201945b83861015613a3157855182529482019490820190613a18565b91880151919650909350505080821115613a4a57600080fd5b50613a5785828601613961565b9150509250929050565b60006020808385031215613a7457600080fd5b82516001600160401b0380821115613a8b57600080fd5b818501915085601f830112613a9f57600080fd5b8151613aad61340d826133a4565b81815260059190911b83018401908481019088831115613acc57600080fd5b8585015b83811015613b7f57805185811115613ae85760008081fd5b860160a0818c03601f1901811315613b005760008081fd5b613b08613308565b898301518152604080840151613b1d81612d42565b828c0152606084810151613b3081612d42565b8083850152506080915081850151613b4781612d42565b90830152918301519188831115613b5e5760008081fd5b613b6c8e8c85870101613961565b9082015285525050918601918601613ad0565b5098975050505050505050565b60208152600061285c602083018461315456fea2646970667358221220a53988482258f99f8f83f8981ce4ec11fd76326136d8e3af578843a522915d4464736f6c634300081300330000000000000000000000000000317bec33af037b5fab2028f52d14658f6a5600000000000000000000000026f71baa9dcda856c5612949cb01596c856a2cbb0000000000000000000000004200000000000000000000000000000000000006
Deployed Bytecode
0x6080604052600436106101bb5760003560e01c80638da5cb5b116100ec578063d8b964e61161008a578063df5d452311610064578063df5d45231461057d578063e30c39781461059d578063f2fde38b146105bb578063f5e53a64146105db57600080fd5b8063d8b964e61461050d578063d904371e1461053d578063da3e33971461055d57600080fd5b8063a73ceca7116100c6578063a73ceca714610463578063b3f00674146104ad578063c1b1660e146104cd578063d0fb0203146104ed57600080fd5b80638da5cb5b146103fb5780638dc060ff1461042d578063a3c573eb1461044357600080fd5b8063715018a6116101595780637ae69a98116101335780637ae69a98146103025780637f5a22f914610347578063823991751461036757806385c17830146103e557600080fd5b8063715018a6146102b857806378e3214f146102cd57806379ba5097146102ed57600080fd5b8063278fd20211610195578063278fd20214610241578063472d35b91461026157806352b2d543146102815780636e1537da146102a557600080fd5b8063119b8248146101c757806311c4b772146101dc578063227c5412146101fc57600080fd5b366101c257005b600080fd5b6101da6101d5366004612daa565b6105f1565b005b3480156101e857600080fd5b506101da6101f7366004612ee1565b6108e2565b34801561020857600080fd5b5061022c610217366004612f18565b60016020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b34801561024d57600080fd5b506101da61025c366004612f33565b6108f8565b34801561026d57600080fd5b506101da61027c366004612f55565b610949565b34801561028d57600080fd5b5061029760055481565b604051908152602001610238565b6102976102b3366004612daa565b6109c3565b3480156102c457600080fd5b506101da610ba1565b3480156102d957600080fd5b506101da6102e8366004612f72565b610bb5565b3480156102f957600080fd5b506101da610bc8565b34801561030e57600080fd5b5061032261031d366004612f9e565b610c47565b604080516001600160a01b039094168452602084019290925290820152606001610238565b34801561035357600080fd5b5061022c610362366004612f55565b610dca565b34801561037357600080fd5b50610387610382366004612f9e565b610de6565b6040805182516001600160a01b039081168252602080850151821690830152838301511691810191909152606080830151908201526080808301519082015260a0808301519082015260c0918201519181019190915260e001610238565b3480156103f157600080fd5b5061029760075481565b34801561040757600080fd5b506002546001600160a01b03165b6040516001600160a01b039091168152602001610238565b34801561043957600080fd5b5061029760045481565b34801561044f57600080fd5b50600a54610415906001600160a01b031681565b34801561046f57600080fd5b5061048361047e366004612f9e565b610e05565b604080516001600160a01b0390951685526020850193909352918301526060820152608001610238565b3480156104b957600080fd5b50600654610415906001600160a01b031681565b3480156104d957600080fd5b506101da6104e8366004612ff9565b610e3d565b3480156104f957600080fd5b50600b54610415906001600160a01b031681565b34801561051957600080fd5b5061022c610528366004612f55565b60006020819052908152604090205460ff1681565b34801561054957600080fd5b506101da61055836600461302e565b610ed4565b34801561056957600080fd5b506101da6105783660046130b3565b611029565b34801561058957600080fd5b50610322610598366004612f9e565b611095565b3480156105a957600080fd5b506003546001600160a01b0316610415565b3480156105c757600080fd5b506101da6105d6366004612f55565b6111a8565b3480156105e757600080fd5b5061029760085481565b6105f9611219565b610601612c7e565b6001600160a01b03808d1660c08301528b16808252604082018b9052608082018e9052610630908b8787611272565b610180830152610160820152610646868961310a565b600003610666576040516312cd5ab760e11b815260040160405180910390fd5b61066e612cea565b610682826000015183604001518686611329565b6001600160a01b031660a0808601919091526060808601929092528201519082015160c083015160808401519394506000936106be919061310a565b6106c8919061310a565b6106d2919061310a565b11156107745780604001516001600160a01b031681602001516001600160a01b031683600001516001600160a01b03167ffe2e49614659d9447156c9e3846112ea8edda361dcd696be486f6f977ce854e58460a001518560c0015186606001518760800151896080015160405161076b959493929190948552602085019390935260408401919091526060830152608082015260a00190565b60405180910390a45b610790826000015183606001518461018001518d8d8d8d6114ba565b6101208701819052606087018290526001600160a01b039283166020880152928216610100870152921660e085015210156107ec576107ec82602001518360e0015184610120015185606001516107e7919061311d565b611504565b336001600160a01b03168260c001516001600160a01b03168360a001516001600160a01b03167f60656aafa8d4c0a705aeb148b167d7db921d08852cd2261b270d5c7a2e655f83856080015186600001518760200151886040015189606001518a60e001518b61010001518c61012001516040516108b29897969594939291909788526001600160a01b039687166020890152948616604088015260608701939093526080860191909152831660a085015290911660c083015260e08201526101000190565b60405180910390a46108c882610160015161160b565b50506108d46001600955565b505050505050505050505050565b6108ea61162c565b6108f48282611686565b5050565b61090061162c565b612710821061090e57600080fd5b60078290556008819055604051819083907f5b2f81a75439605ecd08ce07af893a489989a97d6d2008dff44c6827503ba82c90600090a35050565b61095161162c565b6001600160a01b0381163b610979576040516308ebd80360e11b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0383169081179091556040517f5d0517e3a4eabea892d9750138cd21d4a6cf3b935b43d0598df7055f463819b290600090a250565b60006109cd611219565b8560008190036109f0576040516312cd5ab760e11b815260040160405180910390fd5b6109f8612c7e565b8d8160c001906001600160a01b031690816001600160a01b0316815250508c81600001906001600160a01b031690816001600160a01b0316815250508b8160400181815250508c81602001906001600160a01b031690816001600160a01b0316815250508b8160600181815250508e816080018181525050610a84816000015182604001518989611272565b6101808301526101608201528915610ac557610ab0816000015182606001518361018001518e8e6116ea565b5060608301526001600160a01b031660208201525b610acf85856117ce565b6001600160a01b031660a082015260208101516060808301519091610af8913391908d8d6117e5565b610140850182905260c085015160a08601516080870151875160208901516040808b015160608c01519151999d5096995033986001600160a01b039687169895909616967fba828651bf4de06e53231285961e555fd7dfe17a3e39d64b09fbaa8ebc0166c696610b6e968f959493918d90613180565b60405180910390a4610b8482610160015161160b565b505050610b916001600955565b9c9b505050505050505050505050565b610ba961162c565b610bb360006118cb565b565b610bbd61162c565b6108f4823383611504565b60035433906001600160a01b03168114610c3b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b610c44816118cb565b50565b600080600080610c5786866118e4565b6006549091506001600160a01b0316158015610c7e575060208101516001600160a01b0316155b15610c9457600087600093509350935050610dc0565b6006546000906001600160a01b031615610cc857600554610cb5908461310a565b925060045481610cc5919061310a565b90505b60208201516001600160a01b031615610d1d57600082516001811115610cf057610cf06131d9565b03610d0b576040820151610d04908461310a565b9250610d1d565b6040820151610d1a908261310a565b90505b6001600160a01b0389161580610d4f575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b038a16145b15610d9b57610d5e838961310a565b93508015610d9657610d728161271061311d565b610d7e612710866131ef565b610d889190613206565b610d9390600161310a565b93505b610dbd565b8015610db957610dad8161271061311d565b610d7e6127108a6131ef565b8793505b50505b9450945094915050565b6000610dd461162c565b610ddd826119de565b5060015b919050565b610dee612cea565b610dfa85858585611a50565b90505b949350505050565b6000806000806000610e1989898989611bd2565b805195509050610e2a898983611c74565b969b919a50985094965093945050505050565b610e4561162c565b6001600160a01b038316610e6c5760405163538ba4f960e01b815260040160405180910390fd5b6127108210610e7a57600080fd5b600680546001600160a01b0319166001600160a01b03851690811790915560048390556005829055604051829184917f17906aa05b055ced1cea92b104912638c3ec8c90eec152fca6f36fbd8becca1d90600090a4505050565b610edc61162c565b6000829003610efe57604051630239912560e01b815260040160405180910390fd5b60005b8281101561102357610f42848483818110610f1e57610f1e613228565b9050602002016020810190610f339190612f55565b6001600160a01b03163b151590565b610f5f576040516308ebd80360e11b815260040160405180910390fd5b81600080868685818110610f7557610f75613228565b9050602002016020810190610f8a9190612f55565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055811515848483818110610fc757610fc7613228565b9050602002016020810190610fdc9190612f55565b6001600160a01b03167f1f478f1e5aee36a892d86e821aba410dc0934cb0ebd0241dd75370833884545360405160405180910390a38061101b8161323e565b915050610f01565b50505050565b61103161162c565b6110456001600160a01b0384168383611d12565b604080516001600160a01b038086168252841660208201529081018290527feded619173dbb378903f97d44ecec898a1c4876f445ae551e063113aef58b4719060600160405180910390a1505050565b600b54600090819081906001600160a01b031661112157604051630f5cd35360e31b81523090637ae69a98906110d5908a908a908a908a90600401613257565b606060405180830381865afa1580156110f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611116919061329f565b925092509250610dc0565b600b54604051630f5cd35360e31b81526001600160a01b0390911690637ae69a9890611157908a908a908a908a90600401613257565b606060405180830381865afa158015611174573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611198919061329f565b9250925092509450945094915050565b6111b061162c565b600380546001600160a01b0383166001600160a01b031990911681179091556111e16002546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60026009540361126b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c32565b6002600955565b600080846000036112965760405163090b95c560e31b815260040160405180910390fd5b3083156112a7576112a78585611dd4565b6112bb346001600160a01b0383163161311d565b92506112c687611e15565b1561130757853410156112ec57604051637d6b3cdf60e11b815260040160405180910390fd5b611300866001600160a01b0383163161311d565b915061131f565b6113118782611e4e565b915061131f87338389611ee0565b5094509492505050565b611331612cea565b60008061134087878787611bd2565b92508260400151905061135287611e15565b156113cf5760008360a00151846060015161136d919061310a565b905080156113845761138488856020015183611504565b600084608001518560c0015161139a919061310a565b905080156113b1576113b189866040015183611504565b806113bc838a61311d565b6113c6919061311d565b93505050611499565b6060830151156113ed576113ed600084602001518560600151611504565b60a08301511561140a5761140a8784602001518560a00151611504565b60808301511561142857611428600084604001518560800151611504565b60c083015115611445576114458784604001518560c00151611504565b60c083015160a0840151611459908861311d565b611463919061311d565b9150348360800151846060015161147a919061310a565b111561149957604051637d6b3cdf60e11b815260040160405180910390fd5b81600003610dc05760405163090b95c560e31b815260040160405180910390fd5b60008088888287156114db576114d38c8c8c8c8c6116ea565b965090935091505b85156114f5576114ed82848989611f18565b909650945090505b97509750975097509792505050565b61150d83611e15565b156115215761151c8282612036565b505050565b46632b6653dc81148015611551575073a614f803b6fd780986a42c78ec9c7f77e6ded13c6001600160a01b038516145b156115f757604080516001600160a01b038581166024830152604480830186905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151918616916115ad91906132d6565b6000604051808303816000865af19150503d80600081146115ea576040519150601f19603f3d011682016040523d82523d6000602084013e6115ef565b606091505b505050611023565b6110236001600160a01b038516848461214f565b80471015610c4457604051630cfbd6ed60e01b815260040160405180910390fd5b6002546001600160a01b03163314610bb35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c32565b6001600160e01b03198216600081815260016020908152604091829020805460ff19168515159081179091558251938452908301527fc4a5aadd92b2d0e7efaf25f9d44b0e6fca6c44da8e09fc3250cc12ef954cb60e910160405180910390a15050565b60008080806116fb85870187613444565b602081015181519550925090506001600160a01b03808516908a1603611737576040516001624cdd6d60e11b0319815260040160405180910390fd5b3060006117448683611e4e565b90506117558b8b856080015161217f565b806117608784611e4e565b61176a919061311d565b94508260600151851015611791576040516319af26f360e31b815260040160405180910390fd5b60008961179e8d85611e4e565b6117a8919061311d565b905080156117bf576117bf8c856040015183611504565b50505050955095509592505050565b6000604082106117df575060208201355b92915050565b6000806060816117f7858701876135e0565b80516040820151600a5491955093509091506001600160a01b0316600061181d8a611e15565b61182b57826020015161183b565b88836020015161183b919061310a565b9050816001600160a01b031663b899f904828d8d888e8b8a606001516040518863ffffffff1660e01b815260040161187896959493929190613684565b60206040518083038185885af1158015611896573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906118bb91906136db565b9550505050955095509592505050565b600380546001600160a01b0319169055610c4481612301565b604080516060810182526000808252602082018190529181019190915281156117df57611913828401846136f4565b905060018151600181111561192a5761192a6131d9565b03611989576007548160400151106119845760405162461bcd60e51b815260206004820152601b60248201527f4665654d616e616765723a20696e76616c6964206665655261746500000000006044820152606401610c32565b6117df565b6008548160400151106117df5760405162461bcd60e51b815260206004820152601e60248201527f4665654d616e616765723a20696e76616c6964206e61746976652066656500006044820152606401610c32565b6001600160a01b0381163b611a06576040516308ebd80360e11b815260040160405180910390fd5b600a80546001600160a01b0319166001600160a01b0383169081179091556040517f53b7c37d01415b2804281f4684b0722e0b01fbd375bf502609f465e17ab4441e90600090a250565b611a58612cea565b6000611a6484846118e4565b6006549091506001600160a01b0316158015611a8b575060208101516001600160a01b0316155b15611a965750610dfd565b6001600160a01b0380871683526006541615611b22576006546001600160a01b03908116602084015260055460608401528616611b015761271060045486611ade91906131ef565b611ae89190613206565b82606001818151611af9919061310a565b905250611b22565b61271060045486611b1291906131ef565b611b1c9190613206565b60a08301525b60208101516001600160a01b031615611bc95760208101516001600160a01b03166040830152600081516001811115611b5d57611b5d6131d9565b03611b715760408101516080830152611bc9565b6001600160a01b038616611ba657612710816040015186611b9291906131ef565b611b9c9190613206565b6080830152611bc9565b612710816040015186611bb991906131ef565b611bc39190613206565b60c08301525b50949350505050565b611bda612cea565b600b546001600160a01b0316611bfd57611bf685858585611a50565b9050610dfd565b600b54604051638239917560e01b81526001600160a01b0390911690638239917590611c33908890889088908890600401613257565b60e060405180830381865afa158015611c50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfa9190613762565b6000806000611c8286611e15565b15611cd0576000925083608001518460c001518560a001518660600151611ca9919061310a565b611cb3919061310a565b611cbd919061310a565b9150611cc9828661311d565b9050611d09565b8360c001518460a00151611ce4919061310a565b925083608001518460600151611cfa919061310a565b9150611d06838661311d565b90505b93509350939050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052611d638482612353565b611023576040516001600160a01b038416602482015260006044820152611dca90859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526123fa565b61102384826123fa565b600080808080808080611de9898b018b613800565b97509750975097509750975097509750611e0988888888888888886124cf565b50505050505050505050565b60006001600160a01b03821615806117df57506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b6000611e5983611e15565b15611e6f57506001600160a01b038116316117df565b6040516370a0823160e01b81526001600160a01b0383811660048301528416906370a0823190602401602060405180830381865afa158015611eb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed991906136db565b90506117df565b6040516001600160a01b03808516602483015283166044820152606481018290526110239085906323b872dd60e01b90608401611d93565b6000808080611f2985870187613889565b608081015181519094509250905030611f428882611e4e565b604083015160a0840151919650906023821115611f5f578a828201525b6020810151611f6e8682612699565b6000611f7f8c87602001518f6127b1565b8660600151611f8e919061310a565b90506000876001600160a01b03168285604051611fab91906132d6565b60006040518083038185875af1925050503d8060008114611fe8576040519150601f19603f3d011682016040523d82523d6000602084013e611fed565b606091505b505090508061200f57604051637588692960e01b815260040160405180910390fd5b6120198d87611e4e565b612023908b61311d565b9950505050505050509450945094915050565b804710156120865760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610c32565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146120d3576040519150601f19603f3d011682016040523d82523d6000602084013e6120d8565b606091505b505090508061151c5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610c32565b6040516001600160a01b03831660248201526044810182905261151c90849063a9059cbb60e01b90606401611d93565b805160008190036121a357604051630239912560e01b815260040160405180910390fd5b60008060006121b3868587612863565b9194509250905081151560005b858110156122f65760008782815181106121dc576121dc613228565b60200260200101519050600081606001519050831561224f578260000361222857846122145761220c868261311d565b905080612222565b61221e868261310a565b9050805b5061224f565b8461223f57612237878261311d565b90508061224d565b612249878261310a565b9050805b505b81516000906004816005811115612268576122686131d9565b03612288576122818d8560200151858760800151612943565b91506122c9565b600581600581111561229c5761229c6131d9565b036122b0576122818d848660800151612a2f565b6040516318f9c3a760e11b815260040160405180910390fd5b816122e757604051636ff55bbf60e01b815260040160405180910390fd5b846001019450505050506121c0565b505050505050505050565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000806000846001600160a01b03168460405161237091906132d6565b6000604051808303816000865af19150503d80600081146123ad576040519150601f19603f3d011682016040523d82523d6000602084013e6123b2565b606091505b50915091508180156123dc5750805115806123dc5750808060200190518101906123dc9190613944565b80156123f157506001600160a01b0385163b15155b95945050505050565b600061244f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612b5b9092919063ffffffff16565b90508051600014806124705750808060200190518101906124709190613944565b61151c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610c32565b604051623f675f60e91b81526001600160a01b038881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015612518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061253c91906136db565b60405163d505accf60e01b81526001600160a01b038a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b1580156125b057600080fd5b505af11580156125c4573d6000803e3d6000fd5b5050604051623f675f60e91b81526001600160a01b038b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015612610573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263491906136db565b905061264182600161310a565b8114611e095760405162461bcd60e51b815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f74207375636365656044820152601960fa1b6064820152608401610c32565b7f00000000000000000000000042000000000000000000000000000000000000066001600160a01b03838116908216148015906126ef57506001600160a01b03831660009081526020819052604090205460ff16155b1561270d5760405163369370d960e01b815260040160405180910390fd5b6001600160e01b0319821660009081526001602052604090205460ff161561274857604051630d1a468960e01b815260040160405180910390fd5b806001600160a01b0316836001600160a01b03160361151c576001600160e01b03198216632e1a7d4d60e01b1480159061279357506001600160e01b03198216630d0e30db60e41b14155b1561151c57604051630d1a468960e01b815260040160405180910390fd5b60006127bc84611e15565b156127c857508061285c565b604051636eb1769f60e11b81523060048201526001600160a01b0384811660248301526000919086169063dd62ed3e90604401602060405180830381865afa158015612818573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061283c91906136db565b90508281101561285a5761285a6001600160a01b0386168585611d12565b505b9392505050565b6000808080805b868110156128a55785818151811061288457612884613228565b6020026020010151606001518261289b919061310a565b915060010161286a565b50868111156128f15760009150816128bd888361311d565b90506128c98782613206565b94506128d587866131ef565b6128df908261311d565b6128e9908661310a565b935050612939565b8681101561293957600191506000612909828961311d565b90506129158782613206565b945061292187866131ef565b61292b908261311d565b612935908661310a565b9350505b5093509350939050565b60008060008380602001905181019061295c91906139a6565b8151919350915060005b818110156129a457600084828151811061298257612982613228565b60200260200101519050602381111561299b5787818501525b50600101612966565b5060208201516129b48882612699565b60006129c18a8a8a6127b1565b9050886001600160a01b031681856040516129dc91906132d6565b60006040518083038185875af1925050503d8060008114612a19576040519150601f19603f3d011682016040523d82523d6000602084013e612a1e565b606091505b50909b9a5050505050505050505050565b60008082806020019051810190612a469190613a61565b80519091503060005b82811015612b50576000848281518110612a6b57612a6b613228565b6020026020010151905081600014612a915780602001519850612a8e8984611e4e565b97505b608081015181516023811115612aa75789818301525b60208201516040840151612abb8183612699565b6000612acc8e87606001518f6127b1565b9050816001600160a01b03168186604051612ae791906132d6565b60006040518083038185875af1925050503d8060008114612b24576040519150601f19603f3d011682016040523d82523d6000602084013e612b29565b606091505b5050809b50508a612b3f57505050505050612b50565b866001019650505050505050612a4f565b505050509392505050565b6060610dfd848460008585600080866001600160a01b03168587604051612b8291906132d6565b60006040518083038185875af1925050503d8060008114612bbf576040519150601f19603f3d011682016040523d82523d6000602084013e612bc4565b606091505b5091509150612bd587838387612be0565b979650505050505050565b60608315612c4f578251600003612c48576001600160a01b0385163b612c485760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c32565b5081610dfd565b610dfd8383815115612c645781518083602001fd5b8060405162461bcd60e51b8152600401610c329190613b8c565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081019190915290565b6040518060e0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b0381168114610c4457600080fd5b8035610de181612d42565b60008083601f840112612d7457600080fd5b5081356001600160401b03811115612d8b57600080fd5b602083019150836020828501011115612da357600080fd5b9250929050565b6000806000806000806000806000806000806101008d8f031215612dcd57600080fd5b8c359b50612ddd60208e01612d57565b9a50612deb60408e01612d57565b995060608d013598506001600160401b0360808e01351115612e0c57600080fd5b612e1c8e60808f01358f01612d62565b90985096506001600160401b0360a08e01351115612e3957600080fd5b612e498e60a08f01358f01612d62565b90965094506001600160401b0360c08e01351115612e6657600080fd5b612e768e60c08f01358f01612d62565b90945092506001600160401b0360e08e01351115612e9357600080fd5b612ea38e60e08f01358f01612d62565b81935080925050509295989b509295989b509295989b565b80356001600160e01b031981168114610de157600080fd5b8015158114610c4457600080fd5b60008060408385031215612ef457600080fd5b612efd83612ebb565b91506020830135612f0d81612ed3565b809150509250929050565b600060208284031215612f2a57600080fd5b61285c82612ebb565b60008060408385031215612f4657600080fd5b50508035926020909101359150565b600060208284031215612f6757600080fd5b813561285c81612d42565b60008060408385031215612f8557600080fd5b8235612f9081612d42565b946020939093013593505050565b60008060008060608587031215612fb457600080fd5b8435612fbf81612d42565b93506020850135925060408501356001600160401b03811115612fe157600080fd5b612fed87828801612d62565b95989497509550505050565b60008060006060848603121561300e57600080fd5b833561301981612d42565b95602085013595506040909401359392505050565b60008060006040848603121561304357600080fd5b83356001600160401b038082111561305a57600080fd5b818601915086601f83011261306e57600080fd5b81358181111561307d57600080fd5b8760208260051b850101111561309257600080fd5b602092830195509350508401356130a881612ed3565b809150509250925092565b6000806000606084860312156130c857600080fd5b83356130d381612d42565b925060208401356130e381612d42565b929592945050506040919091013590565b634e487b7160e01b600052601160045260246000fd5b808201808211156117df576117df6130f4565b818103818111156117df576117df6130f4565b60005b8381101561314b578181015183820152602001613133565b50506000910152565b6000815180845261316c816020860160208601613130565b601f01601f19169290920160200192915050565b60006101008a835289602084015260018060a01b03808a1660408501528089166060850152508660808401528560a08401528460c08401528060e08401526131ca81840185613154565b9b9a5050505050505050505050565b634e487b7160e01b600052602160045260246000fd5b80820281158282048414176117df576117df6130f4565b60008261322357634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b600060018201613250576132506130f4565b5060010190565b6001600160a01b0385168152602081018490526060604082018190528101829052818360808301376000818301608090810191909152601f909201601f191601019392505050565b6000806000606084860312156132b457600080fd5b83516132bf81612d42565b602085015160409095015190969495509392505050565b600082516132e8818460208701613130565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b038111828210171561332a5761332a6132f2565b60405290565b604051608081016001600160401b038111828210171561332a5761332a6132f2565b60405160c081016001600160401b038111828210171561332a5761332a6132f2565b604051601f8201601f191681016001600160401b038111828210171561339c5761339c6132f2565b604052919050565b60006001600160401b038211156133bd576133bd6132f2565b5060051b60200190565b60006001600160401b038211156133e0576133e06132f2565b50601f01601f191660200190565b600082601f8301126133ff57600080fd5b813561341261340d826133c7565b613374565b81815284602083860101111561342757600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561345757600080fd5b82356001600160401b038082111561346e57600080fd5b9084019060a0828703121561348257600080fd5b61348a613308565b823561349581612d42565b8152828401356134a481612d42565b8185015260408301356134b681612d42565b604082015260608381013590820152608080840135838111156134d857600080fd5b80850194505087601f8501126134ed57600080fd5b83356134fb61340d826133a4565b81815260059190911b8501860190868101908a83111561351a57600080fd5b8787015b838110156135cb578035878111156135365760008081fd5b880160a0818e03601f1901121561354d5760008081fd5b613555613308565b8a820135600681106135675760008081fd5b8152604082013561357781612d42565b818c0152606082013561358981612d42565b604082015281870135606082015260a0820135898111156135aa5760008081fd5b6135b88f8d838601016133ee565b828901525084525091880191880161351e565b50928401929092525090979650505050505050565b6000602082840312156135f257600080fd5b81356001600160401b038082111561360957600080fd5b908301906080828603121561361d57600080fd5b613625613330565b823581526020830135602082015260408301358281111561364557600080fd5b613651878286016133ee565b60408301525060608301358281111561366957600080fd5b613675878286016133ee565b60608301525095945050505050565b6001600160a01b0387811682528616602082015260c0604082018190526000906136b090830187613154565b85606084015284608084015282810360a08401526136ce8185613154565b9998505050505050505050565b6000602082840312156136ed57600080fd5b5051919050565b60006060828403121561370657600080fd5b604051606081018181106001600160401b0382111715613728576137286132f2565b60405282356002811061373a57600080fd5b8152602083013561374a81612d42565b60208201526040928301359281019290925250919050565b600060e0828403121561377457600080fd5b60405160e081018181106001600160401b0382111715613796576137966132f2565b60405282516137a481612d42565b815260208301516137b481612d42565b602082015260408301516137c781612d42565b80604083015250606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600080600080600080600080610100898b03121561381d57600080fd5b883561382881612d42565b9750602089013561383881612d42565b9650604089013561384881612d42565b9550606089013594506080890135935060a089013560ff8116811461386c57600080fd5b979a969950949793969295929450505060c08201359160e0013590565b60006020828403121561389b57600080fd5b81356001600160401b03808211156138b257600080fd5b9083019060c082860312156138c657600080fd5b6138ce613352565b82356138d981612d42565b815260208301356138e981612d42565b806020830152506040830135604082015260608301356060820152608083013561391281612d42565b608082015260a08301358281111561392957600080fd5b613935878286016133ee565b60a08301525095945050505050565b60006020828403121561395657600080fd5b815161285c81612ed3565b600082601f83011261397257600080fd5b815161398061340d826133c7565b81815284602083860101111561399557600080fd5b610dfd826020830160208701613130565b600080604083850312156139b957600080fd5b82516001600160401b03808211156139d057600080fd5b818501915085601f8301126139e457600080fd5b815160206139f461340d836133a4565b82815260059290921b84018101918181019089841115613a1357600080fd5b948201945b83861015613a3157855182529482019490820190613a18565b91880151919650909350505080821115613a4a57600080fd5b50613a5785828601613961565b9150509250929050565b60006020808385031215613a7457600080fd5b82516001600160401b0380821115613a8b57600080fd5b818501915085601f830112613a9f57600080fd5b8151613aad61340d826133a4565b81815260059190911b83018401908481019088831115613acc57600080fd5b8585015b83811015613b7f57805185811115613ae85760008081fd5b860160a0818c03601f1901811315613b005760008081fd5b613b08613308565b898301518152604080840151613b1d81612d42565b828c0152606084810151613b3081612d42565b8083850152506080915081850151613b4781612d42565b90830152918301519188831115613b5e5760008081fd5b613b6c8e8c85870101613961565b9082015285525050918601918601613ad0565b5098975050505050505050565b60208152600061285c602083018461315456fea2646970667358221220a53988482258f99f8f83f8981ce4ec11fd76326136d8e3af578843a522915d4464736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000317bec33af037b5fab2028f52d14658f6a5600000000000000000000000026f71baa9dcda856c5612949cb01596c856a2cbb0000000000000000000000004200000000000000000000000000000000000006
-----Decoded View---------------
Arg [0] : _bridgeAddress (address): 0x0000317Bec33Af037b5fAb2028f52d14658F6A56
Arg [1] : _owner (address): 0x26f71Baa9dcdA856C5612949cb01596c856A2cbb
Arg [2] : _wToken (address): 0x4200000000000000000000000000000000000006
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000317bec33af037b5fab2028f52d14658f6a56
Arg [1] : 00000000000000000000000026f71baa9dcda856c5612949cb01596c856a2cbb
Arg [2] : 0000000000000000000000004200000000000000000000000000000000000006
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.