Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
BeefyRevenueBridge
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
// Essential Interfaces
import {IERC20} from "@openzeppelin-4/contracts/token/ERC20/ERC20.sol";
import {SafeERC20} from "@openzeppelin-4/contracts/token/ERC20/utils/SafeERC20.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {Address} from "@openzeppelin-4/contracts/utils/Address.sol";
// Bridge Interfaces
import {IAxelar} from "../interfaces/bridge/IAxelar.sol";
import {ICircle} from "../interfaces/bridge/ICircle.sol";
import {IStargate} from "../interfaces/bridge/IStargate.sol";
import {ISynapse} from "../interfaces/bridge/ISynapse.sol";
import {IzkEVM} from "../interfaces/bridge/IzkEVM.sol";
import {IzkSync} from "../interfaces/bridge/IzkSync.sol";
import {IFraxFerry} from "../interfaces/bridge/IFraxFerry.sol";
//Swap Interfaces and Utils
import {IUniswapRouterETH} from "../interfaces/swap/IUniswapRouterETH.sol";
import {ISolidlyRouter} from "../interfaces/swap/ISolidlyRouter.sol";
import {IBalancerVault} from "../interfaces/swap/IBalancerVault.sol";
import {UniV3Actions} from "../utils/UniV3Actions.sol";
import {Path} from '../utils/Path.sol';
import {BeefyBalancerStructs} from "../utils/BeefyBalancerStructs.sol";
import {BalancerActionsLib} from "../utils/BalancerActionsLib.sol";
// Additional Interfaces Needed
import {IWrappedNative} from "../interfaces/IWrappedNative.sol";
import {Events} from "./Events.sol";
import {Errors} from "./Errors.sol";
// Beefy's revenue bridging system
contract BeefyRevenueBridge is
OwnableUpgradeable,
UUPSUpgradeable,
Events,
Errors
{
using SafeERC20 for IERC20;
using Address for address;
using Path for bytes;
IERC20 public stable;
IERC20 public native;
// Set our params
bytes32 public activeBridge;
bytes32 public activeSwap;
Cowllector public cowllector;
BridgeParams public bridgeParams;
SwapParams public swapParams;
DestinationAddress public destinationAddress;
uint256 public minBridgeAmount;
bool private init;
// Mapping our enums to function string
mapping(bytes32 => string) public bridgeToUse;
mapping(bytes32 => string) public swapToUse;
function initialize() external initializer {
__Ownable_init();
_initBridgeMapping();
_initSwapMapping();
funds = IBalancerVault.FundManagement(address(this), false, payable(address(this)), false);
swapKind = IBalancerVault.SwapKind.GIVEN_IN;
}
modifier onlyThis {
_onlyThis();
_;
}
function _onlyThis() private view {
if (msg.sender != address(this)) revert NotAuthorized();
}
function _initBridgeMapping() private {
bridgeToUse[keccak256(abi.encode("CIRCLE"))] = "bridgeCircle()";
bridgeToUse[keccak256(abi.encode("STARGATE"))] = "bridgeStargate()";
bridgeToUse[keccak256(abi.encode("AXELAR"))] = "bridgeAxelar()";
bridgeToUse[keccak256(abi.encode("SYNAPSE"))] = "bridgeSynapse()";
bridgeToUse[keccak256(abi.encode("zkEVM"))] = "bridgezkEVM()";
bridgeToUse[keccak256(abi.encode("zkSYNC"))] = "bridgezkSync()";
}
function _initSwapMapping() private {
swapToUse[keccak256(abi.encode("UNISWAP_V2"))] = "swapUniV2()";
swapToUse[keccak256(abi.encode("SOLIDLY"))] = "swapSolidly()";
swapToUse[keccak256(abi.encode("UNISWAP_V3"))] = "swapUniV3()";
swapToUse[keccak256(abi.encode("UNISWAP_V3_DEADLINE"))] = "swapUniV3Deadline()";
swapToUse[keccak256(abi.encode("ALGEBRA"))] = "swapAlgebra()";
swapToUse[keccak256(abi.encode("BALANCER"))] = "swapBalancer()";
}
function harvest() external {
// We just wrap the native we have at the start.
_wrapNative();
_sendCowllectorFunds();
if (_balanceOfNative() > 0) _bridge();
}
function _swap() private {
address(this).functionCall(
abi.encodeWithSignature(swapToUse[activeSwap])
);
}
function _bridge() private {
address(this).functionCall(
abi.encodeWithSignature(bridgeToUse[activeBridge])
);
}
/**@notice Bridge function called by this contract if it is the the activeBridge */
function bridgeCircle() external onlyThis {
uint32 destinationDomain = abi.decode(bridgeParams.params, (uint32));
_swap();
uint256 bal = _balanceOfStable();
if (bal > minBridgeAmount) {
ICircle(bridgeParams.bridge).depositForBurn(
bal,
destinationDomain,
bytes32(uint256(uint160(destinationAddress.destination))),
address(stable)
);
}
emit Bridged(address(stable), bal);
}
function bridgeStargate() external onlyThis {
(Stargate memory _params) = abi.decode(bridgeParams.params, (Stargate));
IStargate.lzTxObj memory _lzTxObj = IStargate.lzTxObj({
dstGasForCall: _params.gasLimit,
dstNativeAmount: 0,
dstNativeAddr: "0x"
});
uint256 gasAmount = _stargateGasCost(_params.dstChainId, destinationAddress.destinationBytes, _lzTxObj);
_getGas(gasAmount);
_swap();
uint256 bal = _balanceOfStable();
if (bal > minBridgeAmount) {
IStargate(bridgeParams.bridge).swap{ value: gasAmount }(
_params.dstChainId,
_params.srcPoolId,
_params.dstPoolId,
payable(address(this)),
bal,
0,
_lzTxObj,
destinationAddress.destinationBytes,
""
);
}
emit Bridged(address(stable), bal);
}
function _stargateGasCost(uint16 _dstChainId, bytes memory _dstAddress, IStargate.lzTxObj memory _lzTxObj) private view returns (uint256 gasAmount) {
(gasAmount,) = IStargate(bridgeParams.bridge).quoteLayerZeroFee(
_dstChainId,
1, // TYPE_SWAP_REMOTE
_dstAddress,
"",
_lzTxObj
);
}
function bridgeAxelar() external onlyThis {
Axelar memory params = abi.decode(bridgeParams.params, (Axelar));
_swap();
uint256 bal = _balanceOfStable();
if (bal > minBridgeAmount) {
IAxelar(bridgeParams.bridge).sendToken(
params.destinationChain,
destinationAddress.destinationString,
params.symbol,
bal
);
}
emit Bridged(address(stable), bal);
}
function bridgeSynapse() external onlyThis {
(Synapse memory params) = abi.decode(bridgeParams.params, (Synapse));
_swap();
uint256 bal = _balanceOfStable();
if (bal > minBridgeAmount) {
ISynapse(bridgeParams.bridge).swapAndRedeemAndSwap(
destinationAddress.destination,
params.chainId,
params.token,
params.tokenIndexFrom,
params.tokenIndexTo,
bal,
0,
block.timestamp,
params.dstIndexFrom,
params.dstIndexTo,
0,
block.timestamp + 1 hours
);
}
emit Bridged(address(stable), bal);
}
function bridgezkEVM() external onlyThis {
_swap();
uint256 bal = _balanceOfStable();
if (bal > minBridgeAmount) {
IzkEVM(bridgeParams.bridge).bridgeAsset(
0,
destinationAddress.destination,
bal,
address(stable),
true,
""
);
}
emit Bridged(address(stable), bal);
}
function bridgezkSync() external onlyThis {
_swap();
uint256 bal = _balanceOfStable();
if (bal > minBridgeAmount) {
IzkSync(bridgeParams.bridge).withdraw(
destinationAddress.destination,
address(stable),
bal
);
}
emit Bridged(address(stable), bal);
}
function bridgeFraxFerry() external onlyThis {
_swap();
uint256 bal = _balanceOfStable();
if (bal > minBridgeAmount) {
IFraxFerry(bridgeParams.bridge).embarkWithRecipient(
bal,
destinationAddress.destination
);
emit Bridged(address(stable), bal);
}
}
/**@notice Swap functions */
function swapUniV2() external onlyThis {
address[] memory route = abi.decode(swapParams.params, (address[]));
if (route[0] != address(native)) revert IncorrectRoute();
if (route[route.length - 1] != address(stable)) revert IncorrectRoute();
uint256 bal = _balanceOfNative();
IUniswapRouterETH(swapParams.router).swapExactTokensForTokens(
bal, 0, route, address(this), block.timestamp
);
}
function swapSolidly() external onlyThis {
ISolidlyRouter.Routes[] memory routes = abi.decode(swapParams.params, (ISolidlyRouter.Routes[]));
address[] memory route = _solidlyToRoute(routes);
if (route[0] != address(native)) revert IncorrectRoute();
if (route[route.length - 1] != address(stable)) revert IncorrectRoute();
uint256 bal = _balanceOfNative();
ISolidlyRouter(swapParams.router).swapExactTokensForTokens(bal, 0, routes, address(this), block.timestamp);
}
function swapUniV3() external onlyThis {
bytes memory path = abi.decode(swapParams.params, (bytes));
address[] memory route = _pathToRoute(path);
if (route[0] != address(native)) revert IncorrectRoute();
if (route[route.length - 1] != address(stable)) revert IncorrectRoute();
uint256 bal = _balanceOfNative();
UniV3Actions.swapV3(swapParams.router, path, bal);
}
function swapUniV3Deadline() external onlyThis {
bytes memory path = abi.decode(swapParams.params, (bytes));
address[] memory route = _pathToRoute(path);
if (route[0] != address(native)) revert IncorrectRoute();
if (route[route.length - 1] != address(stable)) revert IncorrectRoute();
uint256 bal = _balanceOfNative();
UniV3Actions.swapV3WithDeadline(swapParams.router, path, bal);
}
function swapAlgebra() external onlyThis {
address[] memory route = abi.decode(swapParams.params, (address[]));
if (route[0] != address(native)) revert IncorrectRoute();
if (route[route.length - 1] != address(stable)) revert IncorrectRoute();
bytes memory path = _routeToPath(route);
uint256 bal = _balanceOfNative();
UniV3Actions.swapV3WithDeadline(swapParams.router, path, bal);
}
function swapBalancer() external onlyThis {
(BeefyBalancerStructs.BatchSwapStruct[] memory route, address[] memory assets) = abi.decode(swapParams.params, (BeefyBalancerStructs.BatchSwapStruct[],address[]));
if (assets[0] != address(native)) revert IncorrectRoute();
if (assets[assets.length - 1] != address(stable)) revert IncorrectRoute();
uint256 bal = _balanceOfNative();
IBalancerVault.BatchSwapStep[] memory _swaps = BalancerActionsLib.buildSwapStructArray(route, bal);
BalancerActionsLib.balancerSwap(swapParams.router, swapKind, _swaps, assets, funds, int256(bal));
}
/**@notice View functions */
function _balanceOfStable() private view returns (uint256) {
return stable.balanceOf(address(this));
}
function _balanceOfNative() private view returns (uint256) {
return native.balanceOf(address(this));
}
function findHash(string calldata _variable) external pure returns (bytes32) {
return keccak256(abi.encode(_variable));
}
// Convert encoded path to token route
function _pathToRoute(bytes memory _path) private pure returns (address[] memory) {
uint256 numPools = _path.numPools();
address[] memory route = new address[](numPools + 1);
for (uint256 i; i < numPools; i++) {
(address tokenA, address tokenB,) = _path.decodeFirstPool();
route[i] = tokenA;
route[i + 1] = tokenB;
_path = _path.skipToken();
}
return route;
}
// Convert token route to encoded path
// uint24 type for fees so path is packed tightly
function _routeToPath(address[] memory _route) private pure returns (bytes memory path) {
path = abi.encodePacked(_route[0]);
for (uint256 i = 1; i < _route.length; i++) {
path = abi.encodePacked(path, _route[i]);
}
}
function _solidlyToRoute(ISolidlyRouter.Routes[] memory _route) private pure returns (address[] memory) {
address[] memory route = new address[](_route.length + 1);
route[0] = _route[0].from;
for (uint i; i < _route.length; ++i) {
route[i + 1] = _route[i].to;
}
return route;
}
function _sendCowllectorFunds() private {
if (cowllector.sendFunds) {
uint256 amountOnHand = address(cowllector.cowllector).balance + IERC20(native).balanceOf(cowllector.cowllector);
if (amountOnHand < cowllector.amountCowllectorNeeds) {
uint256 thisBal = _balanceOfNative();
uint256 amountToSend = cowllector.amountCowllectorNeeds - amountOnHand;
amountToSend = amountToSend > thisBal ? thisBal : amountToSend;
IERC20(native).safeTransfer(cowllector.cowllector, amountToSend);
emit CowllectorRefill(amountToSend);
}
}
}
function _getGas(uint256 _gasAmount) private {
uint256 nativeBal = _balanceOfNative();
if (nativeBal >= _gasAmount) {
try IWrappedNative(address(native)).withdraw(_gasAmount) {
// Do nothing. Chains like Metis will fail this.
} catch {
// Do nothing as well.
}
}
}
function _wrapNative() private {
uint256 bal = address(this).balance;
if (bal > 0) {
try IWrappedNative(address(native)).deposit{value: address(this).balance}() {
// Do nothing. Metis needs this try/catch.
} catch {
// Do nothing.
}
}
}
function _approveTokenIfNeeded(address token, address spender) private {
if (IERC20(token).allowance(address(this), spender) == 0) {
IERC20(token).safeApprove(spender, type(uint256).max);
}
}
function _removeApprovalIfNeeded(address token, address spender) private {
if (IERC20(token).allowance(address(this), spender) > 0) {
IERC20(token).safeApprove(spender, 0);
}
}
function _authorizeUpgrade(address) internal override onlyOwner {}
// Setters
function setActiveBridge(bytes32 _bridgeHash, BridgeParams calldata _params) external onlyOwner {
emit SetBridge(_bridgeHash, _params);
_removeApprovalIfNeeded(address(stable), bridgeParams.bridge);
activeBridge = _bridgeHash;
bridgeParams = _params;
_approveTokenIfNeeded(address(stable), _params.bridge);
}
function setActiveSwap(bytes32 _swapHash, SwapParams calldata _params) external onlyOwner {
emit SetSwap(_swapHash, _params);
_removeApprovalIfNeeded(address(native), swapParams.router);
activeSwap = _swapHash;
swapParams = _params;
_approveTokenIfNeeded(address(native), _params.router);
}
function setBridgeMap(bytes32 _bridgeHash, string calldata _function) external onlyOwner {
bridgeToUse[_bridgeHash] = _function;
}
function setCowllector(Cowllector calldata _cowllector) external onlyOwner {
cowllector = _cowllector;
}
function setDestinationAddress(DestinationAddress calldata _destination) external onlyOwner {
emit SetDestinationAddress(_destination);
destinationAddress = _destination;
}
function setMinBridgeAmount(uint256 _amount) external onlyOwner {
emit SetMinBridgeAmount(_amount);
minBridgeAmount = _amount;
}
function setStable(IERC20 _stable, IERC20 _native) external onlyOwner {
if (!init) {
stable = _stable;
native = _native;
init = true;
return;
}
emit SetStable(address(stable), address(_stable));
_removeApprovalIfNeeded(address(stable), bridgeParams.bridge);
stable = _stable;
_approveTokenIfNeeded(address(stable), bridgeParams.bridge);
}
function inCaseTokensGetStuck(address _token, bool _native) external onlyOwner {
if (_native) {
uint256 _nativeAmount = address(this).balance;
(bool sent,) = msg.sender.call{value: _nativeAmount}("");
if(!sent) revert FailedToSendEther();
} else {
uint256 _amount = IERC20(_token).balanceOf(address(this));
IERC20(_token).safeTransfer(msg.sender, _amount);
}
}
receive() external payable {
assert(msg.sender == address(native));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(address from, address to, uint256 amount) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
// Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
// decrementing then incrementing.
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
// Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
// Overflow not possible: amount <= accountBalance <= totalSupply.
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// 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.0) (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. Compatible with tokens that require the approval to be set to
* 0 before setting it to a non-zero value.
*/
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
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_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);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822ProxiableUpgradeable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*
* _Available since v4.8.3._
*/
interface IERC1967Upgradeable {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeaconUpgradeable {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeaconUpgradeable.sol";
import "../../interfaces/IERC1967Upgradeable.sol";
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/StorageSlotUpgradeable.sol";
import "../utils/Initializable.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*/
abstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {
function __ERC1967Upgrade_init() internal onlyInitializing {
}
function __ERC1967Upgrade_init_unchained() internal onlyInitializing {
}
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
AddressUpgradeable.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
import "./Initializable.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
function __UUPSUpgradeable_init() internal onlyInitializing {
}
function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
}
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
_;
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// 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 AddressUpgradeable {
/**
* @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;
import "../proxy/utils/Initializable.sol";
/**
* @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 ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlotUpgradeable {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
contract Errors {
/**@notice Errors */
error BridgeError();
error SwapError();
error NotAuthorized();
error IncorrectRoute();
error NotEnoughEth();
error FailedToSendEther();
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Structs} from "./Structs.sol";
contract Events is Structs {
/**@notice Revenue Bridge Events **/
event SetBridge(bytes32 bridge, BridgeParams params);
event SetSwap(bytes32 swap, SwapParams params);
event SetMinBridgeAmount(uint256 amount);
event SetDestinationAddress(DestinationAddress destinationAddress);
event SetStable(address oldStable, address newStable);
event Bridged(address indexed stable, uint256 stableBridged);
event CowllectorRefill(uint256 amount);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {IBalancerVault} from "../interfaces/swap/IBalancerVault.sol";
contract Structs {
// Will be unused if we dont swap with balancer
IBalancerVault.SwapKind public swapKind;
IBalancerVault.FundManagement public funds;
struct Cowllector {
bool sendFunds;
address cowllector;
uint256 amountCowllectorNeeds;
}
struct BridgeParams {
address bridge;
bytes params;
}
struct SwapParams {
address router;
bytes params;
}
struct DestinationAddress {
address destination;
bytes destinationBytes;
string destinationString;
}
struct Stargate {
uint16 dstChainId;
uint256 gasLimit;
uint256 srcPoolId;
uint256 dstPoolId;
}
struct Axelar {
string destinationChain;
string symbol;
}
struct Synapse {
uint256 chainId;
uint8 tokenIndexFrom;
uint8 tokenIndexTo;
address token;
uint8 dstIndexFrom;
uint8 dstIndexTo;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IAxelar {
function sendToken(
string memory destinationChain,
string memory destinationAddress,
string memory symbol,
uint256 amount
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ICircle {
function depositForBurn(
uint256 amount,
uint32 destinationDomain,
bytes32 mintRecipient,
address burnToken
) external returns (uint64 _nonce);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IFraxFerry {
function embarkWithRecipient(
uint256 amount,
address to
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IStargate {
struct lzTxObj {
uint256 dstGasForCall;
uint256 dstNativeAmount;
bytes dstNativeAddr;
}
function addLiquidity(
uint256 _poolId,
uint256 _amountLD,
address _to
) external;
function swap(
uint16 _dstChainId,
uint256 _srcPoolId,
uint256 _dstPoolId,
address payable _refundAddress,
uint256 _amountLD,
uint256 _minAmountLD,
lzTxObj memory _lzTxParams,
bytes calldata _to,
bytes calldata _payload
) external payable;
function redeemRemote(
uint16 _dstChainId,
uint256 _srcPoolId,
uint256 _dstPoolId,
address payable _refundAddress,
uint256 _amountLP,
uint256 _minAmountLD,
bytes calldata _to,
lzTxObj memory _lzTxParams
) external payable;
function instantRedeemLocal(
uint16 _srcPoolId,
uint256 _amountLP,
address _to
) external returns (uint256);
function redeemLocal(
uint16 _dstChainId,
uint256 _srcPoolId,
uint256 _dstPoolId,
address payable _refundAddress,
uint256 _amountLP,
bytes calldata _to,
lzTxObj memory _lzTxParams
) external payable;
function sendCredits(
uint16 _dstChainId,
uint256 _srcPoolId,
uint256 _dstPoolId,
address payable _refundAddress
) external payable;
function quoteLayerZeroFee(
uint16 _dstChainId,
uint8 _functionType,
bytes calldata _toAddress,
bytes calldata _transferAndCallPayload,
lzTxObj memory _lzTxParams
) external view returns (uint256, uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ISynapse {
function swapAndRedeemAndSwap(
address to,
uint256 chainId,
address token,
uint8 tokenIndexFrom,
uint8 tokenIndexTo,
uint256 dx,
uint256 minDy,
uint256 deadline,
uint8 swapIndexFrom,
uint8 swapIndexTo,
uint256 min,
uint256 swapTime
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IzkEVM {
function bridgeAsset(
uint32 dstChainId,
address receiver,
uint256 amount,
address token,
bool forceUpdate,
bytes memory permitData
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IzkSync {
function withdraw(
address to,
address token,
uint256 amount
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IWrappedNative {
function deposit() external payable;
function withdraw(uint256 wad) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IBalancerVault {
struct SingleSwap {
bytes32 poolId;
SwapKind kind;
address assetIn;
address assetOut;
uint256 amount;
bytes userData;
}
struct BatchSwapStep {
bytes32 poolId;
uint256 assetInIndex;
uint256 assetOutIndex;
uint256 amount;
bytes userData;
}
struct FundManagement {
address sender;
bool fromInternalBalance;
address payable recipient;
bool toInternalBalance;
}
struct JoinPoolRequest {
address[] assets;
uint256[] maxAmountsIn;
bytes userData;
bool fromInternalBalance;
}
enum SwapKind { GIVEN_IN, GIVEN_OUT }
function swap(
SingleSwap memory singleSwap,
FundManagement memory funds,
uint256 limit,
uint256 deadline
) external payable returns (uint256);
function batchSwap(
SwapKind kind,
BatchSwapStep[] memory swaps,
address[] memory assets,
FundManagement memory funds,
int256[] memory limits,
uint256 deadline
) external returns (int256[] memory assetDeltas);
function joinPool(
bytes32 poolId,
address sender,
address recipient,
JoinPoolRequest memory request
) external;
function getPoolTokens(bytes32 poolId)
external
view
returns (
address[] memory tokens,
uint256[] memory balances,
uint256 lastChangeBlock
);
function getPool(bytes32 poolId)
external
view
returns (address, uint8);
function flashLoan(
address recipient,
address[] memory tokens,
uint256[] memory amounts,
bytes memory userData
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IKyberElastic {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 minAmountOut;
uint160 limitSqrtP;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another token
/// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
/// @return amountOut The amount of the received token
function swapExactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 minAmountOut;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function swapExactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 maxAmountIn;
uint160 limitSqrtP;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another token
/// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
/// @return amountIn The amount of the input token
function swapExactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 maxAmountIn;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function swapExactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ISolidlyRouter {
// Routes
struct Routes {
address from;
address to;
bool stable;
}
struct Route {
address from;
address to;
bool stable;
address factory;
}
function addLiquidity(
address tokenA,
address tokenB,
bool stable,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
bool stable,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
bool stable,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
bool stable,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokensSimple(
uint amountIn,
uint amountOutMin,
address tokenFrom,
address tokenTo,
bool stable,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
Routes[] memory route,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
Route[] memory route,
address to,
uint deadline
) external returns (uint[] memory amounts);
function getAmountOut(uint amountIn, address tokenIn, address tokenOut) external view returns (uint amount, bool stable);
function getAmountsOut(uint amountIn, Routes[] memory routes) external view returns (uint[] memory amounts);
function getAmountsOut(uint amountIn, Route[] memory routes) external view returns (uint[] memory amounts);
function quoteAddLiquidity(
address tokenA,
address tokenB,
bool stable,
uint amountADesired,
uint amountBDesired
) external view returns (uint amountA, uint amountB, uint liquidity);
function quoteAddLiquidity(
address tokenA,
address tokenB,
bool stable,
address _factory,
uint amountADesired,
uint amountBDesired
) external view returns (uint amountA, uint amountB, uint liquidity);
function defaultFactory() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IUniswapRouterETH {
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IUniswapRouterV3 {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another token
/// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
/// @return amountOut The amount of the received token
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 amountIn;
uint256 amountOutMinimum;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another token
/// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
/// @return amountIn The amount of the input token
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IUniswapRouterV3WithDeadline {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another token
/// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
/// @return amountOut The amount of the received token
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another token
/// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
/// @return amountIn The amount of the input token
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interfaces/swap/IBalancerVault.sol";
import "@openzeppelin-4/contracts/token/ERC20/ERC20.sol";
import "./BeefyBalancerStructs.sol";
library BalancerActionsLib {
function balancerJoin(address _vault, bytes32 _poolId, address _tokenIn, uint256 _amountIn) internal {
(address[] memory lpTokens,,) = IBalancerVault(_vault).getPoolTokens(_poolId);
uint256[] memory amounts = new uint256[](lpTokens.length);
for (uint256 i = 0; i < amounts.length;) {
amounts[i] = lpTokens[i] == _tokenIn ? _amountIn : 0;
unchecked { ++i; }
}
bytes memory userData = abi.encode(1, amounts, 1);
IBalancerVault.JoinPoolRequest memory request = IBalancerVault.JoinPoolRequest(lpTokens, amounts, userData, false);
IBalancerVault(_vault).joinPool(_poolId, address(this), address(this), request);
}
function buildSwapStructArray(BeefyBalancerStructs.BatchSwapStruct[] memory _route, uint256 _amountIn) internal pure returns (IBalancerVault.BatchSwapStep[] memory) {
IBalancerVault.BatchSwapStep[] memory swaps = new IBalancerVault.BatchSwapStep[](_route.length);
for (uint i; i < _route.length;) {
if (i == 0) {
swaps[0] =
IBalancerVault.BatchSwapStep({
poolId: _route[0].poolId,
assetInIndex: _route[0].assetInIndex,
assetOutIndex: _route[0].assetOutIndex,
amount: _amountIn,
userData: ""
});
} else {
swaps[i] =
IBalancerVault.BatchSwapStep({
poolId: _route[i].poolId,
assetInIndex: _route[i].assetInIndex,
assetOutIndex: _route[i].assetOutIndex,
amount: 0,
userData: ""
});
}
unchecked {
++i;
}
}
return swaps;
}
function balancerSwap(address _vault, IBalancerVault.SwapKind _swapKind, IBalancerVault.BatchSwapStep[] memory _swaps, address[] memory _route, IBalancerVault.FundManagement memory _funds, int256 _amountIn) internal returns (int256[] memory) {
int256[] memory limits = new int256[](_route.length);
for (uint i; i < _route.length;) {
if (i == 0) {
limits[0] = _amountIn;
} else if (i == _route.length - 1) {
limits[i] = -1;
}
unchecked { ++i; }
}
return IBalancerVault(_vault).batchSwap(_swapKind, _swaps, _route, _funds, limits, block.timestamp);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library BeefyBalancerStructs {
enum RouterType {
BALANCER,
UNISWAP_V2,
UNISWAP_V3
}
struct BatchSwapStruct {
bytes32 poolId;
uint256 assetInIndex;
uint256 assetOutIndex;
}
struct Reward {
RouterType routerType;
address router;
mapping(uint => BatchSwapStruct) swapInfo;
address[] assets;
bytes routeToNative; // backup route in case there is no Balancer liquidity for reward
uint minAmount; // minimum amount to be swapped to native
}
struct Input {
address input;
bool isComposable;
bool isBeets;
}
}// SPDX-License-Identifier: BUSL-1.1 /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.5.0 <0.9.0; library BytesLib { function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, 'slice_overflow'); require(_start + _length >= _start, 'slice_overflow'); require(_bytes.length >= _start + _length, 'slice_outOfBounds'); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_start + 20 >= _start, 'toAddress_overflow'); require(_bytes.length >= _start + 20, 'toAddress_outOfBounds'); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) { require(_start + 3 >= _start, 'toUint24_overflow'); require(_bytes.length >= _start + 3, 'toUint24_outOfBounds'); uint24 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x3), _start)) } return tempUint; } }
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import './BytesLib.sol';
/// @title Functions for manipulating path data for multihop swaps
library Path {
using BytesLib for bytes;
/// @dev The length of the bytes encoded address
uint256 private constant ADDR_SIZE = 20;
/// @dev The length of the bytes encoded fee
uint256 private constant FEE_SIZE = 3;
/// @dev The offset of a single token address and pool fee
uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;
/// @dev The offset of an encoded pool key
uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;
/// @dev The minimum length of an encoding that contains 2 or more pools
uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;
/// @notice Returns true iff the path contains two or more pools
/// @param path The encoded swap path
/// @return True if path contains two or more pools, otherwise false
function hasMultiplePools(bytes memory path) internal pure returns (bool) {
return path.length >= MULTIPLE_POOLS_MIN_LENGTH;
}
/// @notice Returns the number of pools in the path
/// @param path The encoded swap path
/// @return The number of pools in the path
function numPools(bytes memory path) internal pure returns (uint256) {
// Ignore the first token address. From then on every fee and token offset indicates a pool.
return ((path.length - ADDR_SIZE) / NEXT_OFFSET);
}
/// @notice Decodes the first pool in path
/// @param path The bytes encoded swap path
/// @return tokenA The first token of the given pool
/// @return tokenB The second token of the given pool
/// @return fee The fee level of the pool
function decodeFirstPool(bytes memory path)
internal
pure
returns (
address tokenA,
address tokenB,
uint24 fee
)
{
tokenA = path.toAddress(0);
fee = path.toUint24(ADDR_SIZE);
tokenB = path.toAddress(NEXT_OFFSET);
}
/// @notice Gets the segment corresponding to the first pool in the path
/// @param path The bytes encoded swap path
/// @return The segment containing all data necessary to target the first pool in the path
function getFirstPool(bytes memory path) internal pure returns (bytes memory) {
return path.slice(0, POP_OFFSET);
}
/// @notice Skips a token + fee element from the buffer and returns the remainder
/// @param path The swap path
/// @return The remaining token + fee elements in the path
function skipToken(bytes memory path) internal pure returns (bytes memory) {
return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interfaces/swap/IKyberElastic.sol";
import "../interfaces/swap/IUniswapRouterV3.sol";
import "../interfaces/swap/IUniswapRouterWithDeadline.sol";
library UniV3Actions {
// kyber V3 swap
function kyberSwap(address _router, bytes memory _path, uint256 _amount) internal returns (uint256 amountOut) {
IKyberElastic.ExactInputParams memory swapParams = IKyberElastic.ExactInputParams({
path: _path,
recipient: address(this),
deadline: block.timestamp,
amountIn: _amount,
minAmountOut: 0
});
return IKyberElastic(_router).swapExactInput(swapParams);
}
// Uniswap V3 swap
function swapV3(address _router, bytes memory _path, uint256 _amount) internal returns (uint256 amountOut) {
IUniswapRouterV3.ExactInputParams memory swapParams = IUniswapRouterV3.ExactInputParams({
path: _path,
recipient: address(this),
amountIn: _amount,
amountOutMinimum: 0
});
return IUniswapRouterV3(_router).exactInput(swapParams);
}
// Uniswap V3 swap with deadline
function swapV3WithDeadline(address _router, bytes memory _path, uint256 _amount) internal returns (uint256 amountOut) {
IUniswapRouterV3WithDeadline.ExactInputParams memory swapParams = IUniswapRouterV3WithDeadline.ExactInputParams({
path: _path,
recipient: address(this),
deadline: block.timestamp,
amountIn: _amount,
amountOutMinimum: 0
});
return IUniswapRouterV3WithDeadline(_router).exactInput(swapParams);
}
// Uniswap V3 swap with deadline
function swapV3WithDeadline(address _router, bytes memory _path, uint256 _amount, address _to) internal returns (uint256 amountOut) {
IUniswapRouterV3WithDeadline.ExactInputParams memory swapParams = IUniswapRouterV3WithDeadline.ExactInputParams({
path: _path,
recipient: _to,
deadline: block.timestamp,
amountIn: _amount,
amountOutMinimum: 0
});
return IUniswapRouterV3WithDeadline(_router).exactInput(swapParams);
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"lib/forge-std:ds-test/=lib/forge-std/lib/ds-test/src/"
],
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"BridgeError","type":"error"},{"inputs":[],"name":"FailedToSendEther","type":"error"},{"inputs":[],"name":"IncorrectRoute","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NotEnoughEth","type":"error"},{"inputs":[],"name":"SwapError","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stable","type":"address"},{"indexed":false,"internalType":"uint256","name":"stableBridged","type":"uint256"}],"name":"Bridged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CowllectorRefill","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"bridge","type":"bytes32"},{"components":[{"internalType":"address","name":"bridge","type":"address"},{"internalType":"bytes","name":"params","type":"bytes"}],"indexed":false,"internalType":"struct Structs.BridgeParams","name":"params","type":"tuple"}],"name":"SetBridge","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"bytes","name":"destinationBytes","type":"bytes"},{"internalType":"string","name":"destinationString","type":"string"}],"indexed":false,"internalType":"struct Structs.DestinationAddress","name":"destinationAddress","type":"tuple"}],"name":"SetDestinationAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetMinBridgeAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldStable","type":"address"},{"indexed":false,"internalType":"address","name":"newStable","type":"address"}],"name":"SetStable","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"swap","type":"bytes32"},{"components":[{"internalType":"address","name":"router","type":"address"},{"internalType":"bytes","name":"params","type":"bytes"}],"indexed":false,"internalType":"struct Structs.SwapParams","name":"params","type":"tuple"}],"name":"SetSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"activeBridge","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeSwap","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeAxelar","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bridgeCircle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bridgeFraxFerry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bridgeParams","outputs":[{"internalType":"address","name":"bridge","type":"address"},{"internalType":"bytes","name":"params","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeStargate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bridgeSynapse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeToUse","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgezkEVM","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bridgezkSync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cowllector","outputs":[{"internalType":"bool","name":"sendFunds","type":"bool"},{"internalType":"address","name":"cowllector","type":"address"},{"internalType":"uint256","name":"amountCowllectorNeeds","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"destinationAddress","outputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"bytes","name":"destinationBytes","type":"bytes"},{"internalType":"string","name":"destinationString","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_variable","type":"string"}],"name":"findHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"funds","outputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"bool","name":"fromInternalBalance","type":"bool"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"bool","name":"toInternalBalance","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"bool","name":"_native","type":"bool"}],"name":"inCaseTokensGetStuck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minBridgeAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"native","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_bridgeHash","type":"bytes32"},{"components":[{"internalType":"address","name":"bridge","type":"address"},{"internalType":"bytes","name":"params","type":"bytes"}],"internalType":"struct Structs.BridgeParams","name":"_params","type":"tuple"}],"name":"setActiveBridge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_swapHash","type":"bytes32"},{"components":[{"internalType":"address","name":"router","type":"address"},{"internalType":"bytes","name":"params","type":"bytes"}],"internalType":"struct Structs.SwapParams","name":"_params","type":"tuple"}],"name":"setActiveSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_bridgeHash","type":"bytes32"},{"internalType":"string","name":"_function","type":"string"}],"name":"setBridgeMap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"sendFunds","type":"bool"},{"internalType":"address","name":"cowllector","type":"address"},{"internalType":"uint256","name":"amountCowllectorNeeds","type":"uint256"}],"internalType":"struct Structs.Cowllector","name":"_cowllector","type":"tuple"}],"name":"setCowllector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"bytes","name":"destinationBytes","type":"bytes"},{"internalType":"string","name":"destinationString","type":"string"}],"internalType":"struct Structs.DestinationAddress","name":"_destination","type":"tuple"}],"name":"setDestinationAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setMinBridgeAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_stable","type":"address"},{"internalType":"contract IERC20","name":"_native","type":"address"}],"name":"setStable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stable","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapAlgebra","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapBalancer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapKind","outputs":[{"internalType":"enum IBalancerVault.SwapKind","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapParams","outputs":[{"internalType":"address","name":"router","type":"address"},{"internalType":"bytes","name":"params","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapSolidly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"swapToUse","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapUniV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapUniV3","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapUniV3Deadline","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60a06040523060805234801561001457600080fd5b50608051615bf36200004d60003960008181610e1601528181610e5f01528181610f2801528181610f6801526112810152615bf36000f3fe6080604052600436106102605760003560e01c8063748b3c0511610144578063c4b00c4f116100b6578063d7d66e711161007a578063d7d66e7114610714578063ee63c1e514610734578063f2fde38b14610749578063f3f1a71a14610769578063fe8d1ab014610789578063ff33d21f1461079e57600080fd5b8063c4b00c4f14610635578063c89f2ce414610655578063ca325469146106c6578063cc5ea4ef146106ea578063d49b6408146106ff57600080fd5b80639c345b9f116101085780639c345b9f1461056b578063a5131aaa14610581578063b54653fb14610596578063b9f39147146105ea578063bac86af5146105ff578063c3c224751461061f57600080fd5b8063748b3c05146104ea5780638129fc1c146104ff578063873d80ec146105145780638da5cb5b14610537578063943f8e961461055557600080fd5b80635066a747116101dd578063671f6a26116101a1578063671f6a26146104375780636ae407111461045e5780636d0a68911461047357806370c75107146104a0578063715018a6146104c057806373f1df33146104d557600080fd5b80635066a747146103aa5780635109d8b6146103ca57806352d1902d146103df578063530728d51461040257806364e510a11461041757600080fd5b80631610ee40116102245780631610ee401461032257806322be3de1146103425780633659cfe6146103625780634641257d146103825780634f1ef2861461039757600080fd5b80630278fb8a14610286578063057d1ae31461029b5780630d1f7833146102b057806311b0b42d146102c5578063154085921461030257600080fd5b366102815760cd546001600160a01b0316331461027f5761027f6143e0565b005b600080fd5b34801561029257600080fd5b5061027f6107be565b3480156102a757600080fd5b5061027f610950565b3480156102bc57600080fd5b5061027f610bb5565b3480156102d157600080fd5b5060cd546102e5906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561030e57600080fd5b5061027f61031d36600461443e565b610d9a565b34801561032e57600080fd5b5061027f61033d36600461449b565b610dbb565b34801561034e57600080fd5b5060cc546102e5906001600160a01b031681565b34801561036e57600080fd5b5061027f61037d3660046144e4565b610e0c565b34801561038e57600080fd5b5061027f610ef4565b61027f6103a5366004614596565b610f1e565b3480156103b657600080fd5b5061027f6103c536600461463a565b610fee565b3480156103d657600080fd5b5061027f611081565b3480156103eb57600080fd5b506103f4611274565b6040519081526020016102f9565b34801561040e57600080fd5b5061027f611327565b34801561042357600080fd5b5061027f61043236600461463a565b611414565b34801561044357600080fd5b5060c9546104519060ff1681565b6040516102f991906146a2565b34801561046a57600080fd5b5061027f6114a2565b34801561047f57600080fd5b5061049361048e3660046146b0565b611688565b6040516102f99190614719565b3480156104ac57600080fd5b506103f46104bb36600461472c565b611722565b3480156104cc57600080fd5b5061027f611756565b3480156104e157600080fd5b5061027f611768565b3480156104f657600080fd5b5061027f6117c9565b34801561050b57600080fd5b5061027f611939565b34801561052057600080fd5b50610529611ab1565b6040516102f992919061476d565b34801561054357600080fd5b506033546001600160a01b03166102e5565b34801561056157600080fd5b506103f460cf5481565b34801561057757600080fd5b506103f460ce5481565b34801561058d57600080fd5b5061027f611b52565b3480156105a257600080fd5b5060d05460d1546105c59160ff8116916101009091046001600160a01b03169083565b6040805193151584526001600160a01b039092166020840152908201526060016102f9565b3480156105f657600080fd5b5061027f611bbe565b34801561060b57600080fd5b5061027f61061a36600461479f565b611d4a565b34801561062b57600080fd5b506103f460d95481565b34801561064157600080fd5b5061027f6106503660046147d8565b611e44565b34801561066157600080fd5b5060ca5460cb54610691916001600160a01b038082169260ff600160a01b93849004811693928216929091041684565b6040516102f994939291906001600160a01b039485168152921515602084015292166040820152901515606082015260800190565b3480156106d257600080fd5b506106db611e59565b6040516102f9939291906147f4565b3480156106f657600080fd5b5061027f611f88565b34801561070b57600080fd5b50610529612123565b34801561072057600080fd5b5061027f61072f3660046146b0565b612141565b34801561074057600080fd5b5061027f612181565b34801561075557600080fd5b5061027f6107643660046144e4565b61230d565b34801561077557600080fd5b506104936107843660046146b0565b612383565b34801561079557600080fd5b5061027f61239c565b3480156107aa57600080fd5b5061027f6107b936600461482a565b612525565b6107c6612601565b600060d460010180546107d890614858565b80601f016020809104026020016040519081016040528092919081815260200182805461080490614858565b80156108515780601f1061082657610100808354040283529160200191610851565b820191906000526020600020905b81548152906001019060200180831161083457829003601f168201915b5050505050806020019051810190610869919061491e565b60cd5481519192506001600160a01b031690829060009061088c5761088c614952565b60200260200101516001600160a01b0316146108bb576040516376c252e160e11b815260040160405180910390fd5b60cc5481516001600160a01b039091169082906108da9060019061497e565b815181106108ea576108ea614952565b60200260200101516001600160a01b031614610919576040516376c252e160e11b815260040160405180910390fd5b600061092482612621565b905060006109306126da565b60d45490915061094a906001600160a01b0316838361274d565b50505050565b610958612601565b600060d2600101805461096a90614858565b80601f016020809104026020016040519081016040528092919081815260200182805461099690614858565b80156109e35780601f106109b8576101008083540402835291602001916109e3565b820191906000526020600020905b8154815290600101906020018083116109c657829003601f168201915b50505050508060200190518101906109fb9190614991565b905060006040518060600160405280836020015181526020016000815260200160405180604001604052806002815260200161060f60f31b81525081525090506000610ad9836000015160d66001018054610a5590614858565b80601f0160208091040260200160405190810160405280929190818152602001828054610a8190614858565b8015610ace5780601f10610aa357610100808354040283529160200191610ace565b820191906000526020600020905b815481529060010190602001808311610ab157829003601f168201915b5050505050846127ee565b9050610ae48161286f565b610aec6128e2565b6000610af6612943565b905060d954811115610b7f5760d2548451604080870151606088015191516327efc43f60e21b81526001600160a01b0390941693639fbf10fc938793610b4c939192309089906000908d9060d790600401614aac565b6000604051808303818588803b158015610b6557600080fd5b505af1158015610b79573d6000803e3d6000fd5b50505050505b60cc546040518281526001600160a01b0390911690600080516020615b578339815191529060200160405180910390a250505050565b610bbd612601565b60008060d46001018054610bd090614858565b80601f0160208091040260200160405190810160405280929190818152602001828054610bfc90614858565b8015610c495780601f10610c1e57610100808354040283529160200191610c49565b820191906000526020600020905b815481529060010190602001808311610c2c57829003601f168201915b5050505050806020019051810190610c619190614b26565b60cd5481519294509092506001600160a01b0316908290600090610c8757610c87614952565b60200260200101516001600160a01b031614610cb6576040516376c252e160e11b815260040160405180910390fd5b60cc5481516001600160a01b03909116908290610cd59060019061497e565b81518110610ce557610ce5614952565b60200260200101516001600160a01b031614610d14576040516376c252e160e11b815260040160405180910390fd5b6000610d1e6126da565b90506000610d2c8483612974565b60d45460c9546040805160808101825260ca546001600160a01b03808216835260ff600160a01b9283900481161515602085015260cb548083169585019590955291909304811615156060830152949550610d939491909316929116908490879087612b7d565b5050505050565b610da2612cc7565b600083815260db6020526040902061094a828483614c67565b610dc3612cc7565b7f518f47fcfba5d9b707c3387a7fa4301136192d8091a43ea13ae8db7275ab5d3a81604051610df29190614d8e565b60405180910390a18060d6610e078282614e5f565b505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610e5d5760405162461bcd60e51b8152600401610e5490614f58565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610ea6600080516020615b77833981519152546001600160a01b031690565b6001600160a01b031614610ecc5760405162461bcd60e51b8152600401610e5490614fa4565b610ed581612d21565b60408051600080825260208201909252610ef191839190612d29565b50565b610efc612e94565b610f04612f05565b6000610f0e6126da565b1115610f1c57610f1c61303e565b565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610f665760405162461bcd60e51b8152600401610e5490614f58565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610faf600080516020615b77833981519152546001600160a01b031690565b6001600160a01b031614610fd55760405162461bcd60e51b8152600401610e5490614fa4565b610fde82612d21565b610fea82826001612d29565b5050565b610ff6612cc7565b7f25f7dd6fc737add5174192a11292dfd270c1397f9c4f641fb6336a208b5efbed8282604051611027929190615033565b60405180910390a160cd5460d45461104b916001600160a01b03908116911661306e565b60cf8290558060d461105d8282615128565b505060cd54610fea906001600160a01b031661107c60208401846144e4565b6130fd565b611089612601565b600060d4600101805461109b90614858565b80601f01602080910402602001604051908101604052809291908181526020018280546110c790614858565b80156111145780601f106110e957610100808354040283529160200191611114565b820191906000526020600020905b8154815290600101906020018083116110f757829003601f168201915b505050505080602001905181019061112c9190615132565b905060006111398261318a565b60cd5481519192506001600160a01b031690829060009061115c5761115c614952565b60200260200101516001600160a01b03161461118b576040516376c252e160e11b815260040160405180910390fd5b60cc5481516001600160a01b039091169082906111aa9060019061497e565b815181106111ba576111ba614952565b60200260200101516001600160a01b0316146111e9576040516376c252e160e11b815260040160405180910390fd5b60006111f36126da565b60d454604051631e82ecdb60e31b81529192506001600160a01b03169063f41766d89061122d90849060009088903090429060040161520a565b6000604051808303816000875af115801561124c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261094a919081019061529f565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146113145760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610e54565b50600080516020615b7783398151915290565b61132f612601565b6113376128e2565b6000611341612943565b905060d9548111156113e15760d25460d65460cc5460405163cd58657960e01b81526000600482018190526001600160a01b0393841660248301526044820186905291831660648201526001608482015260c060a482015260c481019190915291169063cd5865799060e4015b600060405180830381600087803b1580156113c857600080fd5b505af11580156113dc573d6000803e3d6000fd5b505050505b60cc546040518281526001600160a01b0390911690600080516020615b578339815191529060200160405180910390a250565b61141c612cc7565b7f5e355369ceaccb04ff615500f99b96912ce9f237ed35ae521487c19064e2318d828260405161144d929190615033565b60405180910390a160cc5460d254611471916001600160a01b03908116911661306e565b60ce8290558060d26114838282615128565b505060cc54610fea906001600160a01b031661107c60208401846144e4565b6114aa612601565b600060d460010180546114bc90614858565b80601f01602080910402602001604051908101604052809291908181526020018280546114e890614858565b80156115355780601f1061150a57610100808354040283529160200191611535565b820191906000526020600020905b81548152906001019060200180831161151857829003601f168201915b505050505080602001905181019061154d919061491e565b60cd5481519192506001600160a01b031690829060009061157057611570614952565b60200260200101516001600160a01b03161461159f576040516376c252e160e11b815260040160405180910390fd5b60cc5481516001600160a01b039091169082906115be9060019061497e565b815181106115ce576115ce614952565b60200260200101516001600160a01b0316146115fd576040516376c252e160e11b815260040160405180910390fd5b60006116076126da565b60d4546040516338ed173960e01b81529192506001600160a01b0316906338ed173990611641908490600090879030904290600401615373565b6000604051808303816000875af1158015611660573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e07919081019061529f565b60db60205260009081526040902080546116a190614858565b80601f01602080910402602001604051908101604052809291908181526020018280546116cd90614858565b801561171a5780601f106116ef5761010080835404028352916020019161171a565b820191906000526020600020905b8154815290600101906020018083116116fd57829003601f168201915b505050505081565b600082826040516020016117379291906153af565b6040516020818303038152906040528051906020012090505b92915050565b61175e612cc7565b610f1c60006132a8565b611770612601565b6117786128e2565b6000611782612943565b905060d954811115610ef15760d25460d6546040516302e108e960e11b8152600481018490526001600160a01b0391821660248201529116906305c211d2906044016113ae565b6117d1612601565b600060d260010180546117e390614858565b80601f016020809104026020016040519081016040528092919081815260200182805461180f90614858565b801561185c5780601f106118315761010080835404028352916020019161185c565b820191906000526020600020905b81548152906001019060200180831161183f57829003601f168201915b50505050508060200190518101906118749190615413565b905061187e6128e2565b6000611888612943565b905060d9548111156119045760d254825160208401516040516326ef699d60e01b81526001600160a01b03909316926326ef699d926118d192909160d8919087906004016154b9565b600060405180830381600087803b1580156118eb57600080fd5b505af11580156118ff573d6000803e3d6000fd5b505050505b60cc546040518281526001600160a01b0390911690600080516020615b57833981519152906020015b60405180910390a25050565b600054610100900460ff16158080156119595750600054600160ff909116105b806119735750303b158015611973575060005460ff166001145b6119d65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610e54565b6000805460ff1916600117905580156119f9576000805461ff0019166101001790555b611a016132fa565b611a09613329565b611a11613650565b604080516080810182523080825260006020830181905292820181905260609091019190915260ca805460ff60a01b199092166001600160a81b0319928316811790915560cb805490921617905560c9805460ff191690558015610ef1576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b60d4805460d580546001600160a01b039092169291611acf90614858565b80601f0160208091040260200160405190810160405280929190818152602001828054611afb90614858565b8015611b485780601f10611b1d57610100808354040283529160200191611b48565b820191906000526020600020905b815481529060010190602001808311611b2b57829003601f168201915b5050505050905082565b611b5a612601565b611b626128e2565b6000611b6c612943565b905060d9548111156113e15760d25460d65460cc54604051636ce5768960e11b81526001600160a01b03928316600482015290821660248201526044810184905291169063d9caed12906064016113ae565b611bc6612601565b600060d46001018054611bd890614858565b80601f0160208091040260200160405190810160405280929190818152602001828054611c0490614858565b8015611c515780601f10611c2657610100808354040283529160200191611c51565b820191906000526020600020905b815481529060010190602001808311611c3457829003601f168201915b5050505050806020019051810190611c699190615504565b90506000611c7682613959565b60cd5481519192506001600160a01b0316908290600090611c9957611c99614952565b60200260200101516001600160a01b031614611cc8576040516376c252e160e11b815260040160405180910390fd5b60cc5481516001600160a01b03909116908290611ce79060019061497e565b81518110611cf757611cf7614952565b60200260200101516001600160a01b031614611d26576040516376c252e160e11b815260040160405180910390fd5b6000611d306126da565b60d45490915061094a906001600160a01b0316848361274d565b611d52612cc7565b8015611dc3576040514790600090339083908381818185875af1925050503d8060008114611d9c576040519150601f19603f3d011682016040523d82523d6000602084013e611da1565b606091505b505090508061094a57604051630dcf35db60e41b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611e0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2e919061554c565b9050610e076001600160a01b0384163383613a5c565b611e4c612cc7565b8060d0610e078282615565565b60d6805460d780546001600160a01b039092169291611e7790614858565b80601f0160208091040260200160405190810160405280929190818152602001828054611ea390614858565b8015611ef05780601f10611ec557610100808354040283529160200191611ef0565b820191906000526020600020905b815481529060010190602001808311611ed357829003601f168201915b505050505090806002018054611f0590614858565b80601f0160208091040260200160405190810160405280929190818152602001828054611f3190614858565b8015611f7e5780601f10611f5357610100808354040283529160200191611f7e565b820191906000526020600020905b815481529060010190602001808311611f6157829003601f168201915b5050505050905083565b611f90612601565b600060d26001018054611fa290614858565b80601f0160208091040260200160405190810160405280929190818152602001828054611fce90614858565b801561201b5780601f10611ff05761010080835404028352916020019161201b565b820191906000526020600020905b815481529060010190602001808311611ffe57829003601f168201915b505050505080602001905181019061203391906155d9565b905061203d6128e2565b6000612047612943565b905060d9548111156119045760d25460d6548351606085015160208601516040870151608088015160a08901516001600160a01b0397881697639f3307279716959493929189916000914291836120a084610e10615672565b6040516001600160e01b031960e08f901b1681526001600160a01b039c8d166004820152602481019b909b529a90981660448a015260ff96871660648a0152948616608489015260a488019390935260c487019190915260e4860152821661010485015216610124830152610144820152610164810191909152610184016118d1565b60d2805460d380546001600160a01b039092169291611acf90614858565b612149612cc7565b6040518181527ff4f47d85dc8207b9d9c6dfd289d4f5008b33df899eda3da90658d75c351e54759060200160405180910390a160d955565b612189612601565b600060d4600101805461219b90614858565b80601f01602080910402602001604051908101604052809291908181526020018280546121c790614858565b80156122145780601f106121e957610100808354040283529160200191612214565b820191906000526020600020905b8154815290600101906020018083116121f757829003601f168201915b505050505080602001905181019061222c9190615504565b9050600061223982613959565b60cd5481519192506001600160a01b031690829060009061225c5761225c614952565b60200260200101516001600160a01b03161461228b576040516376c252e160e11b815260040160405180910390fd5b60cc5481516001600160a01b039091169082906122aa9060019061497e565b815181106122ba576122ba614952565b60200260200101516001600160a01b0316146122e9576040516376c252e160e11b815260040160405180910390fd5b60006122f36126da565b60d45490915061094a906001600160a01b03168483613abf565b612315612cc7565b6001600160a01b03811661237a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e54565b610ef1816132a8565b60dc60205260009081526040902080546116a190614858565b6123a4612601565b600060d260010180546123b690614858565b80601f01602080910402602001604051908101604052809291908181526020018280546123e290614858565b801561242f5780601f106124045761010080835404028352916020019161242f565b820191906000526020600020905b81548152906001019060200180831161241257829003601f168201915b50505050508060200190518101906124479190615685565b90506124516128e2565b600061245b612943565b905060d9548111156119045760d25460d65460cc546040516337e9a82760e11b81526004810185905263ffffffff861660248201526001600160a01b0392831660448201529082166064820152911690636fd3504e906084016020604051808303816000875af11580156124d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f791906156ab565b5060cc546040518281526001600160a01b0390911690600080516020615b578339815191529060200161192d565b61252d612cc7565b60da5460ff166125725760cc80546001600160a01b039384166001600160a01b03199182161790915560cd805492909316911617905560da805460ff19166001179055565b60cc54604080516001600160a01b03928316815291841660208301527f4239efeca0761c0d170bd15a6e85542dbe0376ba0f5f1551b39c6045866ff735910160405180910390a160cc5460d2546125d5916001600160a01b03908116911661306e565b60cc80546001600160a01b0319166001600160a01b0384811691821790925560d254610fea92166130fd565b333014610f1c5760405163ea8e4eb560e01b815260040160405180910390fd5b60608160008151811061263657612636614952565b6020026020010151604051602001612666919060609190911b6bffffffffffffffffffffffff1916815260140190565b60408051601f19818403018152919052905060015b82518110156126d4578183828151811061269757612697614952565b60200260200101516040516020016126b09291906156d4565b604051602081830303815290604052915080806126cc9061570b565b91505061267b565b50919050565b60cd546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a08231906024015b602060405180830381865afa158015612724573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612748919061554c565b905090565b6040805160a081018252838152306020820152428183015260608101839052600060808201819052915163c04b8d5960e01b81526001600160a01b0386169063c04b8d59906127a0908490600401615724565b6020604051808303816000875af11580156127bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127e3919061554c565b9150505b9392505050565b60d254604051630a51236960e01b81526000916001600160a01b031690630a512369906128269087906001908890889060040161577c565b6040805180830381865afa158015612842573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061286691906157c6565b50949350505050565b60006128796126da565b9050818110610fea5760cd54604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b1580156128c857600080fd5b505af19250505080156128d9575060015b15610fea575050565b60cf54600090815260dc6020526040908190208151600481526024810192839052610ef1929091612912916157ea565b6040519081900390206020820180516001600160e01b03166001600160e01b03199092169190911790523090613b0c565b60cc546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401612707565b6060600083516001600160401b0381111561299157612991614501565b6040519080825280602002602001820160405280156129f757816020015b6129e46040518060a0016040528060008019168152602001600081526020016000815260200160008152602001606081525090565b8152602001906001900390816129af5790505b50905060005b8451811015612b755780600003612ac1576040518060a0016040528086600081518110612a2c57612a2c614952565b602002602001015160000151815260200186600081518110612a5057612a50614952565b602002602001015160200151815260200186600081518110612a7457612a74614952565b60200260200101516040015181526020018581526020016040518060200160405280600081525081525082600081518110612ab157612ab1614952565b6020026020010181905250612b6d565b6040518060a00160405280868381518110612ade57612ade614952565b6020026020010151600001518152602001868381518110612b0157612b01614952565b6020026020010151602001518152602001868381518110612b2457612b24614952565b60200260200101516040015181526020016000815260200160405180602001604052806000815250815250828281518110612b6157612b61614952565b60200260200101819052505b6001016129fd565b509392505050565b6060600084516001600160401b03811115612b9a57612b9a614501565b604051908082528060200260200182016040528015612bc3578160200160208202803683370190505b50905060005b8551811015612c3d5780600003612bff578382600081518110612bee57612bee614952565b602002602001018181525050612c35565b60018651612c0d919061497e565b8103612c3557600019828281518110612c2857612c28614952565b6020026020010181815250505b600101612bc9565b5060405163945bcec960e01b81526001600160a01b0389169063945bcec990612c74908a908a908a908a9088904290600401615890565b6000604051808303816000875af1158015612c93573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612cbb919081019061529f565b98975050505050505050565b6033546001600160a01b03163314610f1c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e54565b610ef1612cc7565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612d5c57610e0783613b50565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612db6575060408051601f3d908101601f19168201909252612db39181019061554c565b60015b612e195760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610e54565b600080516020615b778339815191528114612e885760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610e54565b50610e07838383613bec565b478015610ef15760cd60009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0476040518263ffffffff1660e01b81526004016000604051808303818588803b158015612eeb57600080fd5b505af193505050508015612efd575060015b15610ef15750565b60d05460ff1615610f1c5760cd5460d0546040516370a0823160e01b81526101009091046001600160a01b03908116600483015260009216906370a0823190602401602060405180830381865afa158015612f64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f88919061554c565b60d054612fa4919061010090046001600160a01b031631615672565b60d154909150811015610ef1576000612fbb6126da565b905060008260d060010154612fd0919061497e565b9050818111612fdf5780612fe1565b815b60d05460cd54919250613006916001600160a01b039081169161010090041683613a5c565b6040518181527feb722ef3dbafc24e43f4627f9b306563a93d546865b49eb1e64fbaffdab73d5c9060200160405180910390a1505050565b60ce54600090815260db6020526040908190208151600481526024810192839052610ef1929091612912916157ea565b604051636eb1769f60e11b81523060048201526001600160a01b0382811660248301526000919084169063dd62ed3e90604401602060405180830381865afa1580156130be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e2919061554c565b1115610fea57610fea6001600160a01b038316826000613c11565b604051636eb1769f60e11b81523060048201526001600160a01b03828116602483015283169063dd62ed3e90604401602060405180830381865afa158015613149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061316d919061554c565b600003610fea57610fea6001600160a01b03831682600019613c11565b606060008251600161319c9190615672565b6001600160401b038111156131b3576131b3614501565b6040519080825280602002602001820160405280156131dc578160200160208202803683370190505b509050826000815181106131f2576131f2614952565b6020026020010151600001518160008151811061321157613211614952565b60200260200101906001600160a01b031690816001600160a01b03168152505060005b83518110156132a15783818151811061324f5761324f614952565b602002602001015160200151828260016132699190615672565b8151811061327957613279614952565b6001600160a01b039092166020928302919091019091015261329a8161570b565b9050613234565b5092915050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166133215760405162461bcd60e51b8152600401610e54906159a9565b610f1c613d26565b6040518060400160405280600e81526020016d627269646765436972636c65282960901b81525060db600060405160200161337e90602080825260069082015265434952434c4560d01b604082015260600190565b60405160208183030381529060405280519060200120815260200190815260200160002090816133ae91906159f4565b506040518060400160405280601081526020016f6272696467655374617267617465282960801b81525060db600060405160200161340890602080825260089082015267535441524741544560c01b604082015260600190565b604051602081830303815290604052805190602001208152602001908152602001600020908161343891906159f4565b506040518060400160405280600e81526020016d6272696467654178656c6172282960901b81525060db600060405160200161348e9060208082526006908201526520ac22a620a960d11b604082015260600190565b60405160208183030381529060405280519060200120815260200190815260200160002090816134be91906159f4565b506040518060400160405280600f81526020016e62726964676553796e61707365282960881b81525060db60006040516020016135169060208082526007908201526653594e4150534560c81b604082015260600190565b604051602081830303815290604052805190602001208152602001908152602001600020908161354691906159f4565b506040518060400160405280600d81526020016c6272696467657a6b45564d282960981b81525060db600060405160200161359a906020808252600590820152647a6b45564d60d81b604082015260600190565b60405160208183030381529060405280519060200120815260200190815260200160002090816135ca91906159f4565b506040518060400160405280600e81526020016d6272696467657a6b53796e63282960901b81525060db6000604051602001613620906020808252600690820152657a6b53594e4360d01b604082015260600190565b6040516020818303038152906040528051906020012081526020019081526020016000209081610ef191906159f4565b6040518060400160405280600b81526020016a73776170556e695632282960a81b81525060dc60006040516020016136a6906020808252600a90820152692aa724a9aba0a82fab1960b11b604082015260600190565b60405160208183030381529060405280519060200120815260200190815260200160002090816136d691906159f4565b506040518060400160405280600d81526020016c73776170536f6c69646c79282960981b81525060dc600060405160200161372c90602080825260079082015266534f4c49444c5960c81b604082015260600190565b604051602081830303815290604052805190602001208152602001908152602001600020908161375c91906159f4565b506040518060400160405280600b81526020016a73776170556e695633282960a81b81525060dc60006040516020016137b3906020808252600a9082015269554e49535741505f563360b01b604082015260600190565b60405160208183030381529060405280519060200120815260200190815260200160002090816137e391906159f4565b506040518060400160405280601381526020017273776170556e695633446561646c696e65282960681b81525060dc600060405160200161384b90602080825260139082015272554e49535741505f56335f444541444c494e4560681b604082015260600190565b604051602081830303815290604052805190602001208152602001908152602001600020908161387b91906159f4565b506040518060400160405280600d81526020016c73776170416c6765627261282960981b81525060dc60006040516020016138d190602080825260079082015266414c474542524160c81b604082015260600190565b604051602081830303815290604052805190602001208152602001908152602001600020908161390191906159f4565b506040518060400160405280600e81526020016d7377617042616c616e636572282960901b81525060dc6000604051602001613620906020808252600890820152672120a620a721a2a960c11b604082015260600190565b6060600061396683613d56565b90506000613975826001615672565b6001600160401b0381111561398c5761398c614501565b6040519080825280602002602001820160405280156139b5578160200160208202803683370190505b50905060005b82811015612b75576000806139cf87613d7c565b5091509150818484815181106139e7576139e7614952565b6001600160a01b03909216602092830291909101909101528084613a0c856001615672565b81518110613a1c57613a1c614952565b60200260200101906001600160a01b031690816001600160a01b031681525050613a4587613db8565b965050508080613a549061570b565b9150506139bb565b6040516001600160a01b038316602482015260448101829052610e0790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613de9565b60408051608081018252838152306020820152808201839052600060608201819052915163b858183f60e01b81526001600160a01b0386169063b858183f906127a0908490600401615aad565b60606127e7838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250613ebe565b6001600160a01b0381163b613bbd5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610e54565b600080516020615b7783398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b613bf583613f9b565b600082511180613c025750805b15610e075761094a8383613fdb565b801580613c8b5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015613c65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c89919061554c565b155b613cf65760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610e54565b6040516001600160a01b038316602482015260448101829052610e0790849063095ea7b360e01b90606401613a88565b600054610100900460ff16613d4d5760405162461bcd60e51b8152600401610e54906159a9565b610f1c336132a8565b6000613d6460036014615672565b60148351613d72919061497e565b6117509190615afb565b60008080613d8a8482614000565b9250613d978460146140b4565b9050613daf613da860036014615672565b8590614000565b91509193909250565b6060611750613dc960036014615672565b613dd560036014615672565b8451613de1919061497e565b84919061415f565b6000613e3e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166142b69092919063ffffffff16565b9050805160001480613e5f575080806020019051810190613e5f9190615b1d565b610e075760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e54565b606082471015613f1f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610e54565b600080866001600160a01b03168587604051613f3b9190615b3a565b60006040518083038185875af1925050503d8060008114613f78576040519150601f19603f3d011682016040523d82523d6000602084013e613f7d565b606091505b5091509150613f8e878383876142c5565b925050505b949350505050565b613fa481613b50565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606127e78383604051806060016040528060278152602001615b976027913961433e565b60008161400e816014615672565b10156140515760405162461bcd60e51b8152602060048201526012602482015271746f416464726573735f6f766572666c6f7760701b6044820152606401610e54565b61405c826014615672565b835110156140a45760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b6044820152606401610e54565b500160200151600160601b900490565b6000816140c2816003615672565b10156141045760405162461bcd60e51b8152602060048201526011602482015270746f55696e7432345f6f766572666c6f7760781b6044820152606401610e54565b61410f826003615672565b835110156141565760405162461bcd60e51b8152602060048201526014602482015273746f55696e7432345f6f75744f66426f756e647360601b6044820152606401610e54565b50016003015190565b60608161416d81601f615672565b10156141ac5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610e54565b826141b78382615672565b10156141f65760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610e54565b6142008284615672565b845110156142445760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610e54565b6060821580156142635760405191506000825260208201604052612866565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561429c578051835260209283019201614284565b5050858452601f01601f1916604052505090509392505050565b6060613f938484600085613ebe565b6060831561433457825160000361432d576001600160a01b0385163b61432d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e54565b5081613f93565b613f9383836143b6565b6060600080856001600160a01b03168560405161435b9190615b3a565b600060405180830381855af49150503d8060008114614396576040519150601f19603f3d011682016040523d82523d6000602084013e61439b565b606091505b50915091506143ac868383876142c5565b9695505050505050565b8151156143c65781518083602001fd5b8060405162461bcd60e51b8152600401610e549190614719565b634e487b7160e01b600052600160045260246000fd5b60008083601f84011261440857600080fd5b5081356001600160401b0381111561441f57600080fd5b60208301915083602082850101111561443757600080fd5b9250929050565b60008060006040848603121561445357600080fd5b8335925060208401356001600160401b0381111561447057600080fd5b61447c868287016143f6565b9497909650939450505050565b6000606082840312156126d457600080fd5b6000602082840312156144ad57600080fd5b81356001600160401b038111156144c357600080fd5b613f9384828501614489565b6001600160a01b0381168114610ef157600080fd5b6000602082840312156144f657600080fd5b81356127e7816144cf565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561453957614539614501565b60405290565b604051601f8201601f191681016001600160401b038111828210171561456757614567614501565b604052919050565b60006001600160401b0382111561458857614588614501565b50601f01601f191660200190565b600080604083850312156145a957600080fd5b82356145b4816144cf565b915060208301356001600160401b038111156145cf57600080fd5b8301601f810185136145e057600080fd5b80356145f36145ee8261456f565b61453f565b81815286602083850101111561460857600080fd5b816020840160208301376000602083830101528093505050509250929050565b6000604082840312156126d457600080fd5b6000806040838503121561464d57600080fd5b8235915060208301356001600160401b0381111561466a57600080fd5b61467685828601614628565b9150509250929050565b6002811061469e57634e487b7160e01b600052602160045260246000fd5b9052565b602081016117508284614680565b6000602082840312156146c257600080fd5b5035919050565b60005b838110156146e45781810151838201526020016146cc565b50506000910152565b600081518084526147058160208601602086016146c9565b601f01601f19169290920160200192915050565b6020815260006127e760208301846146ed565b6000806020838503121561473f57600080fd5b82356001600160401b0381111561475557600080fd5b614761858286016143f6565b90969095509350505050565b6001600160a01b0383168152604060208201819052600090613f93908301846146ed565b8015158114610ef157600080fd5b600080604083850312156147b257600080fd5b82356147bd816144cf565b915060208301356147cd81614791565b809150509250929050565b6000606082840312156147ea57600080fd5b6127e78383614489565b6001600160a01b0384168152606060208201819052600090614818908301856146ed565b82810360408401526143ac81856146ed565b6000806040838503121561483d57600080fd5b8235614848816144cf565b915060208301356147cd816144cf565b600181811c9082168061486c57607f821691505b6020821081036126d457634e487b7160e01b600052602260045260246000fd5b60006001600160401b038211156148a5576148a5614501565b5060051b60200190565b600082601f8301126148c057600080fd5b815160206148d06145ee8361488c565b82815260059290921b840181019181810190868411156148ef57600080fd5b8286015b84811015614913578051614906816144cf565b83529183019183016148f3565b509695505050505050565b60006020828403121561493057600080fd5b81516001600160401b0381111561494657600080fd5b613f93848285016148af565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561175057611750614968565b6000608082840312156149a357600080fd5b604051608081018181106001600160401b03821117156149c5576149c5614501565b604052825161ffff811681146149da57600080fd5b808252506020830151602082015260408301516040820152606083015160608201528091505092915050565b80518252602081015160208301526000604082015160606040850152613f9360608501826146ed565b60008154614a3c81614858565b808552602060018381168015614a595760018114614a7357614aa1565b60ff1985168884015283151560051b880183019550614aa1565b866000528260002060005b85811015614a995781548a8201860152908301908401614a7e565b890184019650505b505050505092915050565b600061012061ffff8b16835289602084015288604084015260018060a01b03881660608401528660808401528560a08401528060c0840152614af081840186614a06565b905082810360e0840152614b048185614a2f565b8381036101009094019390935250506000815260200198975050505050505050565b6000806040808486031215614b3a57600080fd5b83516001600160401b0380821115614b5157600080fd5b818601915086601f830112614b6557600080fd5b81516020614b756145ee8361488c565b8281526060928302850182019282820191908b851115614b9457600080fd5b958301955b84871015614bdc5780878d031215614bb15760008081fd5b614bb9614517565b875181528488015185820152888801518982015283529586019591830191614b99565b5091890151919750909450505080831115614bf657600080fd5b5050614676858286016148af565b601f821115610e0757600081815260208120601f850160051c81016020861015614c2b5750805b601f850160051c820191505b81811015614c4a57828155600101614c37565b505050505050565b600019600383901b1c191660019190911b1790565b6001600160401b03831115614c7e57614c7e614501565b614c9283614c8c8354614858565b83614c04565b6000601f841160018114614cc05760008515614cae5750838201355b614cb88682614c52565b845550610d93565b600083815260209020601f19861690835b82811015614cf15786850135825560209485019460019092019101614cd1565b5086821015614d0e5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6000808335601e19843603018112614d3757600080fd5b83016020810192503590506001600160401b03811115614d5657600080fd5b80360382131561443757600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815260008235614d9f816144cf565b6001600160a01b0316602083810191909152614dbd90840184614d20565b60606040850152614dd2608085018284614d65565b915050614de26040850185614d20565b848303601f190160608601526143ac838284614d65565b80546001600160a01b0319166001600160a01b0392909216919091179055565b6000808335601e19843603018112614e3057600080fd5b8301803591506001600160401b03821115614e4a57600080fd5b60200191503681900382131561443757600080fd5b8135614e6a816144cf565b614e748183614df9565b5060018082016020614e8881860186614e19565b6001600160401b03811115614e9f57614e9f614501565b614eb381614ead8654614858565b86614c04565b6000601f821160018114614ee15760008315614ecf5750838201355b614ed98482614c52565b875550614f36565b600086815260209020601f19841690835b82811015614f0f5786850135825593870193908901908701614ef2565b5084821015614f2c5760001960f88660031b161c19848701351681555b50508683881b0186555b50505050505050614f4a6040830183614e19565b61094a818360028601614c67565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b60008135614ffd816144cf565b6001600160a01b031683526150156020830183614d20565b6040602086015261502a604086018284614d65565b95945050505050565b828152604060208201526000613f936040830184614ff0565b8135615057816144cf565b6150618183614df9565b506001808201602061507581860186614e19565b6001600160401b0381111561508c5761508c614501565b61509a81614ead8654614858565b6000601f8211600181146150c857600083156150b65750838201355b6150c08482614c52565b87555061511d565b600086815260209020601f19841690835b828110156150f657868501358255938701939089019087016150d9565b50848210156151135760001960f88660031b161c19848701351681555b50508683881b0186555b505050505050505050565b610fea828261504c565b6000602080838503121561514557600080fd5b82516001600160401b0381111561515b57600080fd5b8301601f8101851361516c57600080fd5b805161517a6145ee8261488c565b8181526060918202830184019184820191908884111561519957600080fd5b938501935b838510156151fe5780858a0312156151b65760008081fd5b6151be614517565b85516151c9816144cf565b8152858701516151d8816144cf565b818801526040868101516151eb81614791565b908201528352938401939185019161519e565b50979650505050505050565b600060a0820187835260208781850152604060a08186015282885180855260c087019150838a01945060005b8181101561527357855180516001600160a01b03908116855286820151168685015284015115158484015294840194606090920191600101615236565b50506001600160a01b0388166060870152935061528f92505050565b8260808301529695505050505050565b600060208083850312156152b257600080fd5b82516001600160401b038111156152c857600080fd5b8301601f810185136152d957600080fd5b80516152e76145ee8261488c565b81815260059190911b8201830190838101908783111561530657600080fd5b928401925b828410156153245783518252928401929084019061530b565b979650505050505050565b600081518084526020808501945080840160005b838110156153685781516001600160a01b031687529582019590820190600101615343565b509495945050505050565b85815284602082015260a06040820152600061539260a083018661532f565b6001600160a01b0394909416606083015250608001529392505050565b602081526000613f93602083018486614d65565b60006153d16145ee8461456f565b90508281528383830111156153e557600080fd5b6127e78360208301846146c9565b600082601f83011261540457600080fd5b6127e7838351602085016153c3565b60006020828403121561542557600080fd5b81516001600160401b038082111561543c57600080fd5b908301906040828603121561545057600080fd5b60405160408101818110838211171561546b5761546b614501565b60405282518281111561547d57600080fd5b615489878286016153f3565b82525060208301518281111561549e57600080fd5b6154aa878286016153f3565b60208301525095945050505050565b6080815260006154cc60808301876146ed565b82810360208401526154de8187614a2f565b905082810360408401526154f281866146ed565b91505082606083015295945050505050565b60006020828403121561551657600080fd5b81516001600160401b0381111561552c57600080fd5b8201601f8101841361553d57600080fd5b613f93848251602084016153c3565b60006020828403121561555e57600080fd5b5051919050565b813561557081614791565b815460ff19811691151560ff1691821783556020840135615590816144cf565b6001600160a81b03199190911690911760089190911b610100600160a81b03161781556040919091013560019190910155565b805160ff811681146155d457600080fd5b919050565b600060c082840312156155eb57600080fd5b60405160c081018181106001600160401b038211171561560d5761560d614501565b60405282518152615620602084016155c3565b6020820152615631604084016155c3565b60408201526060830151615644816144cf565b6060820152615655608084016155c3565b608082015261566660a084016155c3565b60a08201529392505050565b8082018082111561175057611750614968565b60006020828403121561569757600080fd5b815163ffffffff811681146127e757600080fd5b6000602082840312156156bd57600080fd5b81516001600160401b03811681146127e757600080fd5b600083516156e68184602088016146c9565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b60006001820161571d5761571d614968565b5060010190565b602081526000825160a0602084015261574060c08401826146ed565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b61ffff8516815260ff8416602082015260a0604082015260006157a260a08301856146ed565b82810380606085015260008252602081016080850152506153246020820185614a06565b600080604083850312156157d957600080fd5b505080516020909101519092909150565b60008083546157f881614858565b60018281168015615810576001811461582557615854565b60ff1984168752821515830287019450615854565b8760005260208060002060005b8581101561584b5781548a820152908401908201615832565b50505082870194505b50929695505050505050565b600081518084526020808501945080840160005b8381101561536857815187529582019590820190600101615874565b60006101208083016158a2848b614680565b60208481019290925288519081905261014080850192600583901b8601909101918a820160005b8281101561592c5787850361013f190186528151805186528481015185870152604080820151908701526060808201519087015260809081015160a091870182905290615918818801836146ed565b9786019796505050908301906001016158c9565b505050508381036040850152615942818961532f565b915050615982606084018780516001600160a01b039081168352602080830151151590840152604080830151909116908301526060908101511515910152565b82810360e08401526159948186615860565b91505082610100830152979650505050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b81516001600160401b03811115615a0d57615a0d614501565b615a2181615a1b8454614858565b84614c04565b602080601f831160018114615a505760008415615a3e5750858301515b615a488582614c52565b865550614c4a565b600085815260208120601f198616915b82811015615a7f57888601518255948401946001909101908401615a60565b5085821015615a9d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602081526000825160806020840152615ac960a08401826146ed565b905060018060a01b03602085015116604084015260408401516060840152606084015160808401528091505092915050565b600082615b1857634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215615b2f57600080fd5b81516127e781614791565b60008251615b4c8184602087016146c9565b919091019291505056fe48b87fc02925b37a6aefac60c14fa9d8e9988d7dfadf262d4bd845872ca40730360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202cf5d105cce700f83f307a3dd04f585ba73959a056059f2d16f4535b39853d2764736f6c63430008130033
Deployed Bytecode
0x6080604052600436106102605760003560e01c8063748b3c0511610144578063c4b00c4f116100b6578063d7d66e711161007a578063d7d66e7114610714578063ee63c1e514610734578063f2fde38b14610749578063f3f1a71a14610769578063fe8d1ab014610789578063ff33d21f1461079e57600080fd5b8063c4b00c4f14610635578063c89f2ce414610655578063ca325469146106c6578063cc5ea4ef146106ea578063d49b6408146106ff57600080fd5b80639c345b9f116101085780639c345b9f1461056b578063a5131aaa14610581578063b54653fb14610596578063b9f39147146105ea578063bac86af5146105ff578063c3c224751461061f57600080fd5b8063748b3c05146104ea5780638129fc1c146104ff578063873d80ec146105145780638da5cb5b14610537578063943f8e961461055557600080fd5b80635066a747116101dd578063671f6a26116101a1578063671f6a26146104375780636ae407111461045e5780636d0a68911461047357806370c75107146104a0578063715018a6146104c057806373f1df33146104d557600080fd5b80635066a747146103aa5780635109d8b6146103ca57806352d1902d146103df578063530728d51461040257806364e510a11461041757600080fd5b80631610ee40116102245780631610ee401461032257806322be3de1146103425780633659cfe6146103625780634641257d146103825780634f1ef2861461039757600080fd5b80630278fb8a14610286578063057d1ae31461029b5780630d1f7833146102b057806311b0b42d146102c5578063154085921461030257600080fd5b366102815760cd546001600160a01b0316331461027f5761027f6143e0565b005b600080fd5b34801561029257600080fd5b5061027f6107be565b3480156102a757600080fd5b5061027f610950565b3480156102bc57600080fd5b5061027f610bb5565b3480156102d157600080fd5b5060cd546102e5906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561030e57600080fd5b5061027f61031d36600461443e565b610d9a565b34801561032e57600080fd5b5061027f61033d36600461449b565b610dbb565b34801561034e57600080fd5b5060cc546102e5906001600160a01b031681565b34801561036e57600080fd5b5061027f61037d3660046144e4565b610e0c565b34801561038e57600080fd5b5061027f610ef4565b61027f6103a5366004614596565b610f1e565b3480156103b657600080fd5b5061027f6103c536600461463a565b610fee565b3480156103d657600080fd5b5061027f611081565b3480156103eb57600080fd5b506103f4611274565b6040519081526020016102f9565b34801561040e57600080fd5b5061027f611327565b34801561042357600080fd5b5061027f61043236600461463a565b611414565b34801561044357600080fd5b5060c9546104519060ff1681565b6040516102f991906146a2565b34801561046a57600080fd5b5061027f6114a2565b34801561047f57600080fd5b5061049361048e3660046146b0565b611688565b6040516102f99190614719565b3480156104ac57600080fd5b506103f46104bb36600461472c565b611722565b3480156104cc57600080fd5b5061027f611756565b3480156104e157600080fd5b5061027f611768565b3480156104f657600080fd5b5061027f6117c9565b34801561050b57600080fd5b5061027f611939565b34801561052057600080fd5b50610529611ab1565b6040516102f992919061476d565b34801561054357600080fd5b506033546001600160a01b03166102e5565b34801561056157600080fd5b506103f460cf5481565b34801561057757600080fd5b506103f460ce5481565b34801561058d57600080fd5b5061027f611b52565b3480156105a257600080fd5b5060d05460d1546105c59160ff8116916101009091046001600160a01b03169083565b6040805193151584526001600160a01b039092166020840152908201526060016102f9565b3480156105f657600080fd5b5061027f611bbe565b34801561060b57600080fd5b5061027f61061a36600461479f565b611d4a565b34801561062b57600080fd5b506103f460d95481565b34801561064157600080fd5b5061027f6106503660046147d8565b611e44565b34801561066157600080fd5b5060ca5460cb54610691916001600160a01b038082169260ff600160a01b93849004811693928216929091041684565b6040516102f994939291906001600160a01b039485168152921515602084015292166040820152901515606082015260800190565b3480156106d257600080fd5b506106db611e59565b6040516102f9939291906147f4565b3480156106f657600080fd5b5061027f611f88565b34801561070b57600080fd5b50610529612123565b34801561072057600080fd5b5061027f61072f3660046146b0565b612141565b34801561074057600080fd5b5061027f612181565b34801561075557600080fd5b5061027f6107643660046144e4565b61230d565b34801561077557600080fd5b506104936107843660046146b0565b612383565b34801561079557600080fd5b5061027f61239c565b3480156107aa57600080fd5b5061027f6107b936600461482a565b612525565b6107c6612601565b600060d460010180546107d890614858565b80601f016020809104026020016040519081016040528092919081815260200182805461080490614858565b80156108515780601f1061082657610100808354040283529160200191610851565b820191906000526020600020905b81548152906001019060200180831161083457829003601f168201915b5050505050806020019051810190610869919061491e565b60cd5481519192506001600160a01b031690829060009061088c5761088c614952565b60200260200101516001600160a01b0316146108bb576040516376c252e160e11b815260040160405180910390fd5b60cc5481516001600160a01b039091169082906108da9060019061497e565b815181106108ea576108ea614952565b60200260200101516001600160a01b031614610919576040516376c252e160e11b815260040160405180910390fd5b600061092482612621565b905060006109306126da565b60d45490915061094a906001600160a01b0316838361274d565b50505050565b610958612601565b600060d2600101805461096a90614858565b80601f016020809104026020016040519081016040528092919081815260200182805461099690614858565b80156109e35780601f106109b8576101008083540402835291602001916109e3565b820191906000526020600020905b8154815290600101906020018083116109c657829003601f168201915b50505050508060200190518101906109fb9190614991565b905060006040518060600160405280836020015181526020016000815260200160405180604001604052806002815260200161060f60f31b81525081525090506000610ad9836000015160d66001018054610a5590614858565b80601f0160208091040260200160405190810160405280929190818152602001828054610a8190614858565b8015610ace5780601f10610aa357610100808354040283529160200191610ace565b820191906000526020600020905b815481529060010190602001808311610ab157829003601f168201915b5050505050846127ee565b9050610ae48161286f565b610aec6128e2565b6000610af6612943565b905060d954811115610b7f5760d2548451604080870151606088015191516327efc43f60e21b81526001600160a01b0390941693639fbf10fc938793610b4c939192309089906000908d9060d790600401614aac565b6000604051808303818588803b158015610b6557600080fd5b505af1158015610b79573d6000803e3d6000fd5b50505050505b60cc546040518281526001600160a01b0390911690600080516020615b578339815191529060200160405180910390a250505050565b610bbd612601565b60008060d46001018054610bd090614858565b80601f0160208091040260200160405190810160405280929190818152602001828054610bfc90614858565b8015610c495780601f10610c1e57610100808354040283529160200191610c49565b820191906000526020600020905b815481529060010190602001808311610c2c57829003601f168201915b5050505050806020019051810190610c619190614b26565b60cd5481519294509092506001600160a01b0316908290600090610c8757610c87614952565b60200260200101516001600160a01b031614610cb6576040516376c252e160e11b815260040160405180910390fd5b60cc5481516001600160a01b03909116908290610cd59060019061497e565b81518110610ce557610ce5614952565b60200260200101516001600160a01b031614610d14576040516376c252e160e11b815260040160405180910390fd5b6000610d1e6126da565b90506000610d2c8483612974565b60d45460c9546040805160808101825260ca546001600160a01b03808216835260ff600160a01b9283900481161515602085015260cb548083169585019590955291909304811615156060830152949550610d939491909316929116908490879087612b7d565b5050505050565b610da2612cc7565b600083815260db6020526040902061094a828483614c67565b610dc3612cc7565b7f518f47fcfba5d9b707c3387a7fa4301136192d8091a43ea13ae8db7275ab5d3a81604051610df29190614d8e565b60405180910390a18060d6610e078282614e5f565b505050565b6001600160a01b037f000000000000000000000000f4a361fbe65561e6389f9b6ed4c1e28ad16afe4f163003610e5d5760405162461bcd60e51b8152600401610e5490614f58565b60405180910390fd5b7f000000000000000000000000f4a361fbe65561e6389f9b6ed4c1e28ad16afe4f6001600160a01b0316610ea6600080516020615b77833981519152546001600160a01b031690565b6001600160a01b031614610ecc5760405162461bcd60e51b8152600401610e5490614fa4565b610ed581612d21565b60408051600080825260208201909252610ef191839190612d29565b50565b610efc612e94565b610f04612f05565b6000610f0e6126da565b1115610f1c57610f1c61303e565b565b6001600160a01b037f000000000000000000000000f4a361fbe65561e6389f9b6ed4c1e28ad16afe4f163003610f665760405162461bcd60e51b8152600401610e5490614f58565b7f000000000000000000000000f4a361fbe65561e6389f9b6ed4c1e28ad16afe4f6001600160a01b0316610faf600080516020615b77833981519152546001600160a01b031690565b6001600160a01b031614610fd55760405162461bcd60e51b8152600401610e5490614fa4565b610fde82612d21565b610fea82826001612d29565b5050565b610ff6612cc7565b7f25f7dd6fc737add5174192a11292dfd270c1397f9c4f641fb6336a208b5efbed8282604051611027929190615033565b60405180910390a160cd5460d45461104b916001600160a01b03908116911661306e565b60cf8290558060d461105d8282615128565b505060cd54610fea906001600160a01b031661107c60208401846144e4565b6130fd565b611089612601565b600060d4600101805461109b90614858565b80601f01602080910402602001604051908101604052809291908181526020018280546110c790614858565b80156111145780601f106110e957610100808354040283529160200191611114565b820191906000526020600020905b8154815290600101906020018083116110f757829003601f168201915b505050505080602001905181019061112c9190615132565b905060006111398261318a565b60cd5481519192506001600160a01b031690829060009061115c5761115c614952565b60200260200101516001600160a01b03161461118b576040516376c252e160e11b815260040160405180910390fd5b60cc5481516001600160a01b039091169082906111aa9060019061497e565b815181106111ba576111ba614952565b60200260200101516001600160a01b0316146111e9576040516376c252e160e11b815260040160405180910390fd5b60006111f36126da565b60d454604051631e82ecdb60e31b81529192506001600160a01b03169063f41766d89061122d90849060009088903090429060040161520a565b6000604051808303816000875af115801561124c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261094a919081019061529f565b6000306001600160a01b037f000000000000000000000000f4a361fbe65561e6389f9b6ed4c1e28ad16afe4f16146113145760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610e54565b50600080516020615b7783398151915290565b61132f612601565b6113376128e2565b6000611341612943565b905060d9548111156113e15760d25460d65460cc5460405163cd58657960e01b81526000600482018190526001600160a01b0393841660248301526044820186905291831660648201526001608482015260c060a482015260c481019190915291169063cd5865799060e4015b600060405180830381600087803b1580156113c857600080fd5b505af11580156113dc573d6000803e3d6000fd5b505050505b60cc546040518281526001600160a01b0390911690600080516020615b578339815191529060200160405180910390a250565b61141c612cc7565b7f5e355369ceaccb04ff615500f99b96912ce9f237ed35ae521487c19064e2318d828260405161144d929190615033565b60405180910390a160cc5460d254611471916001600160a01b03908116911661306e565b60ce8290558060d26114838282615128565b505060cc54610fea906001600160a01b031661107c60208401846144e4565b6114aa612601565b600060d460010180546114bc90614858565b80601f01602080910402602001604051908101604052809291908181526020018280546114e890614858565b80156115355780601f1061150a57610100808354040283529160200191611535565b820191906000526020600020905b81548152906001019060200180831161151857829003601f168201915b505050505080602001905181019061154d919061491e565b60cd5481519192506001600160a01b031690829060009061157057611570614952565b60200260200101516001600160a01b03161461159f576040516376c252e160e11b815260040160405180910390fd5b60cc5481516001600160a01b039091169082906115be9060019061497e565b815181106115ce576115ce614952565b60200260200101516001600160a01b0316146115fd576040516376c252e160e11b815260040160405180910390fd5b60006116076126da565b60d4546040516338ed173960e01b81529192506001600160a01b0316906338ed173990611641908490600090879030904290600401615373565b6000604051808303816000875af1158015611660573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e07919081019061529f565b60db60205260009081526040902080546116a190614858565b80601f01602080910402602001604051908101604052809291908181526020018280546116cd90614858565b801561171a5780601f106116ef5761010080835404028352916020019161171a565b820191906000526020600020905b8154815290600101906020018083116116fd57829003601f168201915b505050505081565b600082826040516020016117379291906153af565b6040516020818303038152906040528051906020012090505b92915050565b61175e612cc7565b610f1c60006132a8565b611770612601565b6117786128e2565b6000611782612943565b905060d954811115610ef15760d25460d6546040516302e108e960e11b8152600481018490526001600160a01b0391821660248201529116906305c211d2906044016113ae565b6117d1612601565b600060d260010180546117e390614858565b80601f016020809104026020016040519081016040528092919081815260200182805461180f90614858565b801561185c5780601f106118315761010080835404028352916020019161185c565b820191906000526020600020905b81548152906001019060200180831161183f57829003601f168201915b50505050508060200190518101906118749190615413565b905061187e6128e2565b6000611888612943565b905060d9548111156119045760d254825160208401516040516326ef699d60e01b81526001600160a01b03909316926326ef699d926118d192909160d8919087906004016154b9565b600060405180830381600087803b1580156118eb57600080fd5b505af11580156118ff573d6000803e3d6000fd5b505050505b60cc546040518281526001600160a01b0390911690600080516020615b57833981519152906020015b60405180910390a25050565b600054610100900460ff16158080156119595750600054600160ff909116105b806119735750303b158015611973575060005460ff166001145b6119d65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610e54565b6000805460ff1916600117905580156119f9576000805461ff0019166101001790555b611a016132fa565b611a09613329565b611a11613650565b604080516080810182523080825260006020830181905292820181905260609091019190915260ca805460ff60a01b199092166001600160a81b0319928316811790915560cb805490921617905560c9805460ff191690558015610ef1576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b60d4805460d580546001600160a01b039092169291611acf90614858565b80601f0160208091040260200160405190810160405280929190818152602001828054611afb90614858565b8015611b485780601f10611b1d57610100808354040283529160200191611b48565b820191906000526020600020905b815481529060010190602001808311611b2b57829003601f168201915b5050505050905082565b611b5a612601565b611b626128e2565b6000611b6c612943565b905060d9548111156113e15760d25460d65460cc54604051636ce5768960e11b81526001600160a01b03928316600482015290821660248201526044810184905291169063d9caed12906064016113ae565b611bc6612601565b600060d46001018054611bd890614858565b80601f0160208091040260200160405190810160405280929190818152602001828054611c0490614858565b8015611c515780601f10611c2657610100808354040283529160200191611c51565b820191906000526020600020905b815481529060010190602001808311611c3457829003601f168201915b5050505050806020019051810190611c699190615504565b90506000611c7682613959565b60cd5481519192506001600160a01b0316908290600090611c9957611c99614952565b60200260200101516001600160a01b031614611cc8576040516376c252e160e11b815260040160405180910390fd5b60cc5481516001600160a01b03909116908290611ce79060019061497e565b81518110611cf757611cf7614952565b60200260200101516001600160a01b031614611d26576040516376c252e160e11b815260040160405180910390fd5b6000611d306126da565b60d45490915061094a906001600160a01b0316848361274d565b611d52612cc7565b8015611dc3576040514790600090339083908381818185875af1925050503d8060008114611d9c576040519150601f19603f3d011682016040523d82523d6000602084013e611da1565b606091505b505090508061094a57604051630dcf35db60e41b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611e0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2e919061554c565b9050610e076001600160a01b0384163383613a5c565b611e4c612cc7565b8060d0610e078282615565565b60d6805460d780546001600160a01b039092169291611e7790614858565b80601f0160208091040260200160405190810160405280929190818152602001828054611ea390614858565b8015611ef05780601f10611ec557610100808354040283529160200191611ef0565b820191906000526020600020905b815481529060010190602001808311611ed357829003601f168201915b505050505090806002018054611f0590614858565b80601f0160208091040260200160405190810160405280929190818152602001828054611f3190614858565b8015611f7e5780601f10611f5357610100808354040283529160200191611f7e565b820191906000526020600020905b815481529060010190602001808311611f6157829003601f168201915b5050505050905083565b611f90612601565b600060d26001018054611fa290614858565b80601f0160208091040260200160405190810160405280929190818152602001828054611fce90614858565b801561201b5780601f10611ff05761010080835404028352916020019161201b565b820191906000526020600020905b815481529060010190602001808311611ffe57829003601f168201915b505050505080602001905181019061203391906155d9565b905061203d6128e2565b6000612047612943565b905060d9548111156119045760d25460d6548351606085015160208601516040870151608088015160a08901516001600160a01b0397881697639f3307279716959493929189916000914291836120a084610e10615672565b6040516001600160e01b031960e08f901b1681526001600160a01b039c8d166004820152602481019b909b529a90981660448a015260ff96871660648a0152948616608489015260a488019390935260c487019190915260e4860152821661010485015216610124830152610144820152610164810191909152610184016118d1565b60d2805460d380546001600160a01b039092169291611acf90614858565b612149612cc7565b6040518181527ff4f47d85dc8207b9d9c6dfd289d4f5008b33df899eda3da90658d75c351e54759060200160405180910390a160d955565b612189612601565b600060d4600101805461219b90614858565b80601f01602080910402602001604051908101604052809291908181526020018280546121c790614858565b80156122145780601f106121e957610100808354040283529160200191612214565b820191906000526020600020905b8154815290600101906020018083116121f757829003601f168201915b505050505080602001905181019061222c9190615504565b9050600061223982613959565b60cd5481519192506001600160a01b031690829060009061225c5761225c614952565b60200260200101516001600160a01b03161461228b576040516376c252e160e11b815260040160405180910390fd5b60cc5481516001600160a01b039091169082906122aa9060019061497e565b815181106122ba576122ba614952565b60200260200101516001600160a01b0316146122e9576040516376c252e160e11b815260040160405180910390fd5b60006122f36126da565b60d45490915061094a906001600160a01b03168483613abf565b612315612cc7565b6001600160a01b03811661237a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e54565b610ef1816132a8565b60dc60205260009081526040902080546116a190614858565b6123a4612601565b600060d260010180546123b690614858565b80601f01602080910402602001604051908101604052809291908181526020018280546123e290614858565b801561242f5780601f106124045761010080835404028352916020019161242f565b820191906000526020600020905b81548152906001019060200180831161241257829003601f168201915b50505050508060200190518101906124479190615685565b90506124516128e2565b600061245b612943565b905060d9548111156119045760d25460d65460cc546040516337e9a82760e11b81526004810185905263ffffffff861660248201526001600160a01b0392831660448201529082166064820152911690636fd3504e906084016020604051808303816000875af11580156124d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f791906156ab565b5060cc546040518281526001600160a01b0390911690600080516020615b578339815191529060200161192d565b61252d612cc7565b60da5460ff166125725760cc80546001600160a01b039384166001600160a01b03199182161790915560cd805492909316911617905560da805460ff19166001179055565b60cc54604080516001600160a01b03928316815291841660208301527f4239efeca0761c0d170bd15a6e85542dbe0376ba0f5f1551b39c6045866ff735910160405180910390a160cc5460d2546125d5916001600160a01b03908116911661306e565b60cc80546001600160a01b0319166001600160a01b0384811691821790925560d254610fea92166130fd565b333014610f1c5760405163ea8e4eb560e01b815260040160405180910390fd5b60608160008151811061263657612636614952565b6020026020010151604051602001612666919060609190911b6bffffffffffffffffffffffff1916815260140190565b60408051601f19818403018152919052905060015b82518110156126d4578183828151811061269757612697614952565b60200260200101516040516020016126b09291906156d4565b604051602081830303815290604052915080806126cc9061570b565b91505061267b565b50919050565b60cd546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a08231906024015b602060405180830381865afa158015612724573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612748919061554c565b905090565b6040805160a081018252838152306020820152428183015260608101839052600060808201819052915163c04b8d5960e01b81526001600160a01b0386169063c04b8d59906127a0908490600401615724565b6020604051808303816000875af11580156127bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127e3919061554c565b9150505b9392505050565b60d254604051630a51236960e01b81526000916001600160a01b031690630a512369906128269087906001908890889060040161577c565b6040805180830381865afa158015612842573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061286691906157c6565b50949350505050565b60006128796126da565b9050818110610fea5760cd54604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b1580156128c857600080fd5b505af19250505080156128d9575060015b15610fea575050565b60cf54600090815260dc6020526040908190208151600481526024810192839052610ef1929091612912916157ea565b6040519081900390206020820180516001600160e01b03166001600160e01b03199092169190911790523090613b0c565b60cc546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401612707565b6060600083516001600160401b0381111561299157612991614501565b6040519080825280602002602001820160405280156129f757816020015b6129e46040518060a0016040528060008019168152602001600081526020016000815260200160008152602001606081525090565b8152602001906001900390816129af5790505b50905060005b8451811015612b755780600003612ac1576040518060a0016040528086600081518110612a2c57612a2c614952565b602002602001015160000151815260200186600081518110612a5057612a50614952565b602002602001015160200151815260200186600081518110612a7457612a74614952565b60200260200101516040015181526020018581526020016040518060200160405280600081525081525082600081518110612ab157612ab1614952565b6020026020010181905250612b6d565b6040518060a00160405280868381518110612ade57612ade614952565b6020026020010151600001518152602001868381518110612b0157612b01614952565b6020026020010151602001518152602001868381518110612b2457612b24614952565b60200260200101516040015181526020016000815260200160405180602001604052806000815250815250828281518110612b6157612b61614952565b60200260200101819052505b6001016129fd565b509392505050565b6060600084516001600160401b03811115612b9a57612b9a614501565b604051908082528060200260200182016040528015612bc3578160200160208202803683370190505b50905060005b8551811015612c3d5780600003612bff578382600081518110612bee57612bee614952565b602002602001018181525050612c35565b60018651612c0d919061497e565b8103612c3557600019828281518110612c2857612c28614952565b6020026020010181815250505b600101612bc9565b5060405163945bcec960e01b81526001600160a01b0389169063945bcec990612c74908a908a908a908a9088904290600401615890565b6000604051808303816000875af1158015612c93573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612cbb919081019061529f565b98975050505050505050565b6033546001600160a01b03163314610f1c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e54565b610ef1612cc7565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612d5c57610e0783613b50565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612db6575060408051601f3d908101601f19168201909252612db39181019061554c565b60015b612e195760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610e54565b600080516020615b778339815191528114612e885760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610e54565b50610e07838383613bec565b478015610ef15760cd60009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0476040518263ffffffff1660e01b81526004016000604051808303818588803b158015612eeb57600080fd5b505af193505050508015612efd575060015b15610ef15750565b60d05460ff1615610f1c5760cd5460d0546040516370a0823160e01b81526101009091046001600160a01b03908116600483015260009216906370a0823190602401602060405180830381865afa158015612f64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f88919061554c565b60d054612fa4919061010090046001600160a01b031631615672565b60d154909150811015610ef1576000612fbb6126da565b905060008260d060010154612fd0919061497e565b9050818111612fdf5780612fe1565b815b60d05460cd54919250613006916001600160a01b039081169161010090041683613a5c565b6040518181527feb722ef3dbafc24e43f4627f9b306563a93d546865b49eb1e64fbaffdab73d5c9060200160405180910390a1505050565b60ce54600090815260db6020526040908190208151600481526024810192839052610ef1929091612912916157ea565b604051636eb1769f60e11b81523060048201526001600160a01b0382811660248301526000919084169063dd62ed3e90604401602060405180830381865afa1580156130be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e2919061554c565b1115610fea57610fea6001600160a01b038316826000613c11565b604051636eb1769f60e11b81523060048201526001600160a01b03828116602483015283169063dd62ed3e90604401602060405180830381865afa158015613149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061316d919061554c565b600003610fea57610fea6001600160a01b03831682600019613c11565b606060008251600161319c9190615672565b6001600160401b038111156131b3576131b3614501565b6040519080825280602002602001820160405280156131dc578160200160208202803683370190505b509050826000815181106131f2576131f2614952565b6020026020010151600001518160008151811061321157613211614952565b60200260200101906001600160a01b031690816001600160a01b03168152505060005b83518110156132a15783818151811061324f5761324f614952565b602002602001015160200151828260016132699190615672565b8151811061327957613279614952565b6001600160a01b039092166020928302919091019091015261329a8161570b565b9050613234565b5092915050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166133215760405162461bcd60e51b8152600401610e54906159a9565b610f1c613d26565b6040518060400160405280600e81526020016d627269646765436972636c65282960901b81525060db600060405160200161337e90602080825260069082015265434952434c4560d01b604082015260600190565b60405160208183030381529060405280519060200120815260200190815260200160002090816133ae91906159f4565b506040518060400160405280601081526020016f6272696467655374617267617465282960801b81525060db600060405160200161340890602080825260089082015267535441524741544560c01b604082015260600190565b604051602081830303815290604052805190602001208152602001908152602001600020908161343891906159f4565b506040518060400160405280600e81526020016d6272696467654178656c6172282960901b81525060db600060405160200161348e9060208082526006908201526520ac22a620a960d11b604082015260600190565b60405160208183030381529060405280519060200120815260200190815260200160002090816134be91906159f4565b506040518060400160405280600f81526020016e62726964676553796e61707365282960881b81525060db60006040516020016135169060208082526007908201526653594e4150534560c81b604082015260600190565b604051602081830303815290604052805190602001208152602001908152602001600020908161354691906159f4565b506040518060400160405280600d81526020016c6272696467657a6b45564d282960981b81525060db600060405160200161359a906020808252600590820152647a6b45564d60d81b604082015260600190565b60405160208183030381529060405280519060200120815260200190815260200160002090816135ca91906159f4565b506040518060400160405280600e81526020016d6272696467657a6b53796e63282960901b81525060db6000604051602001613620906020808252600690820152657a6b53594e4360d01b604082015260600190565b6040516020818303038152906040528051906020012081526020019081526020016000209081610ef191906159f4565b6040518060400160405280600b81526020016a73776170556e695632282960a81b81525060dc60006040516020016136a6906020808252600a90820152692aa724a9aba0a82fab1960b11b604082015260600190565b60405160208183030381529060405280519060200120815260200190815260200160002090816136d691906159f4565b506040518060400160405280600d81526020016c73776170536f6c69646c79282960981b81525060dc600060405160200161372c90602080825260079082015266534f4c49444c5960c81b604082015260600190565b604051602081830303815290604052805190602001208152602001908152602001600020908161375c91906159f4565b506040518060400160405280600b81526020016a73776170556e695633282960a81b81525060dc60006040516020016137b3906020808252600a9082015269554e49535741505f563360b01b604082015260600190565b60405160208183030381529060405280519060200120815260200190815260200160002090816137e391906159f4565b506040518060400160405280601381526020017273776170556e695633446561646c696e65282960681b81525060dc600060405160200161384b90602080825260139082015272554e49535741505f56335f444541444c494e4560681b604082015260600190565b604051602081830303815290604052805190602001208152602001908152602001600020908161387b91906159f4565b506040518060400160405280600d81526020016c73776170416c6765627261282960981b81525060dc60006040516020016138d190602080825260079082015266414c474542524160c81b604082015260600190565b604051602081830303815290604052805190602001208152602001908152602001600020908161390191906159f4565b506040518060400160405280600e81526020016d7377617042616c616e636572282960901b81525060dc6000604051602001613620906020808252600890820152672120a620a721a2a960c11b604082015260600190565b6060600061396683613d56565b90506000613975826001615672565b6001600160401b0381111561398c5761398c614501565b6040519080825280602002602001820160405280156139b5578160200160208202803683370190505b50905060005b82811015612b75576000806139cf87613d7c565b5091509150818484815181106139e7576139e7614952565b6001600160a01b03909216602092830291909101909101528084613a0c856001615672565b81518110613a1c57613a1c614952565b60200260200101906001600160a01b031690816001600160a01b031681525050613a4587613db8565b965050508080613a549061570b565b9150506139bb565b6040516001600160a01b038316602482015260448101829052610e0790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613de9565b60408051608081018252838152306020820152808201839052600060608201819052915163b858183f60e01b81526001600160a01b0386169063b858183f906127a0908490600401615aad565b60606127e7838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250613ebe565b6001600160a01b0381163b613bbd5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610e54565b600080516020615b7783398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b613bf583613f9b565b600082511180613c025750805b15610e075761094a8383613fdb565b801580613c8b5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015613c65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c89919061554c565b155b613cf65760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610e54565b6040516001600160a01b038316602482015260448101829052610e0790849063095ea7b360e01b90606401613a88565b600054610100900460ff16613d4d5760405162461bcd60e51b8152600401610e54906159a9565b610f1c336132a8565b6000613d6460036014615672565b60148351613d72919061497e565b6117509190615afb565b60008080613d8a8482614000565b9250613d978460146140b4565b9050613daf613da860036014615672565b8590614000565b91509193909250565b6060611750613dc960036014615672565b613dd560036014615672565b8451613de1919061497e565b84919061415f565b6000613e3e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166142b69092919063ffffffff16565b9050805160001480613e5f575080806020019051810190613e5f9190615b1d565b610e075760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e54565b606082471015613f1f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610e54565b600080866001600160a01b03168587604051613f3b9190615b3a565b60006040518083038185875af1925050503d8060008114613f78576040519150601f19603f3d011682016040523d82523d6000602084013e613f7d565b606091505b5091509150613f8e878383876142c5565b925050505b949350505050565b613fa481613b50565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606127e78383604051806060016040528060278152602001615b976027913961433e565b60008161400e816014615672565b10156140515760405162461bcd60e51b8152602060048201526012602482015271746f416464726573735f6f766572666c6f7760701b6044820152606401610e54565b61405c826014615672565b835110156140a45760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b6044820152606401610e54565b500160200151600160601b900490565b6000816140c2816003615672565b10156141045760405162461bcd60e51b8152602060048201526011602482015270746f55696e7432345f6f766572666c6f7760781b6044820152606401610e54565b61410f826003615672565b835110156141565760405162461bcd60e51b8152602060048201526014602482015273746f55696e7432345f6f75744f66426f756e647360601b6044820152606401610e54565b50016003015190565b60608161416d81601f615672565b10156141ac5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610e54565b826141b78382615672565b10156141f65760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610e54565b6142008284615672565b845110156142445760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610e54565b6060821580156142635760405191506000825260208201604052612866565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561429c578051835260209283019201614284565b5050858452601f01601f1916604052505090509392505050565b6060613f938484600085613ebe565b6060831561433457825160000361432d576001600160a01b0385163b61432d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e54565b5081613f93565b613f9383836143b6565b6060600080856001600160a01b03168560405161435b9190615b3a565b600060405180830381855af49150503d8060008114614396576040519150601f19603f3d011682016040523d82523d6000602084013e61439b565b606091505b50915091506143ac868383876142c5565b9695505050505050565b8151156143c65781518083602001fd5b8060405162461bcd60e51b8152600401610e549190614719565b634e487b7160e01b600052600160045260246000fd5b60008083601f84011261440857600080fd5b5081356001600160401b0381111561441f57600080fd5b60208301915083602082850101111561443757600080fd5b9250929050565b60008060006040848603121561445357600080fd5b8335925060208401356001600160401b0381111561447057600080fd5b61447c868287016143f6565b9497909650939450505050565b6000606082840312156126d457600080fd5b6000602082840312156144ad57600080fd5b81356001600160401b038111156144c357600080fd5b613f9384828501614489565b6001600160a01b0381168114610ef157600080fd5b6000602082840312156144f657600080fd5b81356127e7816144cf565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561453957614539614501565b60405290565b604051601f8201601f191681016001600160401b038111828210171561456757614567614501565b604052919050565b60006001600160401b0382111561458857614588614501565b50601f01601f191660200190565b600080604083850312156145a957600080fd5b82356145b4816144cf565b915060208301356001600160401b038111156145cf57600080fd5b8301601f810185136145e057600080fd5b80356145f36145ee8261456f565b61453f565b81815286602083850101111561460857600080fd5b816020840160208301376000602083830101528093505050509250929050565b6000604082840312156126d457600080fd5b6000806040838503121561464d57600080fd5b8235915060208301356001600160401b0381111561466a57600080fd5b61467685828601614628565b9150509250929050565b6002811061469e57634e487b7160e01b600052602160045260246000fd5b9052565b602081016117508284614680565b6000602082840312156146c257600080fd5b5035919050565b60005b838110156146e45781810151838201526020016146cc565b50506000910152565b600081518084526147058160208601602086016146c9565b601f01601f19169290920160200192915050565b6020815260006127e760208301846146ed565b6000806020838503121561473f57600080fd5b82356001600160401b0381111561475557600080fd5b614761858286016143f6565b90969095509350505050565b6001600160a01b0383168152604060208201819052600090613f93908301846146ed565b8015158114610ef157600080fd5b600080604083850312156147b257600080fd5b82356147bd816144cf565b915060208301356147cd81614791565b809150509250929050565b6000606082840312156147ea57600080fd5b6127e78383614489565b6001600160a01b0384168152606060208201819052600090614818908301856146ed565b82810360408401526143ac81856146ed565b6000806040838503121561483d57600080fd5b8235614848816144cf565b915060208301356147cd816144cf565b600181811c9082168061486c57607f821691505b6020821081036126d457634e487b7160e01b600052602260045260246000fd5b60006001600160401b038211156148a5576148a5614501565b5060051b60200190565b600082601f8301126148c057600080fd5b815160206148d06145ee8361488c565b82815260059290921b840181019181810190868411156148ef57600080fd5b8286015b84811015614913578051614906816144cf565b83529183019183016148f3565b509695505050505050565b60006020828403121561493057600080fd5b81516001600160401b0381111561494657600080fd5b613f93848285016148af565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561175057611750614968565b6000608082840312156149a357600080fd5b604051608081018181106001600160401b03821117156149c5576149c5614501565b604052825161ffff811681146149da57600080fd5b808252506020830151602082015260408301516040820152606083015160608201528091505092915050565b80518252602081015160208301526000604082015160606040850152613f9360608501826146ed565b60008154614a3c81614858565b808552602060018381168015614a595760018114614a7357614aa1565b60ff1985168884015283151560051b880183019550614aa1565b866000528260002060005b85811015614a995781548a8201860152908301908401614a7e565b890184019650505b505050505092915050565b600061012061ffff8b16835289602084015288604084015260018060a01b03881660608401528660808401528560a08401528060c0840152614af081840186614a06565b905082810360e0840152614b048185614a2f565b8381036101009094019390935250506000815260200198975050505050505050565b6000806040808486031215614b3a57600080fd5b83516001600160401b0380821115614b5157600080fd5b818601915086601f830112614b6557600080fd5b81516020614b756145ee8361488c565b8281526060928302850182019282820191908b851115614b9457600080fd5b958301955b84871015614bdc5780878d031215614bb15760008081fd5b614bb9614517565b875181528488015185820152888801518982015283529586019591830191614b99565b5091890151919750909450505080831115614bf657600080fd5b5050614676858286016148af565b601f821115610e0757600081815260208120601f850160051c81016020861015614c2b5750805b601f850160051c820191505b81811015614c4a57828155600101614c37565b505050505050565b600019600383901b1c191660019190911b1790565b6001600160401b03831115614c7e57614c7e614501565b614c9283614c8c8354614858565b83614c04565b6000601f841160018114614cc05760008515614cae5750838201355b614cb88682614c52565b845550610d93565b600083815260209020601f19861690835b82811015614cf15786850135825560209485019460019092019101614cd1565b5086821015614d0e5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6000808335601e19843603018112614d3757600080fd5b83016020810192503590506001600160401b03811115614d5657600080fd5b80360382131561443757600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815260008235614d9f816144cf565b6001600160a01b0316602083810191909152614dbd90840184614d20565b60606040850152614dd2608085018284614d65565b915050614de26040850185614d20565b848303601f190160608601526143ac838284614d65565b80546001600160a01b0319166001600160a01b0392909216919091179055565b6000808335601e19843603018112614e3057600080fd5b8301803591506001600160401b03821115614e4a57600080fd5b60200191503681900382131561443757600080fd5b8135614e6a816144cf565b614e748183614df9565b5060018082016020614e8881860186614e19565b6001600160401b03811115614e9f57614e9f614501565b614eb381614ead8654614858565b86614c04565b6000601f821160018114614ee15760008315614ecf5750838201355b614ed98482614c52565b875550614f36565b600086815260209020601f19841690835b82811015614f0f5786850135825593870193908901908701614ef2565b5084821015614f2c5760001960f88660031b161c19848701351681555b50508683881b0186555b50505050505050614f4a6040830183614e19565b61094a818360028601614c67565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b60008135614ffd816144cf565b6001600160a01b031683526150156020830183614d20565b6040602086015261502a604086018284614d65565b95945050505050565b828152604060208201526000613f936040830184614ff0565b8135615057816144cf565b6150618183614df9565b506001808201602061507581860186614e19565b6001600160401b0381111561508c5761508c614501565b61509a81614ead8654614858565b6000601f8211600181146150c857600083156150b65750838201355b6150c08482614c52565b87555061511d565b600086815260209020601f19841690835b828110156150f657868501358255938701939089019087016150d9565b50848210156151135760001960f88660031b161c19848701351681555b50508683881b0186555b505050505050505050565b610fea828261504c565b6000602080838503121561514557600080fd5b82516001600160401b0381111561515b57600080fd5b8301601f8101851361516c57600080fd5b805161517a6145ee8261488c565b8181526060918202830184019184820191908884111561519957600080fd5b938501935b838510156151fe5780858a0312156151b65760008081fd5b6151be614517565b85516151c9816144cf565b8152858701516151d8816144cf565b818801526040868101516151eb81614791565b908201528352938401939185019161519e565b50979650505050505050565b600060a0820187835260208781850152604060a08186015282885180855260c087019150838a01945060005b8181101561527357855180516001600160a01b03908116855286820151168685015284015115158484015294840194606090920191600101615236565b50506001600160a01b0388166060870152935061528f92505050565b8260808301529695505050505050565b600060208083850312156152b257600080fd5b82516001600160401b038111156152c857600080fd5b8301601f810185136152d957600080fd5b80516152e76145ee8261488c565b81815260059190911b8201830190838101908783111561530657600080fd5b928401925b828410156153245783518252928401929084019061530b565b979650505050505050565b600081518084526020808501945080840160005b838110156153685781516001600160a01b031687529582019590820190600101615343565b509495945050505050565b85815284602082015260a06040820152600061539260a083018661532f565b6001600160a01b0394909416606083015250608001529392505050565b602081526000613f93602083018486614d65565b60006153d16145ee8461456f565b90508281528383830111156153e557600080fd5b6127e78360208301846146c9565b600082601f83011261540457600080fd5b6127e7838351602085016153c3565b60006020828403121561542557600080fd5b81516001600160401b038082111561543c57600080fd5b908301906040828603121561545057600080fd5b60405160408101818110838211171561546b5761546b614501565b60405282518281111561547d57600080fd5b615489878286016153f3565b82525060208301518281111561549e57600080fd5b6154aa878286016153f3565b60208301525095945050505050565b6080815260006154cc60808301876146ed565b82810360208401526154de8187614a2f565b905082810360408401526154f281866146ed565b91505082606083015295945050505050565b60006020828403121561551657600080fd5b81516001600160401b0381111561552c57600080fd5b8201601f8101841361553d57600080fd5b613f93848251602084016153c3565b60006020828403121561555e57600080fd5b5051919050565b813561557081614791565b815460ff19811691151560ff1691821783556020840135615590816144cf565b6001600160a81b03199190911690911760089190911b610100600160a81b03161781556040919091013560019190910155565b805160ff811681146155d457600080fd5b919050565b600060c082840312156155eb57600080fd5b60405160c081018181106001600160401b038211171561560d5761560d614501565b60405282518152615620602084016155c3565b6020820152615631604084016155c3565b60408201526060830151615644816144cf565b6060820152615655608084016155c3565b608082015261566660a084016155c3565b60a08201529392505050565b8082018082111561175057611750614968565b60006020828403121561569757600080fd5b815163ffffffff811681146127e757600080fd5b6000602082840312156156bd57600080fd5b81516001600160401b03811681146127e757600080fd5b600083516156e68184602088016146c9565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b60006001820161571d5761571d614968565b5060010190565b602081526000825160a0602084015261574060c08401826146ed565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b61ffff8516815260ff8416602082015260a0604082015260006157a260a08301856146ed565b82810380606085015260008252602081016080850152506153246020820185614a06565b600080604083850312156157d957600080fd5b505080516020909101519092909150565b60008083546157f881614858565b60018281168015615810576001811461582557615854565b60ff1984168752821515830287019450615854565b8760005260208060002060005b8581101561584b5781548a820152908401908201615832565b50505082870194505b50929695505050505050565b600081518084526020808501945080840160005b8381101561536857815187529582019590820190600101615874565b60006101208083016158a2848b614680565b60208481019290925288519081905261014080850192600583901b8601909101918a820160005b8281101561592c5787850361013f190186528151805186528481015185870152604080820151908701526060808201519087015260809081015160a091870182905290615918818801836146ed565b9786019796505050908301906001016158c9565b505050508381036040850152615942818961532f565b915050615982606084018780516001600160a01b039081168352602080830151151590840152604080830151909116908301526060908101511515910152565b82810360e08401526159948186615860565b91505082610100830152979650505050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b81516001600160401b03811115615a0d57615a0d614501565b615a2181615a1b8454614858565b84614c04565b602080601f831160018114615a505760008415615a3e5750858301515b615a488582614c52565b865550614c4a565b600085815260208120601f198616915b82811015615a7f57888601518255948401946001909101908401615a60565b5085821015615a9d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602081526000825160806020840152615ac960a08401826146ed565b905060018060a01b03602085015116604084015260408401516060840152606084015160808401528091505092915050565b600082615b1857634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215615b2f57600080fd5b81516127e781614791565b60008251615b4c8184602087016146c9565b919091019291505056fe48b87fc02925b37a6aefac60c14fa9d8e9988d7dfadf262d4bd845872ca40730360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202cf5d105cce700f83f307a3dd04f585ba73959a056059f2d16f4535b39853d2764736f6c63430008130033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.