Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw | 159853658 | 774 days ago | IN | 0 ETH | 0.00011019 |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
PolysynthBeefyVaultGLP
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.4;
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Beefy} from "../../libraries/Beefy.sol";
import {ShareMathBeefy} from "../../libraries/ShareMathBeefy.sol";
import {ExoticOracleInterface} from "../../interfaces/ExoticOracleInterface.sol";
import {PolysynthKikoVaultStorage} from "../../storage/PolysynthKikoVaultStorage.sol";
import {BeefyVault} from "./BeefyVault.sol";
import {IGlpRouter} from "../../interfaces/IGlpRouter.sol";
import {IBeefy} from "../../interfaces/IBeefy.sol";
import "hardhat/console.sol";
contract PolysynthBeefyVaultGLP is BeefyVault, PolysynthKikoVaultStorage {
using SafeERC20 for IERC20;
using SafeMath for uint256;
using ShareMathBeefy for Beefy.DepositReceipt;
IGlpRouter glpRouter;
address glpManager;
address usdcToken;
// Burnt shares for the current round
constructor(address _vault) BeefyVault(_vault) {}
function initialize(
address _owner,
address _keeper,
address _feeRecipent,
string memory _tokenName,
string memory _tokenSymbol,
Beefy.VaultParams calldata _vaultParams,
IGlpRouter _glpRouter,
address _token
) external initializer {
glpRouter = _glpRouter;
glpManager = glpRouter.glpManager();
usdcToken = _token;
baseInitialize(
_owner,
_keeper,
_feeRecipent,
_tokenName,
_tokenSymbol,
_vaultParams
);
}
modifier onlyObserver() {
require(msg.sender == observer, "!observer");
_;
}
function setGlpRewardRouter(address _glpRouter) external onlyOwner {
require(_glpRouter != address(0), "valid glp address");
glpRouter = IGlpRouter(_glpRouter);
glpManager = glpRouter.glpManager();
}
function setAuctionTime(uint256 _auctionTime) external onlyOwner {
require(_auctionTime != 0, "!_auctionTime");
auctionTime = _auctionTime;
}
function setObserver(address _newObserver) external onlyOwner {
require(_newObserver != address(0), "!_newObserver");
observer = _newObserver;
}
function setVaultPeriod(uint256 _vaultPeriod) external onlyOwner {
require(_vaultPeriod > 0, "!invalid");
vaultParams.vaultPeriod = _vaultPeriod;
}
// /**
// * @notice Initiates a withdrawal that can be processed once the round completes
// * @param numShares is the number of shares to withdraw
// */
// function initiateWithdraw(uint256 numShares) external nonReentrant {
// _initiateWithdraw(numShares);
// currentQueuedWithdrawShares = currentQueuedWithdrawShares.add(
// numShares
// );
// }
// /**
// * @notice Completes a scheduled withdrawal from a past round. Uses finalized pps for the round
// */
// function completeWithdraw() external nonReentrant {
// uint256 withdrawAmount = _completeWithdraw();
// lastQueuedWithdrawAmount = uint128(
// uint256(lastQueuedWithdrawAmount).sub(withdrawAmount)
// );
// }
/**
* @notice withdraw shares
* @param numShares is the number of shares to withdraw
*/
function withdraw(uint256 numShares) external nonReentrant {
// vaultState.burntAmount += uint128(_withdraw(numShares));
// vaultState.burntShares += uint128(numShares);
}
function close() external nonReentrant onlyKeeper {
// console.log("CLOSING ROUND %s PPS %s ", vaultState.round, pricePerShare());
// 1, Check if settlement is done by MM
// 2. Calculate PPS
require(optionState.isSettled || vaultState.round < 3, "Round closed");
Beefy.VaultResp memory vr;
// Old withdraw
// uint256 currQueuedWithdrawShares = currentQueuedWithdrawShares;
(vr.performanceFee, vr.managementFee, ) = _closeRound();
// lastQueuedWithdrawAmount = queuedWithdrawAmount;
vaultState.prevRoundAmount = vaultState.unlockedAmount;
vaultState.lockedAmount =
vaultState.lockedAmount +
vaultState.prevRoundAmount;
vaultState.unlockedAmount = 0;
IBeefy bv = IBeefy(BEEFY_VAULT);
vr.bps = bv.getPricePerFullShare();
vr.currMoobalance = bv.balanceOf(address(this));
vr.currentRound = vaultState.round;
vr.totalFee = vr.managementFee.add(vr.performanceFee);
console.log(
"Currbalance %s unlockedAmount %s settledAmount %s",
vr.currMoobalance,
vaultState.prevRoundAmount,
optionState.settledAmount
);
if (
vr.currMoobalance.add(vr.totalFee).add(
optionState.unSettledYield
) >=
uint256(vaultState.prevRoundAmount).add(
uint256(optionState.settledAmount)
)
) {
// deployed balance must not have settle amount | Add fees to retrieve previous vaultbalance
vr.deployedbalance = vr
.currMoobalance
.add(vr.totalFee)
.add(optionState.unSettledYield)
.sub(vaultState.prevRoundAmount)
.sub(optionState.settledAmount);
vr.lastRoundbps = optionState.beefyPPS;
//Set currrent round bps
optionState.beefyPPS = vr.bps;
// optionState.lockedAmount = currbalance;
uint256 accruedYield = vr.bps - vr.lastRoundbps;
vr.mooYieldShares = (accruedYield * vr.deployedbalance) / vr.bps;
console.log(
"BPS %s lastRoundbps %s mooYieldShares %s",
vr.bps,
vr.lastRoundbps,
vr.mooYieldShares
);
console.log(
"Deployedbalance %s lockedAmount %s settledAmount %s",
vr.deployedbalance,
vaultState.prevRoundAmount,
optionState.settledAmount
);
if (vr.currentRound > 2 && vr.mooYieldShares > 0) {
vr.glpYieldShares =
(vr.mooYieldShares * vr.bps) /
TOKEN_DECIMALS;
//get glp token from beefy vault by selling mooToken
bv.withdraw(vr.mooYieldShares);
console.log(
"MooYieldShares %s GlpYieldShares %s currbalance %s",
vr.mooYieldShares,
vr.glpYieldShares,
vr.currMoobalance
);
//Get USDC by selling GLP Token
uint256 usdcBalanceBefore = IERC20(usdcToken).balanceOf(
address(this)
);
_sellGlpToken(vr.glpYieldShares);
vr.currMoobalance = bv.balanceOf(address(this));
uint256 usdcBalanceAfter = IERC20(usdcToken).balanceOf(
address(this)
);
optionState.borrowAmount = (usdcBalanceAfter -
usdcBalanceBefore);
console.log(
"USDC %s currbalance %s",
optionState.borrowAmount,
vr.currMoobalance
);
}
} else {
optionState.borrowAmount = 0;
}
vaultState.burntShares = 0;
vaultState.burntAmount = 0;
optionState.unSettledYield = 0;
optionState.isSettled = false;
optionState.isBorrowed = false;
optionState.expiry = getNextExpiry();
emit InterestRedeem(
optionState.borrowAmount,
vr.mooYieldShares,
vr.glpYieldShares,
vr.deployedbalance,
vr.currentRound
);
}
function borrow() external nonReentrant {
if (optionState.borrowAmount > 0) {
require(!optionState.isBorrowed, "already borrowed");
require(msg.sender == borrower, "unauthorised");
transferAssetByAddress(
usdcToken,
payable(borrower),
optionState.borrowAmount
);
}
// Event for borrow amount
emit Borrow(borrower, optionState.borrowAmount, 0);
optionState.isBorrowed = true;
}
function settle(uint256 _amount) external nonReentrant {
require(msg.sender == borrower, "unauthorised");
}
function settleGlp() external nonReentrant {
uint256 prevBalance;
require(msg.sender == borrower, "unauthorised");
require(block.timestamp >= optionState.expiry, "early settle");
require(
!optionState.isSettled && optionState.isBorrowed,
"already settled"
);
uint256 amount = IERC20(vaultParams.asset).balanceOf(address(this));
require(amount > 0, "!amount");
IBeefy bv = IBeefy(BEEFY_VAULT);
IERC20(vaultParams.asset).approve(BEEFY_VAULT, amount);
prevBalance = IERC20(BEEFY_VAULT).balanceOf(address(this));
bv.deposit(amount);
optionState.settledAmount = IERC20(BEEFY_VAULT)
.balanceOf(address(this))
.sub(prevBalance);
optionState.settledAssetAmount = 0;
optionState.isSettled = true;
// Event for settle
emit Settle(
borrower,
optionState.couponAmount,
optionState.settledAssetAmount,
optionState.settledAmount
);
}
function accountBalance(address _account)
external
view
returns (
uint256 balance,
uint256 balanceA,
uint256 balanceB,
uint256 sharesBalance
)
{
return getAccountBalance(_account);
}
function _closeRound()
internal
returns (
uint256 performanceFeeInAsset,
uint256 managementFeeInAsset,
uint256 queuedWithdrawAmount
)
{
address recipient = feeRecipient;
uint256 mintShares;
uint256 totalVaultFee;
{
uint256 newPricePerShare;
uint256 currentBalance = IERC20(BEEFY_VAULT).balanceOf(
address(this)
);
uint256 pendingAmount = vaultState.prevRoundAmount +
vaultState.unlockedAmount;
uint256 currentShareSupply = totalSupply();
uint256 currentRound = vaultState.round;
uint256 balanceForVaultFees = currentBalance.sub(pendingAmount);
{
(
performanceFeeInAsset,
managementFeeInAsset,
totalVaultFee
) = getVaultFees(
balanceForVaultFees,
performanceFee,
managementFee
);
}
uint256 tempBalance = currentBalance.sub(totalVaultFee);
{
newPricePerShare = ShareMathBeefy.pricePerShare(
currentShareSupply.add(vaultState.burntShares), //shares withdrawn
tempBalance.add(vaultState.burntAmount), // burnt shares withdrawn
pendingAmount,
vaultParams.decimals
);
_settleUnAccountedYield(newPricePerShare);
// After closing the short, if the options expire in-the-money
// vault pricePerShare would go down because vault's asset balance decreased.
// This ensures that the newly-minted shares do not take on the loss.
mintShares = ShareMathBeefy.assetToShares(
vaultState.prevRoundAmount,
newPricePerShare,
vaultParams.decimals
);
}
// Finalize the pricePerShare at the end of the round
roundPricePerShare[currentRound] = newPricePerShare;
emit CollectVaultFees(
performanceFeeInAsset,
totalVaultFee,
currentRound,
recipient
);
// vaultState.totalPending = 0;
vaultState.round = uint16(currentRound + 1);
console.log(
"CLOSEEEE mintShares %s newPricePerShare %s ",
mintShares,
newPricePerShare
);
}
_mint(address(this), mintShares);
if (totalVaultFee > 0) {
transferAssetByAddress(
BEEFY_VAULT,
payable(feeRecipient),
totalVaultFee
);
}
return (performanceFeeInAsset, managementFeeInAsset, 0);
}
function _settleUnAccountedYield(uint256 newPricePerShare) internal {
uint256 withdrawAmountAtNewPPS = ShareMathBeefy.sharesToAsset(
vaultState.burntShares,
newPricePerShare,
vaultParams.decimals
);
optionState.unSettledYield = withdrawAmountAtNewPPS >
vaultState.burntAmount
? withdrawAmountAtNewPPS.sub(vaultState.burntAmount)
: 0;
console.log(
"CLOSEE withdrawAmountAtNewPPS %s withdrawAmount %s unAccountedyield",
withdrawAmountAtNewPPS,
vaultState.burntAmount,
optionState.unSettledYield
);
if (optionState.unSettledYield > 0) {
transferAssetByAddress(
BEEFY_VAULT,
payable(feeRecipient),
optionState.unSettledYield
);
}
}
function _buyGlpToken(uint256 _usdcAmount, uint256 _minGlpAmount) internal {
glpRouter.mintAndStakeGlp(usdcToken, _usdcAmount, 0, _minGlpAmount);
}
function _sellGlpToken(uint256 _glpAmount) internal {
glpRouter.unstakeAndRedeemGlp(usdcToken, _glpAmount, 0, address(this));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.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 anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing 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.7.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]
* ```
* 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. Equivalent to `reinitializer(1)`.
*/
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.
*
* `initializer` is equivalent to `reinitializer(1)`, so 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.
*
* 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.
*/
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.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @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.7.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20Upgradeable.sol";
import "./extensions/IERC20MetadataUpgradeable.sol";
import "../../utils/ContextUpgradeable.sol";
import "../../proxy/utils/Initializable.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.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* 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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {
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}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
_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 value {ERC20} uses, unless this function is
* 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;
}
_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;
_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;
}
_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 {}
/**
* @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[45] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20Upgradeable.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20MetadataUpgradeable is IERC20Upgradeable {
/**
* @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.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @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.7.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
* ====
*
* [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://diligence.consensys.net/posts/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.5.11/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 functionCall(target, data, "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");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(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) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason 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 {
// 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 v4.4.1 (token/ERC20/extensions/draft-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.6.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.7.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-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;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @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));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @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");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.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
* ====
*
* [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://diligence.consensys.net/posts/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.5.11/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 functionCall(target, data, "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");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(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) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(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) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason 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 {
// 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 (last updated v4.6.0) (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity =0.8.4;
interface ExoticOracleInterface {
function getExpiryPrice(address _asset, uint256 _expiryTimestamp) external view returns (uint256, bool);
function getHistoricalPrice(address _asset, uint80 _roundId) external view returns (uint256, uint256);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity =0.8.4;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IBeefy is IERC20 {
function deposit(uint256) external;
function depositAll() external;
function withdraw(uint256) external;
function withdrawAll() external;
function getPricePerFullShare() external view returns (uint256);
function upgradeStrat() external;
function balance() external view returns (uint256);
function want() external view returns (IERC20);
}// SPDX-License-Identifier: MIT
pragma solidity =0.8.4;
interface IGlpRouter {
function mintAndStakeGlp(address _token, uint256 _amount, uint256 _minUsdg, uint256 _minGlp) external returns (uint256);
function unstakeAndRedeemGlp(address _tokenOut, uint256 _glpAmount, uint256 _minOut, address _receiver) external returns (uint256);
function glpManager() external returns (address);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.4;
library Beefy {
/************************************************
* IMMUTABLES & CONSTANTS
***********************************************/
// Fees are 6-decimal places. For example: 20 * 10**6 = 20%
uint256 internal constant FEE_MULTIPLIER = 10**6;
uint256 internal constant RATIO_MULTIPLIER = 10**4;
// Placeholder uint value to prevent cold writes
uint256 internal constant PLACEHOLDER_UINT = 1;
struct VaultParams {
// Token decimals for vault shares
uint8 decimals;
// Asset used in Kiko Vault
address asset;
// Beefy vault address
address beefyVault;
// Minimum supply of the vault shares issued, for ETH it's 10**10
uint56 minimumSupply;
// Vault cap
uint104 cap;
// Vault lifecycle duration in seconds
uint256 vaultPeriod;
}
struct VaultState {
// 32 byte slot 1
// Current round number. `round` represents the number of `period`s elapsed.
uint16 round;
// Amount that is currently locked for selling options
uint104 lockedAmount;
// Amount that is currently unlocked for yield farming
uint104 unlockedAmount;
// Amount that is currently unlocked for previous yield farming
uint104 prevRoundAmount;
// Amount that was locked for selling options in the previous round
// used for calculating performance fee deduction
uint104 lastLockedAmount;
// 32 byte slot 2
// Stores the total tally of how much of `asset` there is
// to be used to mint rKIKO tokens
uint128 totalPending;
uint128 burntShares;
uint128 burntAmount;
}
struct OptionState {
// Amount that is currently locked in beefy vault for selling options
uint256 lockedAmount;
// USDC Amount that is currently available for borrowing from vault
uint256 borrowAmount;
// USDC Amount that is currently settled
uint256 couponAmount;
// Asset Amount that is currently settled
uint256 settledAssetAmount;
// Total amount settled in beefy token
uint256 settledAmount;
// un settled yiedl due to pre mature withdraw
uint256 unSettledYield;
// Last recorded PPS of the beefy vault
uint256 beefyPPS;
// Expiry of the current round
uint256 expiry;
// settled of the current round
bool isSettled;
// borrowed of the current round
bool isBorrowed;
// Timestamp at the time of last observation
uint256 lastObservation;
}
struct DepositReceipt {
// Maximum of 65535 rounds. Assuming 1 round is 7 days, maximum is 1256 years.
uint16 round;
// Deposit amount, max 20,282,409,603,651 or 20 trillion ETH deposit
uint104 amount;
// Maximum of 65535 rounds. Assuming 1 round is 7 days, maximum is 1256 years.
uint16 roundB;
// Deposit amount, max 20,282,409,603,651 or 20 trillion ETH deposit
uint104 amountB;
// Unredeemed shares balance
uint128 unredeemedShares;
}
struct Withdrawal {
// Maximum of 65535 rounds. Assuming 1 round is 7 days, maximum is 1256 years.
uint16 round;
// Number of shares withdrawn
uint128 shares;
}
struct VaultResp {
uint256 pps;
uint256 bps;
uint16 currentRound;
uint256 currMoobalance;
uint256 lastRoundbps;
uint256 nexRoundPPS;
uint256 deployedbalance;
uint256 accruedYield;
uint256 mooYieldShares;
uint256 glpYieldShares;
uint256 totalFee;
uint256 managementFee;
uint256 performanceFee;
}
}// SPDX-License-Identifier: MIT
pragma solidity =0.8.4;
import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol";
import {Beefy} from "./Beefy.sol";
import "hardhat/console.sol";
library ShareMathBeefy {
using SafeMath for uint256;
uint256 internal constant PLACEHOLDER_UINT = 1;
function assetToShares(
uint256 assetAmount,
uint256 assetPerShare,
uint256 decimals
) internal pure returns (uint256) {
// If this throws, it means that vault's roundPricePerShare[currentRound] has not been set yet
// which should never happen.
// Has to be larger than 1 because `1` is used in `initRoundPricePerShares` to prevent cold writes.
require(assetPerShare > PLACEHOLDER_UINT, "Invalid assetPerShare");
return assetAmount.mul(10**decimals).div(assetPerShare);
}
function sharesToAsset(
uint256 shares,
uint256 assetPerShare,
uint256 decimals
) internal pure returns (uint256) {
// If this throws, it means that vault's roundPricePerShare[currentRound] has not been set yet
// which should never happen.
// Has to be larger than 1 because `1` is used in `initRoundPricePerShares` to prevent cold writes.
require(assetPerShare > PLACEHOLDER_UINT, "Invalid assetPerShare");
return shares.mul(assetPerShare).div(10**decimals);
}
/**
* @notice Returns the shares unredeemed by the user given their DepositReceipt
* @param depositReceipt is the user's deposit receipt
* @param currentRound is the `round` stored on the vault
* @param assetPerShare is the price in asset per share
* @param decimals is the number of decimals the asset/shares use
* @return unredeemedShares is the user's virtual balance of shares that are owed
*/
function getSharesFromReceipt(
Beefy.DepositReceipt memory depositReceipt,
uint256 currentRound,
uint256 assetPerShare,
uint256 assetPerShareB,
uint256 decimals
) internal view returns (uint256 unredeemedShares) {
uint256 sharesFromRound;
//Calculate PartA shares
if (depositReceipt.round > 0 && depositReceipt.round < (currentRound-1)) {
sharesFromRound =
assetToShares(depositReceipt.amount, assetPerShare, decimals);
}
//Calculate PartB shares
if (depositReceipt.roundB > 0 && depositReceipt.roundB < (currentRound-1)) {
sharesFromRound +=
assetToShares(depositReceipt.amountB, assetPerShareB, decimals);
}
return uint256(depositReceipt.unredeemedShares).add(sharesFromRound);
}
function pricePerShare(
uint256 totalSupply,
uint256 totalBalance,
uint256 pendingAmount,
uint256 decimals
) internal view returns (uint256) {
uint256 singleShare = 10**decimals;
return
totalSupply > 0
? singleShare.mul(totalBalance.sub(pendingAmount)).div(
totalSupply
)
: singleShare;
}
/************************************************
* HELPERS
***********************************************/
function assertUint104(uint256 num) internal pure {
require(num <= type(uint104).max, "Overflow uint104");
}
function assertUint128(uint256 num) internal pure {
require(num <= type(uint128).max, "Overflow uint128");
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.4;
abstract contract PolysynthKikoVaultStorageV1 {
// Amount locked for scheduled withdrawals last week;
uint256 public lastQueuedWithdrawAmount;
// Queued withdraw shares for the current round
uint256 public currentQueuedWithdrawShares;
}
abstract contract PolysynthKikoVaultStorageV2 {
// Auction time in seconds from 12AM UTC
uint256 public auctionTime;
}
abstract contract PolysynthKikoVaultStorageV3 {
// Role for observing the price from defender
address public observer;
}
// We are following Compound's method of upgrading new contract implementations
// When we need to add new storage variables, we create a new version of RibbonDeltaVaultStorage
// e.g. RibbonDeltaVaultStorage<versionNumber>, so finally it would look like
// contract RibbonDeltaVaultStorage is RibbonDeltaVaultStorageV1, RibbonDeltaVaultStorageV2
abstract contract PolysynthKikoVaultStorage is
PolysynthKikoVaultStorageV1,
PolysynthKikoVaultStorageV2,
PolysynthKikoVaultStorageV3
{
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.4;
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Beefy} from "../../libraries/Beefy.sol";
import {ShareMathBeefy} from "../../libraries/ShareMathBeefy.sol";
import {ExoticOracleInterface} from "../../interfaces/ExoticOracleInterface.sol";
import {IBeefy} from "../../interfaces/IBeefy.sol";
import "hardhat/console.sol";
contract BeefyVault is
ReentrancyGuardUpgradeable,
OwnableUpgradeable,
ERC20Upgradeable
{
using SafeERC20 for IERC20;
using SafeMath for uint256;
using ShareMathBeefy for Beefy.DepositReceipt;
/************************************************
* NON UPGRADEABLE STORAGE
***********************************************/
/// @notice Stores the user's pending deposit for the round
mapping(address => Beefy.DepositReceipt) public depositReceipts;
/// @notice On every round's close, the pricePerShare value of an rTHETA token is stored
/// This is used to determine the number of shares to be returned
/// to a user with their DepositReceipt.depositAmount
mapping(uint256 => uint256) public roundPricePerShare;
/// @notice Stores pending user withdrawals
mapping(address => Beefy.Withdrawal) public withdrawals;
/// @notice Stores the strike prices of the assets
mapping(address => uint256) public assetStrikePrices;
/// @notice Vault's parameters like cap, decimals
Beefy.VaultParams public vaultParams;
/// @notice Vault's lifecycle state like round and locked amounts
Beefy.VaultState public vaultState;
/// @notice Vault's state of the options sold and the timelocked option
Beefy.OptionState public optionState;
/// @notice Fee recipient for the performance and management fees
address public feeRecipient;
/// @notice MM that won the auction
address public borrower;
/// @notice role in charge of weekly vault operations such as rollToNextOption and burnRemainingOTokens
// no access to critical vault changes
address public keeper;
/// @notice Performance fee charged on premiums earned in rollToNextOption. Only charged when there is no loss.
uint256 public performanceFee;
/// @notice Management fee charged on entire AUM in rollToNextOption. Only charged when there is no loss.
uint256 public managementFee;
// Gap is left to avoid storage collisions. Though PolysynthVault is not upgradeable, we add this as a safety measure.
uint256[30] private ____gap;
// *IMPORTANT* NO NEW STORAGE VARIABLES SHOULD BE ADDED HERE
// This is to prevent storage collisions. All storage variables should be appended to PolysynthThetaVaultStorage
// or PolysynthDeltaVaultStorage instead. Read this documentation to learn more:
// https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#modifying-your-contracts
/************************************************
* IMMUTABLES & CONSTANTS
***********************************************/
address public immutable BEEFY_VAULT;
// /// @notice 30 day period between each options sale.
// uint256 public constant PERIOD = 30 days;
// Number of weeks per year = 52.142857 weeks * FEE_MULTIPLIER = 52142857
// Dividing by weeks per year requires doing num.mul(FEE_MULTIPLIER).div(WEEKS_PER_YEAR)
// uint256 private constant DAYS_PER_YEAR = 365000000;
uint256 private constant WEEKS_PER_YEAR = 52142857;
uint256 public constant TOKEN_DECIMALS = 10**18;
/************************************************
* EVENTS
***********************************************/
event Deposit(address indexed account, uint256 amount, uint256 round);
event InitiateWithdraw(
address indexed account,
uint256 shares,
uint256 round
);
event Redeem(address indexed account, uint256 share, uint256 round);
event ManagementFeeSet(uint256 managementFee, uint256 newManagementFee);
event PerformanceFeeSet(uint256 performanceFee, uint256 newPerformanceFee);
event CapSet(uint256 oldCap, uint256 newCap);
event Withdraw(address indexed account, uint256 amount, uint256 shares);
event InstantWithdraw(
address indexed account,
uint256 amount,
uint256 round
);
event CollectVaultFees(
uint256 performanceFee,
uint256 vaultFee,
uint256 round,
address indexed feeRecipient
);
event Borrow(address indexed account, uint256 amount, uint256 rate);
event Settle(
address indexed account,
uint256 couponAmount,
uint256 assetAmount,
uint256 settledAmount
);
event Observe(
uint256 observeTime,
bool hasKO,
bool hasKI,
uint16 activeDays
);
event InterestRedeem(
uint256 amount,
uint256 mooQuantity,
uint256 glpQuantity,
uint256 deployedBalance,
uint256 round
);
/************************************************
* CONSTRUCTOR & INITIALIZATION
***********************************************/
// /**
// * @notice Initializes the contract with immutable variables
// * @param _weth is the Wrapped Ether contract
// */
constructor(
address _vault
) {
require(_vault != address(0), "!_vault");
BEEFY_VAULT = _vault;
// auctionTime = 13 hours;
}
function baseInitialize(
address _owner,
address _keeper,
address _feeRecipent,
string memory _tokenName,
string memory _tokenSymbol,
Beefy.VaultParams calldata _vaultParams
) internal initializer {
__ReentrancyGuard_init();
__ERC20_init(_tokenName, _tokenSymbol);
__Ownable_init();
transferOwnership(_owner);
keeper = _keeper;
feeRecipient = _feeRecipent;
vaultParams = _vaultParams;
uint256 assetBalance =
IERC20(vaultParams.asset).balanceOf(address(this));
ShareMathBeefy.assertUint104(assetBalance);
vaultState.lastLockedAmount = uint104(assetBalance);
vaultState.round = 1;
}
/**
* @dev Throws if called by any account other than the keeper.
*/
modifier onlyKeeper() {
require(msg.sender == keeper, "!keeper");
_;
}
/************************************************
* SETTERS
***********************************************/
/**
* @notice Sets the new keeper
* @param newKeeper is the address of the new keeper
*/
function setNewKeeper(address newKeeper) external onlyOwner {
require(newKeeper != address(0), "!newKeeper");
keeper = newKeeper;
}
/**
* @notice Sets the new fee recipient
* @param newFeeRecipient is the address of the new fee recipient
*/
function setFeeRecipient(address newFeeRecipient) external onlyOwner {
require(newFeeRecipient != address(0), "!newFeeRecipient");
require(newFeeRecipient != feeRecipient, "Must be new feeRecipient");
feeRecipient = newFeeRecipient;
}
/**
* @notice Sets the management fee for the vault
* @param newManagementFee is the management fee (6 decimals). ex: 2 * 10 ** 6 = 2%
*/
function setManagementFee(uint256 newManagementFee) external onlyOwner {
require(
newManagementFee < 100 * Beefy.FEE_MULTIPLIER,
"Invalid management fee"
);
// We are dividing annualized management fee by num weeks in a year
uint256 tmpManagementFee =
newManagementFee.mul(Beefy.FEE_MULTIPLIER).div(WEEKS_PER_YEAR);
emit ManagementFeeSet(managementFee, newManagementFee);
managementFee = tmpManagementFee;
}
/**
* @notice Sets the performance fee for the vault
* @param newPerformanceFee is the performance fee (6 decimals). ex: 20 * 10 ** 6 = 20%
*/
function setPerformanceFee(uint256 newPerformanceFee) external onlyOwner {
require(
newPerformanceFee < 100 * Beefy.FEE_MULTIPLIER,
"Invalid performance fee"
);
emit PerformanceFeeSet(performanceFee, newPerformanceFee);
performanceFee = newPerformanceFee;
}
/**
* @notice Sets a new cap for deposits
* @param newCap is the new cap for deposits
*/
function setCap(uint256 newCap) external onlyOwner {
require(newCap > 0, "!newCap");
ShareMathBeefy.assertUint104(newCap);
emit CapSet(vaultParams.cap, newCap);
vaultParams.cap = uint104(newCap);
}
function setBorrower(address _borrower) external onlyOwner {
require(_borrower != address(0), "!_borrower");
borrower = _borrower;
}
function updateExpiry(uint256 _expiry) external onlyOwner {
require(_expiry != 0, "!_expiry");
optionState.expiry = _expiry;
}
function updateLastOb() external onlyOwner {
optionState.lastObservation = 0;
}
/************************************************
* DEPOSIT & WITHDRAWALS
***********************************************/
/**
* @notice Deposits ETH into the contract and mint vault shares. Reverts if the asset is not WETH.
*/
// function depositETH() external payable nonReentrant {
// require(vaultParams.asset == WETH, "!WETH");
// require(msg.value > 0, "!value");
// _depositFor(msg.value, msg.sender);
// IWETH(WETH).deposit{value: msg.value}();
// }
/**
* @notice Deposits the `asset` from msg.sender.
* @param amount is the amount of `asset` to deposit
*/
function deposit(uint256 amount) external nonReentrant {
require(amount > 0, "!amount");
// An approve() by the msg.sender is required beforehand
IERC20(vaultParams.asset).safeTransferFrom(
msg.sender,
address(this),
amount
);
IBeefy bv = IBeefy(BEEFY_VAULT);
// This should be balance of mooTokens held by vault
uint256 prevBalance = IERC20(BEEFY_VAULT).balanceOf(address(this));
IERC20(vaultParams.asset).approve(BEEFY_VAULT, amount);
bv.deposit(amount);
uint256 afterBalance = IERC20(BEEFY_VAULT).balanceOf(address(this));
uint256 newTokensReceived = afterBalance.sub(prevBalance);
// The following amount should be the amount of
// mooTokens received, this can be checked through
// (current balance - prev balance), if mooToken amount
// is not returned
_depositFor(newTokensReceived, msg.sender);
console.log("DEPOSITTT BPS %s newTokensReceived %s block", bv.getPricePerFullShare(), newTokensReceived, block.number);
}
function getAccountBalance(address _account) internal view
returns(uint256 amount, uint256 amountA, uint256 amountB, uint256 sharesAmount) {
int16 currentRound = int16(vaultState.round);
Beefy.DepositReceipt storage depositReceipt = depositReceipts[_account];
amountA = (int16(depositReceipt.round) > (currentRound - 2) ? depositReceipt.amount : 0);
amountB = (int16(depositReceipt.roundB) > (currentRound - 2) ? depositReceipt.amountB : 0);
(uint256 heldByAccount, uint256 heldByVault) = shareBalances(_account);
sharesAmount =
ShareMathBeefy.sharesToAsset(
heldByAccount.add(heldByVault),
pricePerShare(),
vaultParams.decimals
);
amount = amountA.add(amountB).add(sharesAmount);
return (amount, amountA, amountB, sharesAmount);
}
/**
* @notice Withdraws the assets on the vault using the outstanding `DepositReceipt.amount`
* @param amount is the amount to withdraw
*/
function withdrawInstantly(uint256 amount) external nonReentrant {
uint256 receiptAmount;
uint256 deductedFromLocked;
uint256 deductedFromUnLocked;
uint256 deductAmount;
uint256 balanceA;
uint256 balanceB;
uint256 sharesBalance;
uint256 accountbal;
uint256 mooTokenAmount;
int16 currentRound = int16(vaultState.round);
require(
currentRound == 0,
"funds will be released after internal audit"
);
Beefy.DepositReceipt storage depositReceipt =
depositReceipts[msg.sender];
// balanceA = (int16(depositReceipt.round) > (currentRound - 2) ? depositReceipt.amount : 0);
// balanceB = (int16(depositReceipt.roundB) > (currentRound - 2) ? depositReceipt.amountB : 0);
(accountbal, balanceA, balanceB, sharesBalance) = getAccountBalance(msg.sender);
require(accountbal >= amount, "!balanceAmount");
mooTokenAmount = amount;
if(balanceB > 0){
deductAmount = balanceB > amount ? amount : balanceB;
(depositReceipt.roundB == vaultState.round) ?
deductedFromUnLocked += deductAmount : deductedFromLocked += deductAmount;
depositReceipt.amountB = uint104(uint256(depositReceipt.amountB).sub(deductAmount));
receiptAmount += deductAmount;
}
if(amount > receiptAmount && balanceA > 0){
deductAmount = balanceA > (amount - receiptAmount) ? (amount - receiptAmount) : balanceA;
(depositReceipt.round == vaultState.round) ?
deductedFromUnLocked += deductAmount : deductedFromLocked += deductAmount;
depositReceipt.amount = uint104(uint256(depositReceipt.amount).sub(deductAmount));
receiptAmount += deductAmount;
}
if(amount > receiptAmount){
deductAmount = amount - receiptAmount;
uint256 sharesWithdraw = ShareMathBeefy.assetToShares(
deductAmount,
pricePerShare(),
vaultParams.decimals
);
(uint256 heldByAccount, uint256 heldByVault) = shareBalances(msg.sender);
uint256 totalShares = heldByAccount.add(heldByVault);
if (totalShares == sharesWithdraw + 1){
sharesWithdraw += 1; //To adjust dust
}else if (totalShares == sharesWithdraw - 1){
sharesWithdraw -= 1; //To adjust dust
}
console.log("WWITHDRAWWWW deductAmount %s sharesWithdraw" , deductAmount, sharesWithdraw);
_withdraw(sharesWithdraw);
vaultState.burntShares += uint128(sharesWithdraw);
vaultState.burntAmount += uint128(deductAmount);
receiptAmount += deductAmount;
mooTokenAmount -= deductAmount;
}
require(receiptAmount == amount, "!amount");
vaultState.unlockedAmount = uint104(
uint256(vaultState.unlockedAmount).sub(deductedFromUnLocked)
);
if (vaultState.round > 1){
vaultState.prevRoundAmount = uint104(
uint256(vaultState.prevRoundAmount).sub(deductedFromLocked)
);
vaultState.lockedAmount = uint104(
uint256(vaultState.lockedAmount).sub(deductedFromLocked)
);
}
if(mooTokenAmount > 0){
IBeefy bv = IBeefy(BEEFY_VAULT);
// bv.approve(BEEFY_VAULT, amount);
uint256 prevBalance = IERC20(vaultParams.asset).balanceOf(address(this));
bv.withdraw(mooTokenAmount);
uint256 afterBalance = IERC20(vaultParams.asset).balanceOf(address(this));
uint256 assetReceived = afterBalance.sub(prevBalance);
transferAsset(msg.sender, assetReceived);
console.log("INSTANTT BPS", bv.getPricePerFullShare());
emit InstantWithdraw(msg.sender, mooTokenAmount, vaultState.round);
}
}
// /**
// * @notice Deposits the `asset` from msg.sender added to `creditor`'s deposit.
// * @notice Used for vault -> vault deposits on the user's behalf
// * @param amount is the amount of `asset` to deposit
// * @param creditor is the address that can claim/withdraw deposited amount
// */
// function depositFor(uint256 amount, address creditor)
// external
// nonReentrant
// {
// require(amount > 0, "!amount");
// require(creditor != address(0));
// _depositFor(amount, creditor);
// // An approve() by the msg.sender is required beforehand
// IERC20(vaultParams.asset).safeTransferFrom(
// msg.sender,
// address(this),
// amount
// );
// }
/************************************************
* POOL OPERATIONS
***********************************************/
// function _observe() internal {
// require(!optionState.hasKnockedOut, "already knocked out");
// // For the last day, vaultActiveDays is checked so that vault active days can go upto 30 instead of 29
// require(optionState.expiry > optionState.lastObservation, "vault expired");
// uint256 observeHour = (block.timestamp / 1 hours) % 24;
// require(observeHour>=8, "observe after 8AM UTC");
// uint256 observeTime = block.timestamp - (block.timestamp % (1 days)) + (8 hours);
// if (observeTime > optionState.expiry) {
// observeTime = optionState.expiry;
// }
// for (uint8 i = 0; i < vaultParams.basketSize; i++) {
// uint256 assetExpiryPrice = getExpiryPrice(vaultParams.underlyings[i], observeTime);
// require(assetExpiryPrice > 0, "observation price 0");
// uint256 upperLimit = assetStrikePrices[vaultParams.underlyings[i]].mul(vaultParams.koBar).div(Beefy.RATIO_MULTIPLIER);
// if (assetExpiryPrice >= upperLimit) {
// optionState.hasKnockedOut = true;
// optionState.koTime = observeTime;
// continue;
// }
// uint256 lowerLimit = assetStrikePrices[vaultParams.underlyings[i]].mul(vaultParams.kiBar).div(Beefy.RATIO_MULTIPLIER);
// if (assetExpiryPrice <= lowerLimit) {
// optionState.hasKnockedIn = true;
// }
// }
// // Employ a way to observe weekly
// // vaultActiveDays will need to be updated
// // according to the number of days passed
// // The following logic will also ensure that
// // even if the observe method is called multiple times
// // throughout the day, it won't increase vaultActiveDays
// uint256 currentActiveDays = (observeTime - optionState.lastObservation) / (1 days);
// if (optionState.lastObservation == 0) {
// currentActiveDays = 1;
// }
// optionState.vaultActiveDays += uint16(currentActiveDays);
// optionState.lastObservation = observeTime;
// emit Observe(
// observeTime,
// optionState.hasKnockedOut,
// optionState.hasKnockedIn,
// optionState.vaultActiveDays
// );
// }
// function borrow() external nonReentrant {
// require(!optionState.isBorrowed,"already borrowed");
// require(msg.sender == borrower, "unauthorised");
// uint256 borrowAmount = uint256(vaultState.lockedAmount).mul(optionState.borrowRate).div(Beefy.RATIO_MULTIPLIER);
// if (borrowAmount > 0) {
// transferAsset(msg.sender, borrowAmount);
// }
// // Event for borrow amount
// emit Borrow(borrower, borrowAmount, optionState.borrowRate);
// optionState.isBorrowed = true;
// }
// function settle() external nonReentrant {
// require(block.timestamp>=optionState.expiry || optionState.hasKnockedOut, "early settle");
// require(!optionState.isSettled,"already settled");
// require(optionState.isBorrowed,"not yet borrowed");
// require(msg.sender == borrower, "unauthorised");
// (uint256 borrowedAmount, uint256 couponAmount, uint256 lossAmount) = _settleAmounts();
// uint256 netReturn = borrowedAmount.add(couponAmount);
// if (netReturn > lossAmount) {
// // An approve() by the msg.sender is required beforehand
// IERC20(vaultParams.asset).safeTransferFrom(
// msg.sender,
// address(this),
// netReturn.sub(lossAmount)
// );
// } else {
// transferAsset(borrower, lossAmount.sub(netReturn));
// }
// optionState.isSettled = true;
// // Event for settle
// emit Settle(borrower, netReturn, lossAmount, couponAmount);
// }
//Dummy function to get price of asset at 8AM everyday
//TODO: Change this and get BIFI PPS here
function getExpiryPrice(address _asset, uint256 _expiryTimestamp) internal view returns (uint256) {
// ExoticOracleInterface oracle = ExoticOracleInterface(ORACLE);
// (uint256 price, )= oracle.getExpiryPrice(_asset, _expiryTimestamp);
return 0;
}
// function updateVaultRates(uint256 _cr, uint256 _br) external onlyKeeper{
// require(_cr != 0, "!_cr");
// require(_cr != 0, "!_br");
// optionState.couponRate = _cr;
// optionState.borrowRate = _br;
// }
/************************************************
* INTERNAL OPERATIONS
***********************************************/
// function _settleAmounts() internal view returns (uint256, uint256, uint256){
// uint256 borrowedAmount = uint256(vaultState.lockedAmount).mul(optionState.borrowRate).div(Beefy.RATIO_MULTIPLIER);
// uint256 couponAmount = uint256(vaultState.lockedAmount)
// .mul(optionState.couponRate * optionState.vaultActiveDays)
// .div(28*Beefy.RATIO_MULTIPLIER);
// uint256 lossAmount;
// uint256 observeTime = optionState.hasKnockedOut ? optionState.koTime : optionState.expiry;
// if (optionState.hasKnockedIn) {
// for (uint8 i = 0; i < vaultParams.basketSize; i++) {
// uint256 assetExpiryPrice = getExpiryPrice(vaultParams.underlyings[i], observeTime);
// uint256 assetStrikePrice = assetStrikePrices[vaultParams.underlyings[i]];
// if (assetExpiryPrice >= assetStrikePrice) {
// continue;
// }
// uint256 lossAmountTemp = assetStrikePrice
// .sub(assetExpiryPrice)
// .mul(vaultState.lockedAmount)
// .div(assetStrikePrice);
// lossAmount = lossAmountTemp > lossAmount ? lossAmountTemp : lossAmount;
// }
// }
// return (borrowedAmount, couponAmount, lossAmount);
// }
/**
* @notice Mints the vault shares to the creditor
* @param amount is the amount of `asset` deposited
* @param creditor is the address to receieve the deposit
*/
function _depositFor(uint256 amount, address creditor) private {
uint256 currentRound = vaultState.round;
uint256 totalWithDepositedAmount = totalBalance().add(amount);
require(totalWithDepositedAmount <= vaultParams.cap, "Exceed cap");
require(
totalWithDepositedAmount >= vaultParams.minimumSupply,
"Insufficient balance"
);
emit Deposit(creditor, amount, currentRound);
Beefy.DepositReceipt memory depositReceipt = depositReceipts[creditor];
// If we have an unprocessed pending deposit from the previous rounds, we have to process it.
// User redeems as per locked round
// For Round 1 capital will be locked in round 2 and deployed in round 3\
// Vault shares will be minted as per round 2 pps.
// Similarly shares will allocated to user using same PPS.
uint256 unredeemedShares =
depositReceipt.getSharesFromReceipt(
currentRound,
roundPricePerShare[depositReceipt.round+1],
roundPricePerShare[depositReceipt.roundB+1],
vaultParams.decimals
);
uint256 depositAmount = amount;
// If we have a pending deposit in the current round, we add on to the pending deposit
if (currentRound == depositReceipt.round) {
uint256 newAmount = uint256(depositReceipt.amount).add(amount);
depositAmount = newAmount;
}else if(currentRound == depositReceipt.roundB){
uint256 newAmount = uint256(depositReceipt.amountB).add(amount);
depositAmount = newAmount;
}
ShareMathBeefy.assertUint104(depositAmount);
Beefy.DepositReceipt memory receipt = depositReceipts[creditor];
receipt.unredeemedShares = uint128(unredeemedShares);
if ((receipt.round == 0) || //To manage first deposit
receipt.round == currentRound || //To manage deposit in same roundA
currentRound > 2 && (
(receipt.roundB == 0 && receipt.round < (currentRound - 1)) || //To manage deposit (Round 1 & 4) older than n-1 rounds
(receipt.roundB != 0 && receipt.roundB < (currentRound - 1)) //To manage deposit (Round 1,2 & 4) older than n-1 rounds
)
)
{
receipt.round = uint16(currentRound);
receipt.amount = uint104(depositAmount);
receipt.roundB = 0;
receipt.amountB = 0;
}else if (receipt.roundB == 0 ||
receipt.roundB == currentRound){ //To manage deposit in next round & same deposit in roundB
receipt.roundB = uint16(currentRound);
receipt.amountB = uint104(depositAmount);
}else{ //To manage deposit in serial rounds
receipt.round = receipt.roundB;
receipt.amount = receipt.amountB;
receipt.roundB = uint16(currentRound);
receipt.amountB = uint104(depositAmount);
}
depositReceipts[creditor] = receipt;
uint256 newUnlockedAmount = uint256(vaultState.unlockedAmount).add(amount);
ShareMathBeefy.assertUint104(newUnlockedAmount);
vaultState.unlockedAmount = uint104(newUnlockedAmount);
}
/**
* @notice Completes a scheduled withdrawal from a past round. Uses finalized pps for the round
* @return withdrawAmount the current withdrawal amount
*/
function _withdraw(uint256 numShares) internal returns (uint256) {
require(numShares > 0, "!numShares");
// We do a max redeem before initiating a withdrawal
// But we check if they must first have unredeemed shares
if (
depositReceipts[msg.sender].amount > 0 ||
depositReceipts[msg.sender].amountB > 0 ||
depositReceipts[msg.sender].unredeemedShares > 0
) {
_redeem(0, true);
}
ShareMathBeefy.assertUint128(numShares);
withdrawals[msg.sender].shares = uint128(numShares);
_transfer(msg.sender, address(this), numShares);
uint256 withdrawAmount =
ShareMathBeefy.sharesToAsset(
numShares,
pricePerShare(),
vaultParams.decimals
);
emit Withdraw(msg.sender, withdrawAmount, numShares);
_burn(address(this), numShares);
require(withdrawAmount > 0, "!withdrawAmount");
IBeefy bv = IBeefy(BEEFY_VAULT);
// This should be balance of GLP held by vault
uint256 prevBalance = IERC20(vaultParams.asset).balanceOf(address(this));
bv.withdraw(withdrawAmount);
uint256 afterBalance = IERC20(vaultParams.asset).balanceOf(address(this));
transferAsset(msg.sender, afterBalance.sub(prevBalance));
console.log("WITHDRAWWW withdrawAmount %s transferAmount %s BPS", withdrawAmount, afterBalance.sub(prevBalance), bv.getPricePerFullShare());
return withdrawAmount;
}
/**
* @notice Redeems shares that are owed to the account
* @param numShares is the number of shares to redeem
*/
function redeem(uint256 numShares) external nonReentrant {
require(numShares > 0, "!numShares");
_redeem(numShares, false);
}
/**
* @notice Redeems the entire unredeemedShares balance that is owed to the account
*/
function maxRedeem() external nonReentrant {
_redeem(0, true);
}
/**
* @notice Redeems shares that are owed to the account
* @param numShares is the number of shares to redeem, could be 0 when isMax=true
* @param isMax is flag for when callers do a max redemption
*/
function _redeem(uint256 numShares, bool isMax) internal {
Beefy.DepositReceipt memory depositReceipt =
depositReceipts[msg.sender];
// This handles the null case when depositReceipt.round = 0
// Because we start with round = 1 at `initialize`
uint256 currentRound = vaultState.round;
// User redeems as per locked round
uint256 unredeemedShares =
depositReceipt.getSharesFromReceipt(
currentRound,
roundPricePerShare[depositReceipt.round+1],
roundPricePerShare[depositReceipt.roundB+1],
vaultParams.decimals
);
numShares = isMax ? unredeemedShares : numShares;
if (numShares == 0) {
return;
}
require(numShares <= unredeemedShares, "Exceeds available");
// If we have a depositReceipt on the same round, BUT we have some unredeemed shares
// we debit from the unredeemedShares, but leave the amount field intact
// If the round has past, with no new deposits, we just zero it out for new deposits.
if (depositReceipt.round < (currentRound-1)) {
depositReceipts[msg.sender].amount = 0;
}
if (depositReceipt.roundB < (currentRound-1)) {
depositReceipts[msg.sender].amountB = 0;
}
ShareMathBeefy.assertUint128(numShares);
depositReceipts[msg.sender].unredeemedShares = uint128(
unredeemedShares.sub(numShares)
);
emit Redeem(msg.sender, numShares, depositReceipt.round);
_transfer(address(this), msg.sender, numShares);
}
// /**
// * @notice Calculates the performance and management fee for this week's round
// * @param currentBalance is the balance of funds held on the vault after closing short
// * @param lastLockedAmount is the amount of funds locked from the previous round
// * @param pendingAmount is the pending deposit amount
// * @param performanceFeePercent is the performance fee pct.
// * @param managementFeePercent is the management fee pct.
// * @return performanceFeeInAsset is the performance fee
// * @return managementFeeInAsset is the management fee
// * @return vaultFee is the total fees
// */
// function getVaultFees(
// uint256 currentBalance,
// uint256 lastLockedAmount,
// uint256 pendingAmount,
// uint256 performanceFeePercent,
// uint256 managementFeePercent
// )
// internal
// view
// returns (
// uint256 performanceFeeInAsset,
// uint256 managementFeeInAsset,
// uint256 vaultFee
// )
// {
// // At the first round, currentBalance=0, pendingAmount>0
// // so we just do not charge anything on the first round
// uint256 lockedBalanceSansPending =
// currentBalance > pendingAmount
// ? currentBalance.sub(pendingAmount)
// : 0;
// // uint256 _interestBeared =
// uint256 _performanceFeeInAsset;
// uint256 _managementFeeInAsset;
// uint256 _vaultFee;
// // Take performance fee and management fee ONLY if difference between
// // last week and this week's vault deposits, taking into account pending
// // deposits and withdrawals, is positive. If it is negative, last week's
// // option expired ITM past breakeven, and the vault took a loss so we
// // do not collect performance fee for last week
// console.log("settledAmount %s lockedBalanceSansPending %s performanceFeePercent %s",optionState.settledAmount, lockedBalanceSansPending, performanceFeePercent);
// if (lockedBalanceSansPending > lastLockedAmount &&
// optionState.settledAmount > 0) {
// _performanceFeeInAsset = performanceFeePercent > 0
// ? optionState.settledAmount
// .mul(performanceFeePercent)
// .div(100 * Beefy.FEE_MULTIPLIER)
// : 0;
// _managementFeeInAsset = managementFeePercent > 0
// ? lockedBalanceSansPending.mul(managementFeePercent).div(
// 100 * Beefy.FEE_MULTIPLIER
// )
// : 0;
// _vaultFee = _performanceFeeInAsset.add(_managementFeeInAsset);
// } else {
// _managementFeeInAsset = managementFeePercent > 0
// ? uint256(vaultState.lockedAmount).mul(managementFeePercent).div(
// 100 * Beefy.FEE_MULTIPLIER
// )
// : 0;
// _vaultFee = _managementFeeInAsset;
// }
// return (_performanceFeeInAsset, _managementFeeInAsset, _vaultFee);
// }
/**
* @notice Calculates the performance and management fee for this week's round
* @param deployedAmount is the capital deployed for yield.
* @param performanceFeePercent is the performance fee pct.
* @param managementFeePercent is the management fee pct.
* @return performanceFeeInAsset is the performance fee
* @return managementFeeInAsset is the management fee
* @return vaultFee is the total fees
*/
function getVaultFees(
uint256 deployedAmount,
uint256 performanceFeePercent,
uint256 managementFeePercent
)
internal
view
returns (
uint256 performanceFeeInAsset,
uint256 managementFeeInAsset,
uint256 vaultFee
)
{
uint256 _performanceFeeInAsset = optionState.settledAmount
.mul(performanceFeePercent)
.div(100 * Beefy.FEE_MULTIPLIER);
uint256 _managementFeeInAsset = uint256(deployedAmount).sub(_performanceFeeInAsset)
.mul(managementFeePercent)
.div(100 * Beefy.FEE_MULTIPLIER);
uint256 _vaultFee = _performanceFeeInAsset.add(_managementFeeInAsset);
console.log("FEEE settledAmount %s deployedAmount %s ", optionState.settledAmount, deployedAmount, managementFeePercent);
console.log("FEEE _performanceFeeInAsset %s _managementFeeInAsset %s _vaultFee %s ", _performanceFeeInAsset, _managementFeeInAsset, _vaultFee);
return (_performanceFeeInAsset, _managementFeeInAsset, _vaultFee);
}
/**
* @notice Helper function to make either an ETH transfer or ERC20 transfer
* @param recipient is the receiving address
* @param amount is the transfer amount
*/
function transferAsset(address recipient, uint256 amount) internal {
address asset = vaultParams.asset;
IERC20(asset).safeTransfer(recipient, amount);
}
/**
* @notice Helper function to make either an ETH transfer or ERC20 transfer
* @param recipient is the receiving address
* @param amount is the transfer amount
*/
function transferAssetByAddress(address asset, address recipient, uint256 amount) internal {
IERC20(asset).safeTransfer(recipient, amount);
}
/**
* @notice Getter for returning the account's share balance including unredeemed shares
* @param account is the account to lookup share balance for
* @return the share balance
*/
function shares(address account) public view returns (uint256) {
(uint256 heldByAccount, uint256 heldByVault) = shareBalances(account);
return heldByAccount.add(heldByVault);
}
/**
* @notice Getter for returning the account's share balance split between account and vault holdings
* @param account is the account to lookup share balance for
* @return heldByAccount is the shares held by account
* @return heldByVault is the shares held on the vault (unredeemedShares)
*/
function shareBalances(address account)
public
view
returns (uint256 heldByAccount, uint256 heldByVault)
{
Beefy.DepositReceipt memory depositReceipt = depositReceipts[account];
if (depositReceipt.round < Beefy.PLACEHOLDER_UINT) {
return (balanceOf(account), 0);
}
uint256 unredeemedShares =
depositReceipt.getSharesFromReceipt(
vaultState.round,
roundPricePerShare[depositReceipt.round+1],
roundPricePerShare[depositReceipt.roundB+1],
vaultParams.decimals
);
return (balanceOf(account), unredeemedShares);
}
/**
* @notice The price of a unit of share denominated in the `asset`
*/
function pricePerShare() public view returns (uint256) {
uint256 pendingAmount = vaultState.prevRoundAmount + vaultState.unlockedAmount;
return
ShareMathBeefy.pricePerShare(
totalSupply(),
totalBalance(),
pendingAmount,
vaultParams.decimals
);
}
/**
* @notice Returns the pool's total balance, including the amounts locked into vaults
* @return total balance of the vault, including the amounts locked in third party protocols
*/
function totalBalance() public view returns (uint256) {
// Before calling closeRound, current option is set to none
// We also commit the lockedAmount but do not deposit into Opyn
// which results in double counting of asset balance and lockedAmount
// Get the borrowed amount by the MM and add to balance of vault
return IERC20(BEEFY_VAULT).balanceOf(address(this));
// optionState.isSettled
//? IERC20(vaultParams.asset).balanceOf(address(this))
// : uint256(vaultState.lockedAmount).add(vaultState.totalPending);
}
// function settleAmounts() public view returns (uint256 borrowedAmount, uint256 couponAmount, uint256 lossAmount) {
// return _settleAmounts();
// }
/**
* @notice Returns the token decimals
*/
function decimals() public view override returns (uint8) {
return vaultParams.decimals;
}
function cap() external view returns (uint256) {
return vaultParams.cap;
}
function totalPending() external view returns (uint256) {
return vaultState.totalPending;
}
function getNextExpiry() internal view returns (uint256) {
uint256 timestamp = block.timestamp;
// dayOfWeek = 0 (sunday) - 6 (saturday)
uint256 dayOfWeek = ((timestamp / 1 days) + 4) % 7;
uint256 nextMonday = timestamp + ((7 + 1 - dayOfWeek) % 7) * 1 days;
uint256 monday8am = nextMonday - (nextMonday % (24 hours)) + (8 hours);
// If the passed timestamp is day=Friday hour>8am, we simply increment it by a week to next Friday
if (timestamp >= monday8am) {
monday8am += 7 days;
}
return monday8am;
// uint256 futureDays = block.timestamp.add(vaultParams.vaultPeriod);
// uint256 nextExpiryAt8am = futureDays - (futureDays % (1 days)) + (8 hours);
// return nextExpiryAt8am;
}
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.4.22 <0.9.0;
library console {
address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);
function _sendLogPayload(bytes memory payload) private view {
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE_ADDRESS;
assembly {
let payloadStart := add(payload, 32)
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
function log() internal view {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int256 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function logUint(uint256 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function logString(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint256 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function log(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint256 p0, uint256 p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
}
function log(uint256 p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
}
function log(uint256 p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
}
function log(uint256 p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
}
function log(string memory p0, uint256 p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
}
function log(string memory p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint256 p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
}
function log(bool p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint256 p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
}
function log(address p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint256 p0, uint256 p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
}
function log(uint256 p0, bool p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
}
function log(uint256 p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
}
function log(uint256 p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
}
function log(uint256 p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
}
function log(uint256 p0, address p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
}
function log(uint256 p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
}
function log(uint256 p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
}
function log(uint256 p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint256 p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
}
function log(bool p0, uint256 p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
}
function log(bool p0, uint256 p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
}
function log(bool p0, uint256 p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint256 p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
}
function log(address p0, uint256 p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
}
function log(address p0, uint256 p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
}
function log(address p0, uint256 p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rate","type":"uint256"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldCap","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCap","type":"uint256"}],"name":"CapSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"performanceFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"round","type":"uint256"},{"indexed":true,"internalType":"address","name":"feeRecipient","type":"address"}],"name":"CollectVaultFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"round","type":"uint256"}],"name":"Deposit","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":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"round","type":"uint256"}],"name":"InitiateWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"round","type":"uint256"}],"name":"InstantWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mooQuantity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"glpQuantity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deployedBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"round","type":"uint256"}],"name":"InterestRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"managementFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newManagementFee","type":"uint256"}],"name":"ManagementFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"observeTime","type":"uint256"},{"indexed":false,"internalType":"bool","name":"hasKO","type":"bool"},{"indexed":false,"internalType":"bool","name":"hasKI","type":"bool"},{"indexed":false,"internalType":"uint16","name":"activeDays","type":"uint16"}],"name":"Observe","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":"uint256","name":"performanceFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPerformanceFee","type":"uint256"}],"name":"PerformanceFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"share","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"round","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"couponAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"settledAmount","type":"uint256"}],"name":"Settle","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"BEEFY_VAULT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_DECIMALS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"accountBalance","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"balanceA","type":"uint256"},{"internalType":"uint256","name":"balanceB","type":"uint256"},{"internalType":"uint256","name":"sharesBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"assetStrikePrices","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"auctionTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"borrower","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"close","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentQueuedWithdrawShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"depositReceipts","outputs":[{"internalType":"uint16","name":"round","type":"uint16"},{"internalType":"uint104","name":"amount","type":"uint104"},{"internalType":"uint16","name":"roundB","type":"uint16"},{"internalType":"uint104","name":"amountB","type":"uint104"},{"internalType":"uint128","name":"unredeemedShares","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_keeper","type":"address"},{"internalType":"address","name":"_feeRecipent","type":"address"},{"internalType":"string","name":"_tokenName","type":"string"},{"internalType":"string","name":"_tokenSymbol","type":"string"},{"components":[{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"beefyVault","type":"address"},{"internalType":"uint56","name":"minimumSupply","type":"uint56"},{"internalType":"uint104","name":"cap","type":"uint104"},{"internalType":"uint256","name":"vaultPeriod","type":"uint256"}],"internalType":"struct Beefy.VaultParams","name":"_vaultParams","type":"tuple"},{"internalType":"contract IGlpRouter","name":"_glpRouter","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastQueuedWithdrawAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managementFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"observer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"optionState","outputs":[{"internalType":"uint256","name":"lockedAmount","type":"uint256"},{"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"internalType":"uint256","name":"couponAmount","type":"uint256"},{"internalType":"uint256","name":"settledAssetAmount","type":"uint256"},{"internalType":"uint256","name":"settledAmount","type":"uint256"},{"internalType":"uint256","name":"unSettledYield","type":"uint256"},{"internalType":"uint256","name":"beefyPPS","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"bool","name":"isSettled","type":"bool"},{"internalType":"bool","name":"isBorrowed","type":"bool"},{"internalType":"uint256","name":"lastObservation","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"performanceFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pricePerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numShares","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"roundPricePerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_auctionTime","type":"uint256"}],"name":"setAuctionTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"setBorrower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCap","type":"uint256"}],"name":"setCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeRecipient","type":"address"}],"name":"setFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_glpRouter","type":"address"}],"name":"setGlpRewardRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newManagementFee","type":"uint256"}],"name":"setManagementFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newKeeper","type":"address"}],"name":"setNewKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newObserver","type":"address"}],"name":"setObserver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPerformanceFee","type":"uint256"}],"name":"setPerformanceFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultPeriod","type":"uint256"}],"name":"setVaultPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"settle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleGlp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"shareBalances","outputs":[{"internalType":"uint256","name":"heldByAccount","type":"uint256"},{"internalType":"uint256","name":"heldByVault","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"shares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPending","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_expiry","type":"uint256"}],"name":"updateExpiry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateLastOb","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vaultParams","outputs":[{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"beefyVault","type":"address"},{"internalType":"uint56","name":"minimumSupply","type":"uint56"},{"internalType":"uint104","name":"cap","type":"uint104"},{"internalType":"uint256","name":"vaultPeriod","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultState","outputs":[{"internalType":"uint16","name":"round","type":"uint16"},{"internalType":"uint104","name":"lockedAmount","type":"uint104"},{"internalType":"uint104","name":"unlockedAmount","type":"uint104"},{"internalType":"uint104","name":"prevRoundAmount","type":"uint104"},{"internalType":"uint104","name":"lastLockedAmount","type":"uint104"},{"internalType":"uint128","name":"totalPending","type":"uint128"},{"internalType":"uint128","name":"burntShares","type":"uint128"},{"internalType":"uint128","name":"burntAmount","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numShares","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawInstantly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"withdrawals","outputs":[{"internalType":"uint16","name":"round","type":"uint16"},{"internalType":"uint128","name":"shares","type":"uint128"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a06040523480156200001157600080fd5b5060405162005df138038062005df1833981016040819052620000349162000091565b806001600160a01b0381166200007a5760405162461bcd60e51b81526020600482015260076024820152660857dd985d5b1d60ca1b604482015260640160405180910390fd5b60601b6001600160601b03191660805250620000c1565b600060208284031215620000a3578081fd5b81516001600160a01b0381168114620000ba578182fd5b9392505050565b60805160601c615cb66200013b600039600081816103ce01528181610ec801528181610f6f015281816110710152818161166f01528181611b0e0152818161262e0152818161272c015281816127cd015281816128d40152818161395f01528181613c7801528181613eb40152614db80152615cb66000f3fe608060405234801561001057600080fd5b50600436106103af5760003560e01c80637df1f1b9116101f4578063aced16611161011a578063db006a75116100ad578063eb70e4981161007c578063eb70e49814610a6e578063f2fde38b14610a82578063f656ba5114610a95578063fe56e23214610abd57600080fd5b8063db006a7514610a2d578063dd62ed3e14610a40578063e68d356914610a53578063e74b981b14610a5b57600080fd5b8063ce7c2ac2116100e9578063ce7c2ac2146109c1578063d164cc15146109d4578063d294cb0f146109e7578063d359f82c14610a1a57600080fd5b8063aced166114610980578063ad7a672f14610993578063b6b55f251461099b578063c762d5f7146109ae57600080fd5b806395d89b4111610192578063a457c2d711610161578063a457c2d71461093e578063a54c889914610951578063a6f7f5d614610964578063a9059cbb1461096d57600080fd5b806395d89b411461080057806399530b06146108085780639fcc2d7514610810578063a083ff17146108ac57600080fd5b806387788782116101ce57806387788782146107c05780638da5cb5b146107c95780638df82800146107da57806394d9c9c7146107ed57600080fd5b80637df1f1b91461077a578063852986891461078d57806387153eb1146107a057600080fd5b80633a43527f116102d95780635a659d261161027757806370897b231161024657806370897b23146106df57806370a08231146106f2578063715018a61461071b5780637a9262a21461072357600080fd5b80635a659d26146106125780635b7f415c146106255780636719b2ee146106345780636f31ab34146106d757600080fd5b806346904840116102b357806346904840146105d857806347786d37146105eb5780634b2431d9146105fe578063503c70aa1461060857600080fd5b80633a43527f1461059f5780633f90916a146105bf57806343d726d6146105d057600080fd5b806323b872dd116103515780632e1a7d4d116103205780632e1a7d4d14610553578063313ce56714610566578063355274ea1461057b578063395093511461058c57600080fd5b806323b872dd1461046d5780632728f333146104805780632775d01c14610538578063278a30121461054b57600080fd5b8063095ea7b31161038d578063095ea7b314610422578063125562de14610445578063155f586d1461044d57806318160ddd1461046557600080fd5b80630342389c146103b457806304ac00c9146103c957806306fdde031461040d575b600080fd5b6103c76103c23660046152e3565b610ad0565b005b6103f07f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b610415610c71565b60405161040491906154be565b6104356104303660046153fb565b610d03565b6040519015158152602001610404565b6103c7610d1d565b6104576101045481565b604051908152602001610404565b609954610457565b61043561047b3660046153bb565b611168565b60d15460d25460d35460d4546104dd9361ffff8116936001600160681b03620100008304811694600160781b90930481169382821693600160681b909304909116916001600160801b0380821692600160801b9092048116911688565b6040805161ffff90991689526001600160681b0397881660208a0152958716958801959095529285166060870152931660808501526001600160801b0392831660a0850152821660c08401521660e082015261010001610404565b6103c7610546366004615446565b61118e565b6103c76118eb565b6103c7610561366004615446565b6118fa565b60cd5460405160ff9091168152602001610404565b60cf546001600160681b0316610457565b61043561059a3660046153fb565b611924565b6104576105ad366004615273565b60cc6020526000908152604090205481565b60d3546001600160801b0316610457565b6103c7611946565b60df546103f0906001600160a01b031681565b6103c76105f9366004615446565b612115565b6104576101035481565b6104576101025481565b6103c7610620366004615273565b6121c8565b610457670de0b6b3a764000081565b610691610642366004615273565b60c9602052600090815260409020805460019091015461ffff808316926001600160681b03620100008204811693600160781b830490931692600160881b90920416906001600160801b031685565b6040805161ffff96871681526001600160681b03958616602082015295909316928501929092529190911660608301526001600160801b0316608082015260a001610404565b6103c76122cd565b6103c76106ed366004615446565b61230a565b610457610700366004615273565b6001600160a01b031660009081526097602052604090205490565b6103c76123af565b610758610731366004615273565b60cb6020526000908152604090205461ffff8116906201000090046001600160801b031682565b6040805161ffff90931683526001600160801b03909116602083015201610404565b60e0546103f0906001600160a01b031681565b6103c761079b366004615446565b6123c3565b6104576107ae366004615446565b60ca6020526000908152604090205481565b61045760e25481565b6065546001600160a01b03166103f0565b6103c76107e8366004615446565b61240b565b6103c76107fb366004615273565b61245d565b6104156124ce565b6104576124dd565b60cd5460ce5460cf5460d05461085c9360ff8116936001600160a01b036101009092048216939181169266ffffffffffffff600160a01b90920491909116916001600160681b03169086565b6040805160ff9790971687526001600160a01b039586166020880152939094169285019290925266ffffffffffffff1660608401526001600160681b0316608083015260a082015260c001610404565b60d55460d65460d75460d85460d95460da5460db5460dc5460dd5460de546108e799989796959493929160ff8082169261010090920416908b565b604080519b8c5260208c019a909a52988a01979097526060890195909552608088019390935260a087019190915260c086015260e08501521515610100840152151561012083015261014082015261016001610404565b61043561094c3660046153fb565b612537565b6103c761095f366004615446565b6125bd565b61045760e35481565b61043561097b3660046153fb565b612608565b60e1546103f0906001600160a01b031681565b610457612616565b6103c76109a9366004615446565b6126b5565b6103c76109bc366004615273565b612a10565b6104576109cf366004615273565b612a7d565b6103c76109e2366004615273565b612aa2565b6109fa6109f5366004615273565b612b0f565b604080519485526020850193909352918301526060820152608001610404565b6103c7610a28366004615446565b612b2d565b6103c7610a3b366004615446565b612b72565b610457610a4e3660046152ab565b612bdf565b6103c7612c0a565b6103c7610a69366004615273565b612d30565b610105546103f0906001600160a01b031681565b6103c7610a90366004615273565b612e01565b610aa8610aa3366004615273565b612e7a565b60408051928352602083019190915201610404565b6103c7610acb366004615446565b612fb5565b600054610100900460ff1615808015610af05750600054600160ff909116105b80610b0a5750303b158015610b0a575060005460ff166001145b610b2f5760405162461bcd60e51b8152600401610b269061556d565b60405180910390fd5b6000805460ff191660011790558015610b52576000805461ff0019166101001790555b61010680546001600160a01b0319166001600160a01b03851690811790915560408051633e9b6c6f60e21b8152905163fa6db1bc916004808201926020929091908290030181600087803b158015610ba957600080fd5b505af1158015610bbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be1919061528f565b61010780546001600160a01b03199081166001600160a01b03938416179091556101088054909116918416919091179055610c20898989898989613074565b8015610c66576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b6060609a8054610c8090615886565b80601f0160208091040260200160405190810160405280929190818152602001828054610cac90615886565b8015610cf95780601f10610cce57610100808354040283529160200191610cf9565b820191906000526020600020905b815481529060010190602001808311610cdc57829003601f168201915b5050505050905090565b600033610d11818585613268565b60019150505b92915050565b60026001541415610d405760405162461bcd60e51b8152600401610b2690615627565b600260015560e0546000906001600160a01b03163314610d725760405162461bcd60e51b8152600401610b2690615547565b60dc54421015610db35760405162461bcd60e51b815260206004820152600c60248201526b6561726c7920736574746c6560a01b6044820152606401610b26565b60dd5460ff16158015610dcd575060dd54610100900460ff165b610e0b5760405162461bcd60e51b815260206004820152600f60248201526e185b1c9958591e481cd95d1d1b1959608a1b6044820152606401610b26565b60cd546040516370a0823160e01b815230600482015260009161010090046001600160a01b0316906370a082319060240160206040518083038186803b158015610e5457600080fd5b505afa158015610e68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8c919061545e565b905060008111610eae5760405162461bcd60e51b8152600401610b26906155bb565b60cd5460405163095ea7b360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000818116600484015260248301859052926101009004169063095ea7b390604401602060405180830381600087803b158015610f2157600080fd5b505af1158015610f35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f599190615426565b506040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b158015610fb957600080fd5b505afa158015610fcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff1919061545e565b60405163b6b55f2560e01b8152600481018490529093506001600160a01b0382169063b6b55f2590602401600060405180830381600087803b15801561103657600080fd5b505af115801561104a573d6000803e3d6000fd5b50506040516370a0823160e01b81523060048201526110f192508591506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b1580156110b357600080fd5b505afa1580156110c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110eb919061545e565b9061338c565b60d9819055600060d881905560dd805460ff1916600117905560e05460d754604080519182526020820193909352918201929092526001600160a01b03909116907f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe7949060600160405180910390a250506001805550565b600033611176858285613398565b611181858585613412565b60019150505b9392505050565b600260015414156111b15760405162461bcd60e51b8152600401610b2690615627565b6002600190815560d1546000918291829182918291829182918291829161ffff9091169081900b156112395760405162461bcd60e51b815260206004820152602b60248201527f66756e64732077696c6c2062652072656c656173656420616674657220696e7460448201526a195c9b985b08185d591a5d60aa1b6064820152608401610b26565b33600081815260c96020526040902090611252906135e0565b9199509750955093508b84101561129c5760405162461bcd60e51b815260206004820152600e60248201526d0858985b185b98d9505b5bdd5b9d60921b6044820152606401610b26565b8b92508515611340578b86116112b257856112b4565b8b5b60d154825491995061ffff908116600160781b90920416146112e2576112da888b6156c8565b9950896112f0565b6112ec888a6156c8565b9850885b50805461130d90600160881b90046001600160681b03168961338c565b81546001600160681b0391909116600160881b02600160881b600160f01b031990911617815561133d888c6156c8565b9a505b8a8c11801561134f5750600087115b156113f65761135e8b8d615843565b871161136a5786611374565b6113748b8d615843565b60d154825491995061ffff91821691161461139b57611393888b6156c8565b9950896113a9565b6113a5888a6156c8565b9850885b5080546113c5906201000090046001600160681b03168961338c565b81546001600160681b0391909116620100000262010000600160781b03199091161781556113f3888c6156c8565b9a505b8a8c1115611568576114088b8d615843565b97506000611423896114186124dd565b60cd5460ff166136ea565b905060008061143133612e7a565b90925090506000611442838361374d565b905061144f8460016156c8565b811415611468576114616001856156c8565b9350611488565b611473600185615843565b81141561148857611485600185615843565b93505b6114ab6040518060600160405280602b8152602001615b1e602b91398d86613759565b6114b4846137a5565b5060d380548591906010906114da908490600160801b90046001600160801b0316615689565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508b60d160030160008282829054906101000a90046001600160801b03166115259190615689565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508b8f61155591906156c8565b9e506115618c88615843565b9650505050505b8b8b146115875760405162461bcd60e51b8152600401610b26906155bb565b60d1546115a490600160781b90046001600160681b03168a61338c565b60d180546001600160681b0392909216600160781b02600160781b600160e01b031983168117909155600161ffff918216919092161711156116515760d2546115f6906001600160681b03168b61338c565b60d280546001600160681b0319166001600160681b0392831617905560d1546116279162010000909104168b61338c565b60d180546001600160681b0392909216620100000262010000600160781b03199092169190911790555b82156118d95760cd546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000916000916101009091046001600160a01b0316906370a082319060240160206040518083038186803b1580156116c357600080fd5b505afa1580156116d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116fb919061545e565b604051632e1a7d4d60e01b8152600481018790529091506001600160a01b03831690632e1a7d4d90602401600060405180830381600087803b15801561174057600080fd5b505af1158015611754573d6000803e3d6000fd5b505060cd546040516370a0823160e01b8152306004820152600093506101009091046001600160a01b031691506370a082319060240160206040518083038186803b1580156117a257600080fd5b505afa1580156117b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117da919061545e565b905060006117e8828461338c565b90506117f43382613b86565b6118926040518060400160405280600c81526020016b494e5354414e54542042505360a01b815250856001600160a01b03166377c7b8fc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561185557600080fd5b505afa158015611869573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188d919061545e565b613ba2565b60d1546040805189815261ffff909216602083015233917fab2daf3c146ca6416cbccd2a86ed2ba995e171ef6319df14a38aef01403a9c96910160405180910390a2505050505b50506001805550505050505050505050565b6118f3613beb565b600060de55565b6002600154141561191d5760405162461bcd60e51b8152600401610b2690615627565b5060018055565b600033610d118185856119378383612bdf565b61194191906156c8565b613268565b600260015414156119695760405162461bcd60e51b8152600401610b2690615627565b600260015560e1546001600160a01b031633146119b25760405162461bcd60e51b815260206004820152600760248201526610b5b2b2b832b960c91b6044820152606401610b26565b60dd5460ff16806119cb575060d154600361ffff909116105b611a065760405162461bcd60e51b815260206004820152600c60248201526b149bdd5b990818db1bdcd95960a21b6044820152606401610b26565b611a75604051806101a001604052806000815260200160008152602001600061ffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b611a7d613c45565b5061016083015261018082015260d15460d280546001600160681b0319166001600160681b03600160781b84048116918217909255611ac5929091620100009091041661565e565b60d1805462010000600160e01b031916620100006001600160681b039390931692909202600160781b600160e01b03191691909117905560408051631df1ee3f60e21b815290517f0000000000000000000000000000000000000000000000000000000000000000916001600160a01b038316916377c7b8fc91600480820192602092909190829003018186803b158015611b5f57600080fd5b505afa158015611b73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b97919061545e565b60208301526040516370a0823160e01b81523060048201526001600160a01b038216906370a082319060240160206040518083038186803b158015611bdb57600080fd5b505afa158015611bef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c13919061545e565b606083015260d15461ffff166040830152610180820151610160830151611c399161374d565b61014083015260408051606081019091526031808252611c789190615a886020830139606084015160d25460d9546001600160681b0390911690613ef1565b60d95460d254611c93916001600160681b039091169061374d565b60da546101408401516060850151611cb69291611cb0919061374d565b9061374d565b106120655760d95460d25460da546101408501516060860151611cef94936110eb936001600160681b03909116928492611cb09161374d565b60c083015260db805460808401819052602084015191829055600091611d159190615843565b905082602001518360c0015182611d2c91906157df565b611d3691906156e0565b61010084015260408051606081019091526028808252611d6e9190615a60602083013984602001518560800151866101000151613ef1565b611da6604051806060016040528060338152602001615ab96033913960c085015160d25460d9546001600160681b0390911690613ef1565b6002836040015161ffff16118015611dc357506000836101000151115b1561205f57670de0b6b3a76400008360200151846101000151611de691906157df565b611df091906156e0565b610120840152610100830151604051632e1a7d4d60e01b815260048101919091526001600160a01b03831690632e1a7d4d90602401600060405180830381600087803b158015611e3f57600080fd5b505af1158015611e53573d6000803e3d6000fd5b50505050611e89604051806060016040528060328152602001615aec603291398461010001518561012001518660600151613ef1565b610108546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015611ece57600080fd5b505afa158015611ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f06919061545e565b9050611f16846101200151613f3a565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a082319060240160206040518083038186803b158015611f5557600080fd5b505afa158015611f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8d919061545e565b6060850152610108546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015611fd757600080fd5b505afa158015611feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200f919061545e565b905061201b8282615843565b60d681905560408051808201909152601681527555534443202573206375727262616c616e636520257360501b6020820152606087015161205c9290613759565b50505b5061206b565b600060d6555b60d380546001600160801b0316905560d480546001600160801b0319169055600060da5560dd805461ffff191690556120a2613fd1565b60dc5560d65461010083015161012084015160c085015160408087015181519586526020860194909452840191909152606083015261ffff1660808201527f136258a39190042d2cd2e39a244f43d39a46be4417d5895b5419169f659fa12d9060a00160405180910390a1505060018055565b61211d613beb565b600081116121575760405162461bcd60e51b81526020600482015260076024820152660216e65774361760cc1b6044820152606401610b26565b61216081614071565b60cf54604080516001600160681b039092168252602082018390527f5f86edbb9d92228a9edc3f0ebc0f001bda1ea345ac7335e0eeef3504b31d1a1c910160405180910390a160cf80546001600160681b0319166001600160681b0392909216919091179055565b6121d0613beb565b6001600160a01b03811661221a5760405162461bcd60e51b815260206004820152601160248201527076616c696420676c70206164647265737360781b6044820152606401610b26565b61010680546001600160a01b0319166001600160a01b03831690811790915560408051633e9b6c6f60e21b8152905163fa6db1bc916004808201926020929091908290030181600087803b15801561227157600080fd5b505af1158015612285573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a9919061528f565b61010780546001600160a01b0319166001600160a01b039290921691909117905550565b600260015414156122f05760405162461bcd60e51b8152600401610b2690615627565b6002600181905550612304600060016140bb565b60018055565b612312613beb565b612320620f424060646157df565b811061236e5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420706572666f726d616e6365206665650000000000000000006044820152606401610b26565b60e25460408051918252602082018390527f24867dfb6fcb9970a07be21024956524abe7a1837faa903ff0e99aaa40cf893e910160405180910390a160e255565b6123b7613beb565b6123c16000614308565b565b6123cb613beb565b600081116124065760405162461bcd60e51b8152602060048201526008602482015267085a5b9d985b1a5960c21b6044820152606401610b26565b60d055565b6002600154141561242e5760405162461bcd60e51b8152600401610b2690615627565b600260015560e0546001600160a01b0316331461191d5760405162461bcd60e51b8152600401610b2690615547565b612465613beb565b6001600160a01b0381166124ab5760405162461bcd60e51b815260206004820152600d60248201526c10afb732bba7b139b2b93b32b960991b6044820152606401610b26565b61010580546001600160a01b0319166001600160a01b0392909216919091179055565b6060609b8054610c8090615886565b60d15460d2546000918291612505916001600160681b03600160781b9091048116911661565e565b6001600160681b0316905061253161251c60995490565b612524612616565b60cd54849060ff1661435a565b91505090565b600033816125458286612bdf565b9050838110156125a55760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610b26565b6125b28286868403613268565b506001949350505050565b6125c5613beb565b806126025760405162461bcd60e51b815260206004820152600d60248201526c215f61756374696f6e54696d6560981b6044820152606401610b26565b61010455565b600033610d11818585613412565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561267857600080fd5b505afa15801561268c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b0919061545e565b905090565b600260015414156126d85760405162461bcd60e51b8152600401610b2690615627565b6002600155806126fa5760405162461bcd60e51b8152600401610b26906155bb565b60cd546127179061010090046001600160a01b031633308461439a565b6040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038316906370a082319060240160206040518083038186803b15801561277b57600080fd5b505afa15801561278f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b3919061545e565b60cd5460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018790529293506101009091049091169063095ea7b390604401602060405180830381600087803b15801561282a57600080fd5b505af115801561283e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128629190615426565b5060405163b6b55f2560e01b8152600481018490526001600160a01b0383169063b6b55f2590602401600060405180830381600087803b1580156128a557600080fd5b505af11580156128b9573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031691506370a082319060240160206040518083038186803b15801561291f57600080fd5b505afa158015612933573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612957919061545e565b90506000612965828461338c565b90506129718133614405565b612a056040518060600160405280602b8152602001615b74602b9139856001600160a01b03166377c7b8fc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156129c657600080fd5b505afa1580156129da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129fe919061545e565b8343613ef1565b505060018055505050565b612a18613beb565b6001600160a01b038116612a5b5760405162461bcd60e51b815260206004820152600a60248201526910afb137b93937bbb2b960b11b6044820152606401610b26565b60e080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806000612a8b84612e7a565b9092509050612a9a828261374d565b949350505050565b612aaa613beb565b6001600160a01b038116612aed5760405162461bcd60e51b815260206004820152600a60248201526910b732bba5b2b2b832b960b11b6044820152606401610b26565b60e180546001600160a01b0319166001600160a01b0392909216919091179055565b600080600080612b1e856135e0565b93509350935093509193509193565b612b35613beb565b80612b6d5760405162461bcd60e51b8152602060048201526008602482015267215f65787069727960c01b6044820152606401610b26565b60dc55565b60026001541415612b955760405162461bcd60e51b8152600401610b2690615627565b600260015580612bd45760405162461bcd60e51b815260206004820152600a602482015269216e756d53686172657360b01b6044820152606401610b26565b61191d8160006140bb565b6001600160a01b03918216600090815260986020908152604080832093909416825291909152205490565b60026001541415612c2d5760405162461bcd60e51b8152600401610b2690615627565b600260015560d65415612cd05760dd54610100900460ff1615612c855760405162461bcd60e51b815260206004820152601060248201526f185b1c9958591e48189bdc9c9bddd95960821b6044820152606401610b26565b60e0546001600160a01b03163314612caf5760405162461bcd60e51b8152600401610b2690615547565b6101085460e05460d654612cd0926001600160a01b03908116921690614897565b60e05460d65460408051918252600060208301526001600160a01b03909216917fe1979fe4c35e0cef342fef5668e2c8e7a7e9f5d5d1ca8fee0ac6c427fa4153af910160405180910390a260dd805461ff00191661010017905560018055565b612d38613beb565b6001600160a01b038116612d815760405162461bcd60e51b815260206004820152601060248201526f085b995dd19959549958da5c1a595b9d60821b6044820152606401610b26565b60df546001600160a01b0382811691161415612ddf5760405162461bcd60e51b815260206004820152601860248201527f4d757374206265206e657720666565526563697069656e7400000000000000006044820152606401610b26565b60df80546001600160a01b0319166001600160a01b0392909216919091179055565b612e09613beb565b6001600160a01b038116612e6e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b26565b612e7781614308565b50565b6001600160a01b038116600090815260c960209081526040808320815160a081018352815461ffff8082168084526001600160681b03620100008404811697850197909752600160781b830490911694830194909452600160881b900490931660608401526001908101546001600160801b031660808401528392911015612f1a575050506001600160a01b031660009081526097602052604081205491565b60d1548151600091612f8a9161ffff9091169060ca908490612f3d9060016156ab565b61ffff1681526020019081526020016000205460ca600086604001516001612f6591906156ab565b61ffff16815260208101919091526040016000205460cd54869392919060ff166148ab565b9050612fab856001600160a01b031660009081526097602052604090205490565b9590945092505050565b612fbd613beb565b612fcb620f424060646157df565b81106130125760405162461bcd60e51b8152602060048201526016602482015275496e76616c6964206d616e6167656d656e742066656560501b6044820152606401610b26565b600061302f63031ba30961302984620f424061496a565b90614976565b60e35460408051918252602082018590529192507f4e874b007ab14f7e263baefd44951834c8266f4f224d1092e49e9c254354cc54910160405180910390a160e35550565b600054610100900460ff16158080156130945750600054600160ff909116105b806130ae5750303b1580156130ae575060005460ff166001145b6130ca5760405162461bcd60e51b8152600401610b269061556d565b6000805460ff1916600117905580156130ed576000805461ff0019166101001790555b6130f5614982565b6130ff84846149b1565b6131076149e2565b61311087612e01565b60e180546001600160a01b038089166001600160a01b03199283161790925560df8054928816929091169190911790558160cd61314d8282615954565b505060cd546040516370a0823160e01b815230600482015260009161010090046001600160a01b0316906370a082319060240160206040518083038186803b15801561319857600080fd5b505afa1580156131ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d0919061545e565b90506131db81614071565b60d280546001600160681b03909216600160681b026cffffffffffffffffffffffffff60681b1990921691909117905560d1805461ffff19166001179055801561325f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6001600160a01b0383166132ca5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610b26565b6001600160a01b03821661332b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610b26565b6001600160a01b0383811660008181526098602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006111878284615843565b60006133a48484612bdf565b9050600019811461340c57818110156133ff5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610b26565b61340c8484848403613268565b50505050565b6001600160a01b0383166134765760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610b26565b6001600160a01b0382166134d85760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610b26565b6001600160a01b038316600090815260976020526040902054818110156135505760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610b26565b6001600160a01b038085166000908152609760205260408082208585039055918516815290812080548492906135879084906156c8565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516135d391815260200190565b60405180910390a361340c565b60d1546001600160a01b038216600090815260c960205260408120909182918291829161ffff909116906136156002836157fe565b8154600191820b61ffff90911690910b13613631576000613643565b80546201000090046001600160681b03165b6001600160681b031694506136596002836157fe565b60010b81600001600f9054906101000a900461ffff1660010b1361367e576000613691565b8054600160881b90046001600160681b03165b6001600160681b031693506000806136a889612e7a565b90925090506136cd6136ba838361374d565b6136c26124dd565b60cd5460ff16614a11565b94506136dd85611cb0898961374d565b9750505050509193509193565b6000600183116137345760405162461bcd60e51b8152602060048201526015602482015274496e76616c6964206173736574506572536861726560581b6044820152606401610b26565b612a9a8361302961374685600a615737565b879061496a565b600061118782846156c8565b6137a0838383604051602401613771939291906154f3565b60408051601f198184030181529190526020810180516001600160e01b031663ca47c4eb60e01b179052614a73565b505050565b60008082116137e35760405162461bcd60e51b815260206004820152600a602482015269216e756d53686172657360b01b6044820152606401610b26565b33600090815260c960205260409020546201000090046001600160681b031615158061382d575033600090815260c96020526040902054600160881b90046001600160681b031615155b80613852575033600090815260c960205260409020600101546001600160801b031615155b1561386357613863600060016140bb565b61386c82614a94565b33600081815260cb60205260409020805471ffffffffffffffffffffffffffffffff00001916620100006001600160801b038616021790556138af903084613412565b60006138bd836136c26124dd565b604080518281526020810186905291925033917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a26139053084614ade565b600081116139475760405162461bcd60e51b815260206004820152600f60248201526e085dda5d1a191c985dd05b5bdd5b9d608a1b6044820152606401610b26565b60cd546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000916000916101009091046001600160a01b0316906370a082319060240160206040518083038186803b1580156139b357600080fd5b505afa1580156139c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139eb919061545e565b604051632e1a7d4d60e01b8152600481018590529091506001600160a01b03831690632e1a7d4d90602401600060405180830381600087803b158015613a3057600080fd5b505af1158015613a44573d6000803e3d6000fd5b505060cd546040516370a0823160e01b8152306004820152600093506101009091046001600160a01b031691506370a082319060240160206040518083038186803b158015613a9257600080fd5b505afa158015613aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613aca919061545e565b9050613adf33613ada838561338c565b613b86565b613b7c604051806060016040528060328152602001615c276032913985613b06848661338c565b866001600160a01b03166377c7b8fc6040518163ffffffff1660e01b815260040160206040518083038186803b158015613b3f57600080fd5b505afa158015613b53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b77919061545e565b613ef1565b5091949350505050565b60cd5461010090046001600160a01b03166137a0818484614c2c565b613be78282604051602401613bb89291906154d1565b60408051601f198184030181529190526020810180516001600160e01b0316632d839cb360e21b179052614a73565b5050565b6065546001600160a01b031633146123c15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b26565b60df546040516370a0823160e01b8152306004820152600091829182916001600160a01b039081169183918291829182917f0000000000000000000000000000000000000000000000000000000000000000909116906370a082319060240160206040518083038186803b158015613cbc57600080fd5b505afa158015613cd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cf4919061545e565b60d15460d254919250600091613d1d916001600160681b03600160781b9091048116911661565e565b6001600160681b031690506000613d3360995490565b60d15490915061ffff166000613d49858561338c565b9050613d5a8160e25460e354614c5c565b919d509b5096506000613d6d868961338c565b60d354909150613db690613d92908690600160801b90046001600160801b031661374d565b60d454613da99084906001600160801b031661374d565b60cd54889060ff1661435a565b9650613dc187614d11565b60d25460cd54613ddf916001600160681b031690899060ff166136ea565b98508660ca600085815260200190815260200160002081905550896001600160a01b03167f0a242f7ecaf711036ca770774ceffae28e60ef042ac113ddd187f2631db0c0068e8a86604051613e47939291909283526020830191909152604082015260600190565b60405180910390a2613e5a8360016156c8565b60d1805461ffff191661ffff929092169190911790556040805160608101909152602b808252613e949190615b4960208301398a89613759565b50505050505050613ea53083614de9565b8015613ee35760df54613ee3907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b031683614897565b509394929350600092915050565b61340c84848484604051602401613f0b9493929190615518565b60408051601f198184030181529190526020810180516001600160e01b031663a7a8785360e01b179052614a73565b61010654610108546040516303cea95560e21b81526001600160a01b0391821660048201526024810184905260006044820152306064820152911690630f3aa55490608401602060405180830381600087803b158015613f9957600080fd5b505af1158015613fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613be7919061545e565b600042816007613fe462015180846156e0565b613fef9060046156c8565b613ff991906158c1565b90506000600761400a836008615843565b61401491906158c1565b61402190620151806157df565b61402b90846156c8565b9050600061403c62015180836158c1565b6140469083615843565b614052906170806156c8565b9050808410612a9a5761406862093a80826156c8565b95945050505050565b6001600160681b03811115612e775760405162461bcd60e51b815260206004820152601060248201526f13dd995c999b1bddc81d5a5b9d0c4c0d60821b6044820152606401610b26565b33600090815260c960209081526040808320815160a081018352815461ffff8082168084526001600160681b03620100008404811697850197909752600160781b8304821695840195909552600160881b90910490941660608201526001918201546001600160801b0316608082015260d15490949316929161419591849160ca918591614148916156ab565b61ffff1681526020019081526020016000205460ca60008760400151600161417091906156ab565b61ffff16815260208101919091526040016000205460cd54879392919060ff166148ab565b9050836141a257846141a4565b805b9450846141b2575050505050565b808511156141f65760405162461bcd60e51b81526020600482015260116024820152704578636565647320617661696c61626c6560781b6044820152606401610b26565b614201600183615843565b835161ffff16101561422d5733600090815260c960205260409020805462010000600160781b03191690555b614238600183615843565b836040015161ffff1610156142685733600090815260c9602052604090208054600160881b600160f01b03191690555b61427185614a94565b61427b818661338c565b33600081815260c960205260409081902060010180546001600160801b03949094166001600160801b0319909416939093179092558451915190917fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929916142ee9189825261ffff16602082015260400190565b60405180910390a2614301303387613412565b5050505050565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008061436883600a615737565b9050600086116143785780614390565b61439086613029614389888861338c565b849061496a565b9695505050505050565b6040516001600160a01b038085166024830152831660448201526064810182905261340c9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614ec8565b60d15461ffff16600061441a84611cb0612616565b60cf549091506001600160681b03168111156144655760405162461bcd60e51b815260206004820152600a6024820152690457863656564206361760b41b6044820152606401610b26565b60ce54600160a01b900466ffffffffffffff168110156144be5760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610b26565b60408051858152602081018490526001600160a01b038516917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a26001600160a01b038316600090815260c960209081526040808320815160a081018352815461ffff8082168084526001600160681b03620100008404811697850197909752600160781b830490911694830194909452600160881b900490931660608401526001908101546001600160801b0316608084015291929161459391869160ca918591612f3d91906156ab565b8251909150869061ffff168514156145c95760208301516000906145c0906001600160681b03168961374d565b91506145f89050565b826040015161ffff168514156145f85760608301516000906145f4906001600160681b03168961374d565b9150505b61460181614071565b6001600160a01b038616600090815260c96020908152604091829020825160a081018452905461ffff8082168084526001600160681b03620100008404811695850195909552600160781b830490911694830194909452600160881b900490911660608201526001600160801b03841660808201529015806146875750805161ffff1686145b806146ea57506002861180156146ea5750604081015161ffff161580156146bc57506146b4600187615843565b815161ffff16105b806146ea5750604081015161ffff16158015906146ea57506146df600187615843565b816040015161ffff16105b156147185761ffff861681526001600160681b03821660208201526000604082018190526060820152614786565b604081015161ffff161580614734575085816040015161ffff16145b156147575761ffff861660408201526001600160681b0382166060820152614786565b60408101805161ffff90811683526060830180516001600160681b039081166020860152918916909252831690525b6001600160a01b038716600090815260c960209081526040808320845181549386015192860151606087015161ffff9283166effffffffffffffffffffffffffffff1990961695909517620100006001600160681b0395861602176effffffffffffffffffffffffffffff60781b1916600160781b929091168202600160881b600160f01b03191617600160881b948416949094029390931781556080850151600190910180546001600160801b0319166001600160801b0390921691909117905560d154614858929004168a61374d565b905061486381614071565b60d180546001600160681b03909216600160781b02600160781b600160e01b03199092169190911790555050505050505050565b6137a06001600160a01b0384168383614c2c565b6000806000876000015161ffff161180156148d457506148cc600187615843565b875161ffff16105b156148f4576148f187602001516001600160681b031686856136ea565b90505b6000876040015161ffff1611801561491d5750614912600187615843565b876040015161ffff16105b156149475761493a87606001516001600160681b031685856136ea565b61494490826156c8565b90505b608087015161495f906001600160801b03168261374d565b979650505050505050565b600061118782846157df565b600061118782846156e0565b600054610100900460ff166149a95760405162461bcd60e51b8152600401610b26906155dc565b6123c1614f9a565b600054610100900460ff166149d85760405162461bcd60e51b8152600401610b26906155dc565b613be78282614fc1565b600054610100900460ff16614a095760405162461bcd60e51b8152600401610b26906155dc565b6123c161500f565b600060018311614a5b5760405162461bcd60e51b8152602060048201526015602482015274496e76616c6964206173736574506572536861726560581b6044820152606401610b26565b612a9a614a6983600a615737565b613029868661496a565b80516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b6001600160801b03811115612e775760405162461bcd60e51b815260206004820152601060248201526f09eeccae4ccd8deee40ead2dce86264760831b6044820152606401610b26565b6001600160a01b038216614b3e5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610b26565b6001600160a01b03821660009081526097602052604090205481811015614bb25760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610b26565b6001600160a01b0383166000908152609760205260408120838303905560998054849290614be1908490615843565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6040516001600160a01b0383166024820152604481018290526137a090849063a9059cbb60e01b906064016143ce565b6000808080614c7f614c72620f424060646157df565b60d954613029908961496a565b90506000614ca8614c94620f424060646157df565b61302988614ca28c8761338c565b9061496a565b90506000614cb6838361374d565b9050614cde604051806060016040528060288152602001615c596028913960d9548b8a613ef1565b614d02604051806080016040528060458152602001615be260459139848484613ef1565b91989097509095509350505050565b60d35460cd54600091614d3a91600160801b9091046001600160801b031690849060ff16614a11565b60d4549091506001600160801b03168111614d56576000614d6d565b60d454614d6d9082906001600160801b031661338c565b60da5560408051608081019091526043808252614da49190615b9f602083013960d45460da5484916001600160801b031690613ef1565b60da5415613be75760df5460da54613be7917f0000000000000000000000000000000000000000000000000000000000000000916001600160a01b0390911690614897565b6001600160a01b038216614e3f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610b26565b8060996000828254614e5191906156c8565b90915550506001600160a01b03821660009081526097602052604081208054839290614e7e9084906156c8565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6000614f1d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661503f9092919063ffffffff16565b8051909150156137a05780806020019051810190614f3b9190615426565b6137a05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610b26565b600054610100900460ff166123045760405162461bcd60e51b8152600401610b26906155dc565b600054610100900460ff16614fe85760405162461bcd60e51b8152600401610b26906155dc565b8151614ffb90609a906020850190615143565b5080516137a090609b906020840190615143565b600054610100900460ff166150365760405162461bcd60e51b8152600401610b26906155dc565b6123c133614308565b6060612a9a8484600085856001600160a01b0385163b6150a15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b26565b600080866001600160a01b031685876040516150bd91906154a2565b60006040518083038185875af1925050503d80600081146150fa576040519150601f19603f3d011682016040523d82523d6000602084013e6150ff565b606091505b509150915061495f82828660608315615119575081611187565b8251156151295782518084602001fd5b8160405162461bcd60e51b8152600401610b2691906154be565b82805461514f90615886565b90600052602060002090601f01602090048101928261517157600085556151b7565b82601f1061518a57805160ff19168380011785556151b7565b828001600101855582156151b7579182015b828111156151b757825182559160200191906001019061519c565b506151c39291506151c7565b5090565b5b808211156151c357600081556001016151c8565b80356151e781615a4a565b919050565b600082601f8301126151fc578081fd5b813567ffffffffffffffff8082111561521757615217615901565b604051601f8301601f19908116603f0116810190828211818310171561523f5761523f615901565b81604052838152866020858801011115615257578485fd5b8360208701602083013792830160200193909352509392505050565b600060208284031215615284578081fd5b813561118781615a4a565b6000602082840312156152a0578081fd5b815161118781615a4a565b600080604083850312156152bd578081fd5b82356152c881615a4a565b915060208301356152d881615a4a565b809150509250929050565b600080600080600080600080888a036101a0811215615300578485fd5b893561530b81615a4a565b985060208a013561531b81615a4a565b975060408a013561532b81615a4a565b965060608a013567ffffffffffffffff80821115615347578687fd5b6153538d838e016151ec565b975060808c0135915080821115615368578687fd5b506153758c828d016151ec565b95505060c0609f1982011215615389578384fd5b5060a08901925061539d6101608a016151dc565b91506153ac6101808a016151dc565b90509295985092959890939650565b6000806000606084860312156153cf578283fd5b83356153da81615a4a565b925060208401356153ea81615a4a565b929592945050506040919091013590565b6000806040838503121561540d578182fd5b823561541881615a4a565b946020939093013593505050565b600060208284031215615437578081fd5b81518015158114611187578182fd5b600060208284031215615457578081fd5b5035919050565b60006020828403121561546f578081fd5b5051919050565b6000815180845261548e81602086016020860161585a565b601f01601f19169290920160200192915050565b600082516154b481846020870161585a565b9190910192915050565b6020815260006111876020830184615476565b6040815260006154e46040830185615476565b90508260208301529392505050565b6060815260006155066060830186615476565b60208301949094525060400152919050565b60808152600061552b6080830187615476565b6020830195909552506040810192909252606090910152919050565b6020808252600c908201526b1d5b985d5d1a1bdc9a5cd95960a21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526007908201526608585b5bdd5b9d60ca1b604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60006001600160681b03808316818516808303821115615680576156806158d5565b01949350505050565b60006001600160801b03808316818516808303821115615680576156806158d5565b600061ffff808316818516808303821115615680576156806158d5565b600082198211156156db576156db6158d5565b500190565b6000826156ef576156ef6158eb565b500490565b600181815b8085111561572f578160001904821115615715576157156158d5565b8085161561572257918102915b93841c93908002906156f9565b509250929050565b6000611187838360008261574d57506001610d17565b8161575a57506000610d17565b8160018114615770576002811461577a57615796565b6001915050610d17565b60ff84111561578b5761578b6158d5565b50506001821b610d17565b5060208310610133831016604e8410600b84101617156157b9575081810a610d17565b6157c383836156f4565b80600019048211156157d7576157d76158d5565b029392505050565b60008160001904831182151516156157f9576157f96158d5565b500290565b60008160010b8360010b82811281617fff1901831281151615615823576158236158d5565b81617fff018313811615615839576158396158d5565b5090039392505050565b600082821015615855576158556158d5565b500390565b60005b8381101561587557818101518382015260200161585d565b8381111561340c5750506000910152565b600181811c9082168061589a57607f821691505b602082108114156158bb57634e487b7160e01b600052602260045260246000fd5b50919050565b6000826158d0576158d06158eb565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60008135610d1781615a4a565b600081356001600160681b0381168114610d17578182fd5b6000813566ffffffffffffff81168114610d17578182fd5b813560ff811680821461596657600080fd5b825460ff198116821784559150602084013561598181615a4a565b6001600160a81b0319929092161760089190911b610100600160a81b0316178155600181016159d26159b560408501615917565b82546001600160a01b0319166001600160a01b0391909116178255565b615a0b6159e16060850161593c565b82805466ffffffffffffff60a01b191660a09290921b66ffffffffffffff60a01b16919091179055565b50615a3c615a1b60808401615924565b600283016001600160681b0382166001600160681b03198254161781555050565b60a082013560038201555050565b6001600160a01b0381168114612e7757600080fdfe425053202573206c617374526f756e64627073202573206d6f6f5969656c645368617265732025734375727262616c616e636520257320756e6c6f636b6564416d6f756e7420257320736574746c6564416d6f756e742025734465706c6f79656462616c616e6365202573206c6f636b6564416d6f756e7420257320736574746c6564416d6f756e742025734d6f6f5969656c6453686172657320257320476c705969656c64536861726573202573206375727262616c616e636520257357574954484452415757575720646564756374416d6f756e74202573207368617265735769746864726177434c4f5345454545206d696e74536861726573202573206e657750726963655065725368617265202573204445504f534954545420425053202573206e6577546f6b656e73526563656976656420257320626c6f636b434c4f534545207769746864726177416d6f756e7441744e6577505053202573207769746864726177416d6f756e7420257320756e4163636f756e7465647969656c6446454545205f706572666f726d616e6365466565496e4173736574202573205f6d616e6167656d656e74466565496e4173736574202573205f7661756c744665652025732057495448445241575757207769746864726177416d6f756e74202573207472616e73666572416d6f756e74202573204250534645454520736574746c6564416d6f756e74202573206465706c6f796564416d6f756e7420257320a264697066735822122029afbe04a9c21cd25fbe507a0bde8c872615aaf3460776cfc5f33b5b927e869c64736f6c634300080400330000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103af5760003560e01c80637df1f1b9116101f4578063aced16611161011a578063db006a75116100ad578063eb70e4981161007c578063eb70e49814610a6e578063f2fde38b14610a82578063f656ba5114610a95578063fe56e23214610abd57600080fd5b8063db006a7514610a2d578063dd62ed3e14610a40578063e68d356914610a53578063e74b981b14610a5b57600080fd5b8063ce7c2ac2116100e9578063ce7c2ac2146109c1578063d164cc15146109d4578063d294cb0f146109e7578063d359f82c14610a1a57600080fd5b8063aced166114610980578063ad7a672f14610993578063b6b55f251461099b578063c762d5f7146109ae57600080fd5b806395d89b4111610192578063a457c2d711610161578063a457c2d71461093e578063a54c889914610951578063a6f7f5d614610964578063a9059cbb1461096d57600080fd5b806395d89b411461080057806399530b06146108085780639fcc2d7514610810578063a083ff17146108ac57600080fd5b806387788782116101ce57806387788782146107c05780638da5cb5b146107c95780638df82800146107da57806394d9c9c7146107ed57600080fd5b80637df1f1b91461077a578063852986891461078d57806387153eb1146107a057600080fd5b80633a43527f116102d95780635a659d261161027757806370897b231161024657806370897b23146106df57806370a08231146106f2578063715018a61461071b5780637a9262a21461072357600080fd5b80635a659d26146106125780635b7f415c146106255780636719b2ee146106345780636f31ab34146106d757600080fd5b806346904840116102b357806346904840146105d857806347786d37146105eb5780634b2431d9146105fe578063503c70aa1461060857600080fd5b80633a43527f1461059f5780633f90916a146105bf57806343d726d6146105d057600080fd5b806323b872dd116103515780632e1a7d4d116103205780632e1a7d4d14610553578063313ce56714610566578063355274ea1461057b578063395093511461058c57600080fd5b806323b872dd1461046d5780632728f333146104805780632775d01c14610538578063278a30121461054b57600080fd5b8063095ea7b31161038d578063095ea7b314610422578063125562de14610445578063155f586d1461044d57806318160ddd1461046557600080fd5b80630342389c146103b457806304ac00c9146103c957806306fdde031461040d575b600080fd5b6103c76103c23660046152e3565b610ad0565b005b6103f07f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc81565b6040516001600160a01b0390911681526020015b60405180910390f35b610415610c71565b60405161040491906154be565b6104356104303660046153fb565b610d03565b6040519015158152602001610404565b6103c7610d1d565b6104576101045481565b604051908152602001610404565b609954610457565b61043561047b3660046153bb565b611168565b60d15460d25460d35460d4546104dd9361ffff8116936001600160681b03620100008304811694600160781b90930481169382821693600160681b909304909116916001600160801b0380821692600160801b9092048116911688565b6040805161ffff90991689526001600160681b0397881660208a0152958716958801959095529285166060870152931660808501526001600160801b0392831660a0850152821660c08401521660e082015261010001610404565b6103c7610546366004615446565b61118e565b6103c76118eb565b6103c7610561366004615446565b6118fa565b60cd5460405160ff9091168152602001610404565b60cf546001600160681b0316610457565b61043561059a3660046153fb565b611924565b6104576105ad366004615273565b60cc6020526000908152604090205481565b60d3546001600160801b0316610457565b6103c7611946565b60df546103f0906001600160a01b031681565b6103c76105f9366004615446565b612115565b6104576101035481565b6104576101025481565b6103c7610620366004615273565b6121c8565b610457670de0b6b3a764000081565b610691610642366004615273565b60c9602052600090815260409020805460019091015461ffff808316926001600160681b03620100008204811693600160781b830490931692600160881b90920416906001600160801b031685565b6040805161ffff96871681526001600160681b03958616602082015295909316928501929092529190911660608301526001600160801b0316608082015260a001610404565b6103c76122cd565b6103c76106ed366004615446565b61230a565b610457610700366004615273565b6001600160a01b031660009081526097602052604090205490565b6103c76123af565b610758610731366004615273565b60cb6020526000908152604090205461ffff8116906201000090046001600160801b031682565b6040805161ffff90931683526001600160801b03909116602083015201610404565b60e0546103f0906001600160a01b031681565b6103c761079b366004615446565b6123c3565b6104576107ae366004615446565b60ca6020526000908152604090205481565b61045760e25481565b6065546001600160a01b03166103f0565b6103c76107e8366004615446565b61240b565b6103c76107fb366004615273565b61245d565b6104156124ce565b6104576124dd565b60cd5460ce5460cf5460d05461085c9360ff8116936001600160a01b036101009092048216939181169266ffffffffffffff600160a01b90920491909116916001600160681b03169086565b6040805160ff9790971687526001600160a01b039586166020880152939094169285019290925266ffffffffffffff1660608401526001600160681b0316608083015260a082015260c001610404565b60d55460d65460d75460d85460d95460da5460db5460dc5460dd5460de546108e799989796959493929160ff8082169261010090920416908b565b604080519b8c5260208c019a909a52988a01979097526060890195909552608088019390935260a087019190915260c086015260e08501521515610100840152151561012083015261014082015261016001610404565b61043561094c3660046153fb565b612537565b6103c761095f366004615446565b6125bd565b61045760e35481565b61043561097b3660046153fb565b612608565b60e1546103f0906001600160a01b031681565b610457612616565b6103c76109a9366004615446565b6126b5565b6103c76109bc366004615273565b612a10565b6104576109cf366004615273565b612a7d565b6103c76109e2366004615273565b612aa2565b6109fa6109f5366004615273565b612b0f565b604080519485526020850193909352918301526060820152608001610404565b6103c7610a28366004615446565b612b2d565b6103c7610a3b366004615446565b612b72565b610457610a4e3660046152ab565b612bdf565b6103c7612c0a565b6103c7610a69366004615273565b612d30565b610105546103f0906001600160a01b031681565b6103c7610a90366004615273565b612e01565b610aa8610aa3366004615273565b612e7a565b60408051928352602083019190915201610404565b6103c7610acb366004615446565b612fb5565b600054610100900460ff1615808015610af05750600054600160ff909116105b80610b0a5750303b158015610b0a575060005460ff166001145b610b2f5760405162461bcd60e51b8152600401610b269061556d565b60405180910390fd5b6000805460ff191660011790558015610b52576000805461ff0019166101001790555b61010680546001600160a01b0319166001600160a01b03851690811790915560408051633e9b6c6f60e21b8152905163fa6db1bc916004808201926020929091908290030181600087803b158015610ba957600080fd5b505af1158015610bbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be1919061528f565b61010780546001600160a01b03199081166001600160a01b03938416179091556101088054909116918416919091179055610c20898989898989613074565b8015610c66576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b6060609a8054610c8090615886565b80601f0160208091040260200160405190810160405280929190818152602001828054610cac90615886565b8015610cf95780601f10610cce57610100808354040283529160200191610cf9565b820191906000526020600020905b815481529060010190602001808311610cdc57829003601f168201915b5050505050905090565b600033610d11818585613268565b60019150505b92915050565b60026001541415610d405760405162461bcd60e51b8152600401610b2690615627565b600260015560e0546000906001600160a01b03163314610d725760405162461bcd60e51b8152600401610b2690615547565b60dc54421015610db35760405162461bcd60e51b815260206004820152600c60248201526b6561726c7920736574746c6560a01b6044820152606401610b26565b60dd5460ff16158015610dcd575060dd54610100900460ff165b610e0b5760405162461bcd60e51b815260206004820152600f60248201526e185b1c9958591e481cd95d1d1b1959608a1b6044820152606401610b26565b60cd546040516370a0823160e01b815230600482015260009161010090046001600160a01b0316906370a082319060240160206040518083038186803b158015610e5457600080fd5b505afa158015610e68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8c919061545e565b905060008111610eae5760405162461bcd60e51b8152600401610b26906155bb565b60cd5460405163095ea7b360e01b81526001600160a01b037f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc818116600484015260248301859052926101009004169063095ea7b390604401602060405180830381600087803b158015610f2157600080fd5b505af1158015610f35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f599190615426565b506040516370a0823160e01b81523060048201527f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc6001600160a01b0316906370a082319060240160206040518083038186803b158015610fb957600080fd5b505afa158015610fcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff1919061545e565b60405163b6b55f2560e01b8152600481018490529093506001600160a01b0382169063b6b55f2590602401600060405180830381600087803b15801561103657600080fd5b505af115801561104a573d6000803e3d6000fd5b50506040516370a0823160e01b81523060048201526110f192508591506001600160a01b037f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc16906370a082319060240160206040518083038186803b1580156110b357600080fd5b505afa1580156110c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110eb919061545e565b9061338c565b60d9819055600060d881905560dd805460ff1916600117905560e05460d754604080519182526020820193909352918201929092526001600160a01b03909116907f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe7949060600160405180910390a250506001805550565b600033611176858285613398565b611181858585613412565b60019150505b9392505050565b600260015414156111b15760405162461bcd60e51b8152600401610b2690615627565b6002600190815560d1546000918291829182918291829182918291829161ffff9091169081900b156112395760405162461bcd60e51b815260206004820152602b60248201527f66756e64732077696c6c2062652072656c656173656420616674657220696e7460448201526a195c9b985b08185d591a5d60aa1b6064820152608401610b26565b33600081815260c96020526040902090611252906135e0565b9199509750955093508b84101561129c5760405162461bcd60e51b815260206004820152600e60248201526d0858985b185b98d9505b5bdd5b9d60921b6044820152606401610b26565b8b92508515611340578b86116112b257856112b4565b8b5b60d154825491995061ffff908116600160781b90920416146112e2576112da888b6156c8565b9950896112f0565b6112ec888a6156c8565b9850885b50805461130d90600160881b90046001600160681b03168961338c565b81546001600160681b0391909116600160881b02600160881b600160f01b031990911617815561133d888c6156c8565b9a505b8a8c11801561134f5750600087115b156113f65761135e8b8d615843565b871161136a5786611374565b6113748b8d615843565b60d154825491995061ffff91821691161461139b57611393888b6156c8565b9950896113a9565b6113a5888a6156c8565b9850885b5080546113c5906201000090046001600160681b03168961338c565b81546001600160681b0391909116620100000262010000600160781b03199091161781556113f3888c6156c8565b9a505b8a8c1115611568576114088b8d615843565b97506000611423896114186124dd565b60cd5460ff166136ea565b905060008061143133612e7a565b90925090506000611442838361374d565b905061144f8460016156c8565b811415611468576114616001856156c8565b9350611488565b611473600185615843565b81141561148857611485600185615843565b93505b6114ab6040518060600160405280602b8152602001615b1e602b91398d86613759565b6114b4846137a5565b5060d380548591906010906114da908490600160801b90046001600160801b0316615689565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508b60d160030160008282829054906101000a90046001600160801b03166115259190615689565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508b8f61155591906156c8565b9e506115618c88615843565b9650505050505b8b8b146115875760405162461bcd60e51b8152600401610b26906155bb565b60d1546115a490600160781b90046001600160681b03168a61338c565b60d180546001600160681b0392909216600160781b02600160781b600160e01b031983168117909155600161ffff918216919092161711156116515760d2546115f6906001600160681b03168b61338c565b60d280546001600160681b0319166001600160681b0392831617905560d1546116279162010000909104168b61338c565b60d180546001600160681b0392909216620100000262010000600160781b03199092169190911790555b82156118d95760cd546040516370a0823160e01b81523060048201527f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc916000916101009091046001600160a01b0316906370a082319060240160206040518083038186803b1580156116c357600080fd5b505afa1580156116d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116fb919061545e565b604051632e1a7d4d60e01b8152600481018790529091506001600160a01b03831690632e1a7d4d90602401600060405180830381600087803b15801561174057600080fd5b505af1158015611754573d6000803e3d6000fd5b505060cd546040516370a0823160e01b8152306004820152600093506101009091046001600160a01b031691506370a082319060240160206040518083038186803b1580156117a257600080fd5b505afa1580156117b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117da919061545e565b905060006117e8828461338c565b90506117f43382613b86565b6118926040518060400160405280600c81526020016b494e5354414e54542042505360a01b815250856001600160a01b03166377c7b8fc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561185557600080fd5b505afa158015611869573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188d919061545e565b613ba2565b60d1546040805189815261ffff909216602083015233917fab2daf3c146ca6416cbccd2a86ed2ba995e171ef6319df14a38aef01403a9c96910160405180910390a2505050505b50506001805550505050505050505050565b6118f3613beb565b600060de55565b6002600154141561191d5760405162461bcd60e51b8152600401610b2690615627565b5060018055565b600033610d118185856119378383612bdf565b61194191906156c8565b613268565b600260015414156119695760405162461bcd60e51b8152600401610b2690615627565b600260015560e1546001600160a01b031633146119b25760405162461bcd60e51b815260206004820152600760248201526610b5b2b2b832b960c91b6044820152606401610b26565b60dd5460ff16806119cb575060d154600361ffff909116105b611a065760405162461bcd60e51b815260206004820152600c60248201526b149bdd5b990818db1bdcd95960a21b6044820152606401610b26565b611a75604051806101a001604052806000815260200160008152602001600061ffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b611a7d613c45565b5061016083015261018082015260d15460d280546001600160681b0319166001600160681b03600160781b84048116918217909255611ac5929091620100009091041661565e565b60d1805462010000600160e01b031916620100006001600160681b039390931692909202600160781b600160e01b03191691909117905560408051631df1ee3f60e21b815290517f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc916001600160a01b038316916377c7b8fc91600480820192602092909190829003018186803b158015611b5f57600080fd5b505afa158015611b73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b97919061545e565b60208301526040516370a0823160e01b81523060048201526001600160a01b038216906370a082319060240160206040518083038186803b158015611bdb57600080fd5b505afa158015611bef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c13919061545e565b606083015260d15461ffff166040830152610180820151610160830151611c399161374d565b61014083015260408051606081019091526031808252611c789190615a886020830139606084015160d25460d9546001600160681b0390911690613ef1565b60d95460d254611c93916001600160681b039091169061374d565b60da546101408401516060850151611cb69291611cb0919061374d565b9061374d565b106120655760d95460d25460da546101408501516060860151611cef94936110eb936001600160681b03909116928492611cb09161374d565b60c083015260db805460808401819052602084015191829055600091611d159190615843565b905082602001518360c0015182611d2c91906157df565b611d3691906156e0565b61010084015260408051606081019091526028808252611d6e9190615a60602083013984602001518560800151866101000151613ef1565b611da6604051806060016040528060338152602001615ab96033913960c085015160d25460d9546001600160681b0390911690613ef1565b6002836040015161ffff16118015611dc357506000836101000151115b1561205f57670de0b6b3a76400008360200151846101000151611de691906157df565b611df091906156e0565b610120840152610100830151604051632e1a7d4d60e01b815260048101919091526001600160a01b03831690632e1a7d4d90602401600060405180830381600087803b158015611e3f57600080fd5b505af1158015611e53573d6000803e3d6000fd5b50505050611e89604051806060016040528060328152602001615aec603291398461010001518561012001518660600151613ef1565b610108546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015611ece57600080fd5b505afa158015611ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f06919061545e565b9050611f16846101200151613f3a565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a082319060240160206040518083038186803b158015611f5557600080fd5b505afa158015611f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8d919061545e565b6060850152610108546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015611fd757600080fd5b505afa158015611feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200f919061545e565b905061201b8282615843565b60d681905560408051808201909152601681527555534443202573206375727262616c616e636520257360501b6020820152606087015161205c9290613759565b50505b5061206b565b600060d6555b60d380546001600160801b0316905560d480546001600160801b0319169055600060da5560dd805461ffff191690556120a2613fd1565b60dc5560d65461010083015161012084015160c085015160408087015181519586526020860194909452840191909152606083015261ffff1660808201527f136258a39190042d2cd2e39a244f43d39a46be4417d5895b5419169f659fa12d9060a00160405180910390a1505060018055565b61211d613beb565b600081116121575760405162461bcd60e51b81526020600482015260076024820152660216e65774361760cc1b6044820152606401610b26565b61216081614071565b60cf54604080516001600160681b039092168252602082018390527f5f86edbb9d92228a9edc3f0ebc0f001bda1ea345ac7335e0eeef3504b31d1a1c910160405180910390a160cf80546001600160681b0319166001600160681b0392909216919091179055565b6121d0613beb565b6001600160a01b03811661221a5760405162461bcd60e51b815260206004820152601160248201527076616c696420676c70206164647265737360781b6044820152606401610b26565b61010680546001600160a01b0319166001600160a01b03831690811790915560408051633e9b6c6f60e21b8152905163fa6db1bc916004808201926020929091908290030181600087803b15801561227157600080fd5b505af1158015612285573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a9919061528f565b61010780546001600160a01b0319166001600160a01b039290921691909117905550565b600260015414156122f05760405162461bcd60e51b8152600401610b2690615627565b6002600181905550612304600060016140bb565b60018055565b612312613beb565b612320620f424060646157df565b811061236e5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420706572666f726d616e6365206665650000000000000000006044820152606401610b26565b60e25460408051918252602082018390527f24867dfb6fcb9970a07be21024956524abe7a1837faa903ff0e99aaa40cf893e910160405180910390a160e255565b6123b7613beb565b6123c16000614308565b565b6123cb613beb565b600081116124065760405162461bcd60e51b8152602060048201526008602482015267085a5b9d985b1a5960c21b6044820152606401610b26565b60d055565b6002600154141561242e5760405162461bcd60e51b8152600401610b2690615627565b600260015560e0546001600160a01b0316331461191d5760405162461bcd60e51b8152600401610b2690615547565b612465613beb565b6001600160a01b0381166124ab5760405162461bcd60e51b815260206004820152600d60248201526c10afb732bba7b139b2b93b32b960991b6044820152606401610b26565b61010580546001600160a01b0319166001600160a01b0392909216919091179055565b6060609b8054610c8090615886565b60d15460d2546000918291612505916001600160681b03600160781b9091048116911661565e565b6001600160681b0316905061253161251c60995490565b612524612616565b60cd54849060ff1661435a565b91505090565b600033816125458286612bdf565b9050838110156125a55760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610b26565b6125b28286868403613268565b506001949350505050565b6125c5613beb565b806126025760405162461bcd60e51b815260206004820152600d60248201526c215f61756374696f6e54696d6560981b6044820152606401610b26565b61010455565b600033610d11818585613412565b6040516370a0823160e01b81523060048201526000907f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc6001600160a01b0316906370a082319060240160206040518083038186803b15801561267857600080fd5b505afa15801561268c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b0919061545e565b905090565b600260015414156126d85760405162461bcd60e51b8152600401610b2690615627565b6002600155806126fa5760405162461bcd60e51b8152600401610b26906155bb565b60cd546127179061010090046001600160a01b031633308461439a565b6040516370a0823160e01b81523060048201527f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc906000906001600160a01b038316906370a082319060240160206040518083038186803b15801561277b57600080fd5b505afa15801561278f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b3919061545e565b60cd5460405163095ea7b360e01b81526001600160a01b037f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc81166004830152602482018790529293506101009091049091169063095ea7b390604401602060405180830381600087803b15801561282a57600080fd5b505af115801561283e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128629190615426565b5060405163b6b55f2560e01b8152600481018490526001600160a01b0383169063b6b55f2590602401600060405180830381600087803b1580156128a557600080fd5b505af11580156128b9573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092507f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc6001600160a01b031691506370a082319060240160206040518083038186803b15801561291f57600080fd5b505afa158015612933573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612957919061545e565b90506000612965828461338c565b90506129718133614405565b612a056040518060600160405280602b8152602001615b74602b9139856001600160a01b03166377c7b8fc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156129c657600080fd5b505afa1580156129da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129fe919061545e565b8343613ef1565b505060018055505050565b612a18613beb565b6001600160a01b038116612a5b5760405162461bcd60e51b815260206004820152600a60248201526910afb137b93937bbb2b960b11b6044820152606401610b26565b60e080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806000612a8b84612e7a565b9092509050612a9a828261374d565b949350505050565b612aaa613beb565b6001600160a01b038116612aed5760405162461bcd60e51b815260206004820152600a60248201526910b732bba5b2b2b832b960b11b6044820152606401610b26565b60e180546001600160a01b0319166001600160a01b0392909216919091179055565b600080600080612b1e856135e0565b93509350935093509193509193565b612b35613beb565b80612b6d5760405162461bcd60e51b8152602060048201526008602482015267215f65787069727960c01b6044820152606401610b26565b60dc55565b60026001541415612b955760405162461bcd60e51b8152600401610b2690615627565b600260015580612bd45760405162461bcd60e51b815260206004820152600a602482015269216e756d53686172657360b01b6044820152606401610b26565b61191d8160006140bb565b6001600160a01b03918216600090815260986020908152604080832093909416825291909152205490565b60026001541415612c2d5760405162461bcd60e51b8152600401610b2690615627565b600260015560d65415612cd05760dd54610100900460ff1615612c855760405162461bcd60e51b815260206004820152601060248201526f185b1c9958591e48189bdc9c9bddd95960821b6044820152606401610b26565b60e0546001600160a01b03163314612caf5760405162461bcd60e51b8152600401610b2690615547565b6101085460e05460d654612cd0926001600160a01b03908116921690614897565b60e05460d65460408051918252600060208301526001600160a01b03909216917fe1979fe4c35e0cef342fef5668e2c8e7a7e9f5d5d1ca8fee0ac6c427fa4153af910160405180910390a260dd805461ff00191661010017905560018055565b612d38613beb565b6001600160a01b038116612d815760405162461bcd60e51b815260206004820152601060248201526f085b995dd19959549958da5c1a595b9d60821b6044820152606401610b26565b60df546001600160a01b0382811691161415612ddf5760405162461bcd60e51b815260206004820152601860248201527f4d757374206265206e657720666565526563697069656e7400000000000000006044820152606401610b26565b60df80546001600160a01b0319166001600160a01b0392909216919091179055565b612e09613beb565b6001600160a01b038116612e6e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b26565b612e7781614308565b50565b6001600160a01b038116600090815260c960209081526040808320815160a081018352815461ffff8082168084526001600160681b03620100008404811697850197909752600160781b830490911694830194909452600160881b900490931660608401526001908101546001600160801b031660808401528392911015612f1a575050506001600160a01b031660009081526097602052604081205491565b60d1548151600091612f8a9161ffff9091169060ca908490612f3d9060016156ab565b61ffff1681526020019081526020016000205460ca600086604001516001612f6591906156ab565b61ffff16815260208101919091526040016000205460cd54869392919060ff166148ab565b9050612fab856001600160a01b031660009081526097602052604090205490565b9590945092505050565b612fbd613beb565b612fcb620f424060646157df565b81106130125760405162461bcd60e51b8152602060048201526016602482015275496e76616c6964206d616e6167656d656e742066656560501b6044820152606401610b26565b600061302f63031ba30961302984620f424061496a565b90614976565b60e35460408051918252602082018590529192507f4e874b007ab14f7e263baefd44951834c8266f4f224d1092e49e9c254354cc54910160405180910390a160e35550565b600054610100900460ff16158080156130945750600054600160ff909116105b806130ae5750303b1580156130ae575060005460ff166001145b6130ca5760405162461bcd60e51b8152600401610b269061556d565b6000805460ff1916600117905580156130ed576000805461ff0019166101001790555b6130f5614982565b6130ff84846149b1565b6131076149e2565b61311087612e01565b60e180546001600160a01b038089166001600160a01b03199283161790925560df8054928816929091169190911790558160cd61314d8282615954565b505060cd546040516370a0823160e01b815230600482015260009161010090046001600160a01b0316906370a082319060240160206040518083038186803b15801561319857600080fd5b505afa1580156131ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d0919061545e565b90506131db81614071565b60d280546001600160681b03909216600160681b026cffffffffffffffffffffffffff60681b1990921691909117905560d1805461ffff19166001179055801561325f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6001600160a01b0383166132ca5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610b26565b6001600160a01b03821661332b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610b26565b6001600160a01b0383811660008181526098602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006111878284615843565b60006133a48484612bdf565b9050600019811461340c57818110156133ff5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610b26565b61340c8484848403613268565b50505050565b6001600160a01b0383166134765760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610b26565b6001600160a01b0382166134d85760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610b26565b6001600160a01b038316600090815260976020526040902054818110156135505760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610b26565b6001600160a01b038085166000908152609760205260408082208585039055918516815290812080548492906135879084906156c8565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516135d391815260200190565b60405180910390a361340c565b60d1546001600160a01b038216600090815260c960205260408120909182918291829161ffff909116906136156002836157fe565b8154600191820b61ffff90911690910b13613631576000613643565b80546201000090046001600160681b03165b6001600160681b031694506136596002836157fe565b60010b81600001600f9054906101000a900461ffff1660010b1361367e576000613691565b8054600160881b90046001600160681b03165b6001600160681b031693506000806136a889612e7a565b90925090506136cd6136ba838361374d565b6136c26124dd565b60cd5460ff16614a11565b94506136dd85611cb0898961374d565b9750505050509193509193565b6000600183116137345760405162461bcd60e51b8152602060048201526015602482015274496e76616c6964206173736574506572536861726560581b6044820152606401610b26565b612a9a8361302961374685600a615737565b879061496a565b600061118782846156c8565b6137a0838383604051602401613771939291906154f3565b60408051601f198184030181529190526020810180516001600160e01b031663ca47c4eb60e01b179052614a73565b505050565b60008082116137e35760405162461bcd60e51b815260206004820152600a602482015269216e756d53686172657360b01b6044820152606401610b26565b33600090815260c960205260409020546201000090046001600160681b031615158061382d575033600090815260c96020526040902054600160881b90046001600160681b031615155b80613852575033600090815260c960205260409020600101546001600160801b031615155b1561386357613863600060016140bb565b61386c82614a94565b33600081815260cb60205260409020805471ffffffffffffffffffffffffffffffff00001916620100006001600160801b038616021790556138af903084613412565b60006138bd836136c26124dd565b604080518281526020810186905291925033917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a26139053084614ade565b600081116139475760405162461bcd60e51b815260206004820152600f60248201526e085dda5d1a191c985dd05b5bdd5b9d608a1b6044820152606401610b26565b60cd546040516370a0823160e01b81523060048201527f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc916000916101009091046001600160a01b0316906370a082319060240160206040518083038186803b1580156139b357600080fd5b505afa1580156139c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139eb919061545e565b604051632e1a7d4d60e01b8152600481018590529091506001600160a01b03831690632e1a7d4d90602401600060405180830381600087803b158015613a3057600080fd5b505af1158015613a44573d6000803e3d6000fd5b505060cd546040516370a0823160e01b8152306004820152600093506101009091046001600160a01b031691506370a082319060240160206040518083038186803b158015613a9257600080fd5b505afa158015613aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613aca919061545e565b9050613adf33613ada838561338c565b613b86565b613b7c604051806060016040528060328152602001615c276032913985613b06848661338c565b866001600160a01b03166377c7b8fc6040518163ffffffff1660e01b815260040160206040518083038186803b158015613b3f57600080fd5b505afa158015613b53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b77919061545e565b613ef1565b5091949350505050565b60cd5461010090046001600160a01b03166137a0818484614c2c565b613be78282604051602401613bb89291906154d1565b60408051601f198184030181529190526020810180516001600160e01b0316632d839cb360e21b179052614a73565b5050565b6065546001600160a01b031633146123c15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b26565b60df546040516370a0823160e01b8152306004820152600091829182916001600160a01b039081169183918291829182917f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc909116906370a082319060240160206040518083038186803b158015613cbc57600080fd5b505afa158015613cd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cf4919061545e565b60d15460d254919250600091613d1d916001600160681b03600160781b9091048116911661565e565b6001600160681b031690506000613d3360995490565b60d15490915061ffff166000613d49858561338c565b9050613d5a8160e25460e354614c5c565b919d509b5096506000613d6d868961338c565b60d354909150613db690613d92908690600160801b90046001600160801b031661374d565b60d454613da99084906001600160801b031661374d565b60cd54889060ff1661435a565b9650613dc187614d11565b60d25460cd54613ddf916001600160681b031690899060ff166136ea565b98508660ca600085815260200190815260200160002081905550896001600160a01b03167f0a242f7ecaf711036ca770774ceffae28e60ef042ac113ddd187f2631db0c0068e8a86604051613e47939291909283526020830191909152604082015260600190565b60405180910390a2613e5a8360016156c8565b60d1805461ffff191661ffff929092169190911790556040805160608101909152602b808252613e949190615b4960208301398a89613759565b50505050505050613ea53083614de9565b8015613ee35760df54613ee3907f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc906001600160a01b031683614897565b509394929350600092915050565b61340c84848484604051602401613f0b9493929190615518565b60408051601f198184030181529190526020810180516001600160e01b031663a7a8785360e01b179052614a73565b61010654610108546040516303cea95560e21b81526001600160a01b0391821660048201526024810184905260006044820152306064820152911690630f3aa55490608401602060405180830381600087803b158015613f9957600080fd5b505af1158015613fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613be7919061545e565b600042816007613fe462015180846156e0565b613fef9060046156c8565b613ff991906158c1565b90506000600761400a836008615843565b61401491906158c1565b61402190620151806157df565b61402b90846156c8565b9050600061403c62015180836158c1565b6140469083615843565b614052906170806156c8565b9050808410612a9a5761406862093a80826156c8565b95945050505050565b6001600160681b03811115612e775760405162461bcd60e51b815260206004820152601060248201526f13dd995c999b1bddc81d5a5b9d0c4c0d60821b6044820152606401610b26565b33600090815260c960209081526040808320815160a081018352815461ffff8082168084526001600160681b03620100008404811697850197909752600160781b8304821695840195909552600160881b90910490941660608201526001918201546001600160801b0316608082015260d15490949316929161419591849160ca918591614148916156ab565b61ffff1681526020019081526020016000205460ca60008760400151600161417091906156ab565b61ffff16815260208101919091526040016000205460cd54879392919060ff166148ab565b9050836141a257846141a4565b805b9450846141b2575050505050565b808511156141f65760405162461bcd60e51b81526020600482015260116024820152704578636565647320617661696c61626c6560781b6044820152606401610b26565b614201600183615843565b835161ffff16101561422d5733600090815260c960205260409020805462010000600160781b03191690555b614238600183615843565b836040015161ffff1610156142685733600090815260c9602052604090208054600160881b600160f01b03191690555b61427185614a94565b61427b818661338c565b33600081815260c960205260409081902060010180546001600160801b03949094166001600160801b0319909416939093179092558451915190917fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929916142ee9189825261ffff16602082015260400190565b60405180910390a2614301303387613412565b5050505050565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008061436883600a615737565b9050600086116143785780614390565b61439086613029614389888861338c565b849061496a565b9695505050505050565b6040516001600160a01b038085166024830152831660448201526064810182905261340c9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614ec8565b60d15461ffff16600061441a84611cb0612616565b60cf549091506001600160681b03168111156144655760405162461bcd60e51b815260206004820152600a6024820152690457863656564206361760b41b6044820152606401610b26565b60ce54600160a01b900466ffffffffffffff168110156144be5760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610b26565b60408051858152602081018490526001600160a01b038516917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a26001600160a01b038316600090815260c960209081526040808320815160a081018352815461ffff8082168084526001600160681b03620100008404811697850197909752600160781b830490911694830194909452600160881b900490931660608401526001908101546001600160801b0316608084015291929161459391869160ca918591612f3d91906156ab565b8251909150869061ffff168514156145c95760208301516000906145c0906001600160681b03168961374d565b91506145f89050565b826040015161ffff168514156145f85760608301516000906145f4906001600160681b03168961374d565b9150505b61460181614071565b6001600160a01b038616600090815260c96020908152604091829020825160a081018452905461ffff8082168084526001600160681b03620100008404811695850195909552600160781b830490911694830194909452600160881b900490911660608201526001600160801b03841660808201529015806146875750805161ffff1686145b806146ea57506002861180156146ea5750604081015161ffff161580156146bc57506146b4600187615843565b815161ffff16105b806146ea5750604081015161ffff16158015906146ea57506146df600187615843565b816040015161ffff16105b156147185761ffff861681526001600160681b03821660208201526000604082018190526060820152614786565b604081015161ffff161580614734575085816040015161ffff16145b156147575761ffff861660408201526001600160681b0382166060820152614786565b60408101805161ffff90811683526060830180516001600160681b039081166020860152918916909252831690525b6001600160a01b038716600090815260c960209081526040808320845181549386015192860151606087015161ffff9283166effffffffffffffffffffffffffffff1990961695909517620100006001600160681b0395861602176effffffffffffffffffffffffffffff60781b1916600160781b929091168202600160881b600160f01b03191617600160881b948416949094029390931781556080850151600190910180546001600160801b0319166001600160801b0390921691909117905560d154614858929004168a61374d565b905061486381614071565b60d180546001600160681b03909216600160781b02600160781b600160e01b03199092169190911790555050505050505050565b6137a06001600160a01b0384168383614c2c565b6000806000876000015161ffff161180156148d457506148cc600187615843565b875161ffff16105b156148f4576148f187602001516001600160681b031686856136ea565b90505b6000876040015161ffff1611801561491d5750614912600187615843565b876040015161ffff16105b156149475761493a87606001516001600160681b031685856136ea565b61494490826156c8565b90505b608087015161495f906001600160801b03168261374d565b979650505050505050565b600061118782846157df565b600061118782846156e0565b600054610100900460ff166149a95760405162461bcd60e51b8152600401610b26906155dc565b6123c1614f9a565b600054610100900460ff166149d85760405162461bcd60e51b8152600401610b26906155dc565b613be78282614fc1565b600054610100900460ff16614a095760405162461bcd60e51b8152600401610b26906155dc565b6123c161500f565b600060018311614a5b5760405162461bcd60e51b8152602060048201526015602482015274496e76616c6964206173736574506572536861726560581b6044820152606401610b26565b612a9a614a6983600a615737565b613029868661496a565b80516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b6001600160801b03811115612e775760405162461bcd60e51b815260206004820152601060248201526f09eeccae4ccd8deee40ead2dce86264760831b6044820152606401610b26565b6001600160a01b038216614b3e5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610b26565b6001600160a01b03821660009081526097602052604090205481811015614bb25760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610b26565b6001600160a01b0383166000908152609760205260408120838303905560998054849290614be1908490615843565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6040516001600160a01b0383166024820152604481018290526137a090849063a9059cbb60e01b906064016143ce565b6000808080614c7f614c72620f424060646157df565b60d954613029908961496a565b90506000614ca8614c94620f424060646157df565b61302988614ca28c8761338c565b9061496a565b90506000614cb6838361374d565b9050614cde604051806060016040528060288152602001615c596028913960d9548b8a613ef1565b614d02604051806080016040528060458152602001615be260459139848484613ef1565b91989097509095509350505050565b60d35460cd54600091614d3a91600160801b9091046001600160801b031690849060ff16614a11565b60d4549091506001600160801b03168111614d56576000614d6d565b60d454614d6d9082906001600160801b031661338c565b60da5560408051608081019091526043808252614da49190615b9f602083013960d45460da5484916001600160801b031690613ef1565b60da5415613be75760df5460da54613be7917f0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc916001600160a01b0390911690614897565b6001600160a01b038216614e3f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610b26565b8060996000828254614e5191906156c8565b90915550506001600160a01b03821660009081526097602052604081208054839290614e7e9084906156c8565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6000614f1d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661503f9092919063ffffffff16565b8051909150156137a05780806020019051810190614f3b9190615426565b6137a05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610b26565b600054610100900460ff166123045760405162461bcd60e51b8152600401610b26906155dc565b600054610100900460ff16614fe85760405162461bcd60e51b8152600401610b26906155dc565b8151614ffb90609a906020850190615143565b5080516137a090609b906020840190615143565b600054610100900460ff166150365760405162461bcd60e51b8152600401610b26906155dc565b6123c133614308565b6060612a9a8484600085856001600160a01b0385163b6150a15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b26565b600080866001600160a01b031685876040516150bd91906154a2565b60006040518083038185875af1925050503d80600081146150fa576040519150601f19603f3d011682016040523d82523d6000602084013e6150ff565b606091505b509150915061495f82828660608315615119575081611187565b8251156151295782518084602001fd5b8160405162461bcd60e51b8152600401610b2691906154be565b82805461514f90615886565b90600052602060002090601f01602090048101928261517157600085556151b7565b82601f1061518a57805160ff19168380011785556151b7565b828001600101855582156151b7579182015b828111156151b757825182559160200191906001019061519c565b506151c39291506151c7565b5090565b5b808211156151c357600081556001016151c8565b80356151e781615a4a565b919050565b600082601f8301126151fc578081fd5b813567ffffffffffffffff8082111561521757615217615901565b604051601f8301601f19908116603f0116810190828211818310171561523f5761523f615901565b81604052838152866020858801011115615257578485fd5b8360208701602083013792830160200193909352509392505050565b600060208284031215615284578081fd5b813561118781615a4a565b6000602082840312156152a0578081fd5b815161118781615a4a565b600080604083850312156152bd578081fd5b82356152c881615a4a565b915060208301356152d881615a4a565b809150509250929050565b600080600080600080600080888a036101a0811215615300578485fd5b893561530b81615a4a565b985060208a013561531b81615a4a565b975060408a013561532b81615a4a565b965060608a013567ffffffffffffffff80821115615347578687fd5b6153538d838e016151ec565b975060808c0135915080821115615368578687fd5b506153758c828d016151ec565b95505060c0609f1982011215615389578384fd5b5060a08901925061539d6101608a016151dc565b91506153ac6101808a016151dc565b90509295985092959890939650565b6000806000606084860312156153cf578283fd5b83356153da81615a4a565b925060208401356153ea81615a4a565b929592945050506040919091013590565b6000806040838503121561540d578182fd5b823561541881615a4a565b946020939093013593505050565b600060208284031215615437578081fd5b81518015158114611187578182fd5b600060208284031215615457578081fd5b5035919050565b60006020828403121561546f578081fd5b5051919050565b6000815180845261548e81602086016020860161585a565b601f01601f19169290920160200192915050565b600082516154b481846020870161585a565b9190910192915050565b6020815260006111876020830184615476565b6040815260006154e46040830185615476565b90508260208301529392505050565b6060815260006155066060830186615476565b60208301949094525060400152919050565b60808152600061552b6080830187615476565b6020830195909552506040810192909252606090910152919050565b6020808252600c908201526b1d5b985d5d1a1bdc9a5cd95960a21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526007908201526608585b5bdd5b9d60ca1b604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60006001600160681b03808316818516808303821115615680576156806158d5565b01949350505050565b60006001600160801b03808316818516808303821115615680576156806158d5565b600061ffff808316818516808303821115615680576156806158d5565b600082198211156156db576156db6158d5565b500190565b6000826156ef576156ef6158eb565b500490565b600181815b8085111561572f578160001904821115615715576157156158d5565b8085161561572257918102915b93841c93908002906156f9565b509250929050565b6000611187838360008261574d57506001610d17565b8161575a57506000610d17565b8160018114615770576002811461577a57615796565b6001915050610d17565b60ff84111561578b5761578b6158d5565b50506001821b610d17565b5060208310610133831016604e8410600b84101617156157b9575081810a610d17565b6157c383836156f4565b80600019048211156157d7576157d76158d5565b029392505050565b60008160001904831182151516156157f9576157f96158d5565b500290565b60008160010b8360010b82811281617fff1901831281151615615823576158236158d5565b81617fff018313811615615839576158396158d5565b5090039392505050565b600082821015615855576158556158d5565b500390565b60005b8381101561587557818101518382015260200161585d565b8381111561340c5750506000910152565b600181811c9082168061589a57607f821691505b602082108114156158bb57634e487b7160e01b600052602260045260246000fd5b50919050565b6000826158d0576158d06158eb565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60008135610d1781615a4a565b600081356001600160681b0381168114610d17578182fd5b6000813566ffffffffffffff81168114610d17578182fd5b813560ff811680821461596657600080fd5b825460ff198116821784559150602084013561598181615a4a565b6001600160a81b0319929092161760089190911b610100600160a81b0316178155600181016159d26159b560408501615917565b82546001600160a01b0319166001600160a01b0391909116178255565b615a0b6159e16060850161593c565b82805466ffffffffffffff60a01b191660a09290921b66ffffffffffffff60a01b16919091179055565b50615a3c615a1b60808401615924565b600283016001600160681b0382166001600160681b03198254161781555050565b60a082013560038201555050565b6001600160a01b0381168114612e7757600080fdfe425053202573206c617374526f756e64627073202573206d6f6f5969656c645368617265732025734375727262616c616e636520257320756e6c6f636b6564416d6f756e7420257320736574746c6564416d6f756e742025734465706c6f79656462616c616e6365202573206c6f636b6564416d6f756e7420257320736574746c6564416d6f756e742025734d6f6f5969656c6453686172657320257320476c705969656c64536861726573202573206375727262616c616e636520257357574954484452415757575720646564756374416d6f756e74202573207368617265735769746864726177434c4f5345454545206d696e74536861726573202573206e657750726963655065725368617265202573204445504f534954545420425053202573206e6577546f6b656e73526563656976656420257320626c6f636b434c4f534545207769746864726177416d6f756e7441744e6577505053202573207769746864726177416d6f756e7420257320756e4163636f756e7465647969656c6446454545205f706572666f726d616e6365466565496e4173736574202573205f6d616e6167656d656e74466565496e4173736574202573205f7661756c744665652025732057495448445241575757207769746864726177416d6f756e74202573207472616e73666572416d6f756e74202573204250534645454520736574746c6564416d6f756e74202573206465706c6f796564416d6f756e7420257320a264697066735822122029afbe04a9c21cd25fbe507a0bde8c872615aaf3460776cfc5f33b5b927e869c64736f6c63430008040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc
-----Decoded View---------------
Arg [0] : _vault (address): 0x9dbbBaecACEDf53d5Caa295b8293c1def2055Adc
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000009dbbbaecacedf53d5caa295b8293c1def2055adc
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.