Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 1 from a total of 1 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Initialize | 14073463 | 1489 days ago | IN | 0 ETH | 0.04346869 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ConvertibleVoucher
Compiler Version
v0.7.6+commit.7338295f
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
pragma abicoder v2;
import "@solv/v2-solidity-utils/contracts/openzeppelin/utils/ReentrancyGuardUpgradeable.sol";
import "@solv/v2-solidity-utils/contracts/openzeppelin/token/ERC20/IERC20.sol";
import "@solv/v2-solidity-utils/contracts/helpers/ERC20TransferHelper.sol";
import "@solv/v2-solidity-utils/contracts/helpers/VNFTTransferHelper.sol";
import "@solv/v2-voucher-core/contracts/VoucherCore.sol";
import "@solv/v2-solver/contracts/interface/ISolver.sol";
import "./ConvertiblePool.sol";
import "./interface/IVNFTDescriptor.sol";
import "./interface/IConvertibleVoucher.sol";
import "./interface/external/IICToken.sol";
contract ConvertibleVoucher is IConvertibleVoucher, VoucherCore, ReentrancyGuardUpgradeable {
using SafeMathUpgradeable for uint256;
ConvertiblePool public convertiblePool;
IVNFTDescriptor public voucherDescriptor;
ISolver public solver;
function initialize(
address convertiblePool_,
address voucherDescriptor_,
address solver_,
uint8 unitDecimals_,
string calldata name_,
string calldata symbol_
)
external
initializer
{
ReentrancyGuardUpgradeable.__ReentrancyGuard_init();
VoucherCore._initialize(name_, symbol_, unitDecimals_);
convertiblePool = ConvertiblePool(convertiblePool_);
voucherDescriptor = IVNFTDescriptor(voucherDescriptor_);
solver = ISolver(solver_);
ERC165Upgradeable._registerInterface(type(IConvertibleVoucher).interfaceId);
}
function mint(
address issuer_,
address fundCurrency_,
uint128 lowestPrice_,
uint128 highestPrice_,
uint64 effectiveTime_,
uint64 maturity_,
uint256 tokenInAmount_ // 最大偿付token数量 (at lowestPrice)
)
external
override
nonReentrant
returns (uint256 slot, uint256 tokenId)
{
uint256 err = solver.operationAllowed(
"mint",
abi.encode(
_msgSender(),
issuer_,
fundCurrency_,
lowestPrice_,
highestPrice_,
effectiveTime_,
maturity_,
tokenInAmount_
)
);
require(err == 0, "Solver: not allowed");
slot = getSlot(
issuer_, fundCurrency_, lowestPrice_, highestPrice_,
effectiveTime_, maturity_, 0
);
if (!getSlotDetail(slot).isValid) {
convertiblePool.createSlot(
issuer_, fundCurrency_, lowestPrice_, highestPrice_,
effectiveTime_, maturity_, 0
);
}
uint256 units = convertiblePool.mintWithUnderlyingToken(_msgSender(), slot, tokenInAmount_);
tokenId = VoucherCore._mint(_msgSender(), slot, units);
solver.operationVerify(
"mint",
abi.encode(_msgSender(), issuer_, slot, tokenId, units)
);
}
function claimAll(uint256 tokenId_) external override {
claim(tokenId_, unitsInToken(tokenId_));
}
function claim(uint256 tokenId_, uint256 claimUnits_) public override {
claimTo(tokenId_, _msgSender(), claimUnits_);
}
function claimTo(uint256 tokenId_, address to_, uint256 claimUnits_) public override nonReentrant {
require(_msgSender() == ownerOf(tokenId_), "only owner");
require(claimUnits_ <= unitsInToken(tokenId_), "over claim");
uint256 err = solver.operationAllowed(
"claim",
abi.encode(_msgSender(), tokenId_, to_, claimUnits_)
);
require(err == 0, "Solver: not allowed");
(uint256 claimCurrencyAmount, uint256 claimTokenAmount)
= convertiblePool.claim(voucherSlotMapping[tokenId_], to_, claimUnits_);
if (claimUnits_ == unitsInToken(tokenId_)) {
_burnVoucher(tokenId_);
} else {
_burnUnits(tokenId_, claimUnits_);
}
solver.operationVerify(
"claim",
abi.encode(_msgSender(), tokenId_, to_, claimUnits_)
);
emit Claim(tokenId_, to_, claimUnits_, claimCurrencyAmount, claimTokenAmount);
}
function getSlot(
address issuer_,
address fundCurrency_,
uint128 lowestPrice_,
uint128 highestPrice_,
uint64 effectiveTime_,
uint64 maturity_,
uint8 collateralType_
)
public
view
override
returns (uint256)
{
return convertiblePool.getSlot(
issuer_, fundCurrency_, lowestPrice_, highestPrice_,
effectiveTime_, maturity_, collateralType_
);
}
function getSlotDetail(uint256 slot_) public view override returns (IConvertiblePool.SlotDetail memory) {
return convertiblePool.getSlotDetail(slot_);
}
function getIssuerSlots(address issuer_) external view override returns (uint256[] memory slots) {
return convertiblePool.getIssuerSlots(issuer_);
}
function contractURI() external view override returns (string memory) {
return voucherDescriptor.contractURI();
}
function slotURI(uint256 slot_) external view override returns (string memory) {
return voucherDescriptor.slotURI(slot_);
}
function tokenURI(uint256 tokenId_) public view virtual override returns (string memory) {
require(_exists(tokenId_), "token not exists");
return voucherDescriptor.tokenURI(tokenId_);
}
function getSnapshot(uint256 tokenId_)
public
override
view
returns (ConvertibleVoucherSnapshot memory snapshot)
{
snapshot.tokenId = tokenId_;
snapshot.parValue = unitsInToken(tokenId_);
snapshot.slotDetail = convertiblePool.getSlotDetail(voucherSlotMapping[tokenId_]);
}
function underlying() external view override returns (address) {
return convertiblePool.underlyingToken();
}
function underlyingVestingVoucher() external view override returns (address) {
return convertiblePool.underlyingVestingVoucher();
}
function setVoucherDescriptor(address newDescriptor_) external onlyAdmin {
require(newDescriptor_ != address(0), "newDescriptor can not be 0 address");
emit SetDescriptor(address(voucherDescriptor), newDescriptor_);
voucherDescriptor = IVNFTDescriptor(newDescriptor_);
}
function setSolver(ISolver newSolver_) external onlyAdmin {
require(newSolver_.isSolver(), "invalid solver");
emit SetSolver(address(solver), address(newSolver_));
solver = newSolver_;
}
function voucherType() external pure override returns (Constants.VoucherType) {
return Constants.VoucherType.BOUNDING;
}
function version() external pure returns (string memory) {
return "1.0.1";
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
import "../openzeppelin/utils/ContextUpgradeable.sol";
import "../openzeppelin/proxy/Initializable.sol";
abstract contract AdminControl is Initializable, ContextUpgradeable {
event NewAdmin(address oldAdmin, address newAdmin);
event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
address public admin;
address public pendingAdmin;
modifier onlyAdmin() {
require(_msgSender() == admin, "only admin");
_;
}
function __AdminControl_init(address admin_) internal initializer {
admin = admin_;
}
function setPendingAdmin(address newPendingAdmin_) external virtual onlyAdmin {
emit NewPendingAdmin(pendingAdmin, newPendingAdmin_);
pendingAdmin = newPendingAdmin_;
}
function acceptAdmin() external virtual {
require(_msgSender() == pendingAdmin, "only pending admin");
emit NewAdmin(admin, pendingAdmin);
admin = pendingAdmin;
pendingAdmin = address(0);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
import "../misc/Constants.sol";
interface ERC20Interface {
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount)
external
returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
}
// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library ERC20TransferHelper {
function doTransferIn(
address underlying,
address from,
uint256 amount
) internal returns (uint256) {
if (underlying == Constants.ETH_ADDRESS) {
// Sanity checks
require(tx.origin == from || msg.sender == from, "sender mismatch");
require(msg.value == amount, "value mismatch");
return amount;
} else {
require(msg.value == 0, "don't support msg.value");
uint256 balanceBefore = ERC20Interface(underlying).balanceOf(
address(this)
);
(bool success, bytes memory data) = underlying.call(
abi.encodeWithSelector(
ERC20Interface.transferFrom.selector,
from,
address(this),
amount
)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"STF"
);
// Calculate the amount that was *actually* transferred
uint256 balanceAfter = ERC20Interface(underlying).balanceOf(
address(this)
);
require(
balanceAfter >= balanceBefore,
"TOKEN_TRANSFER_IN_OVERFLOW"
);
return balanceAfter - balanceBefore; // underflow already checked above, just subtract
}
}
function doTransferOut(
address underlying,
address payable to,
uint256 amount
) internal {
if (underlying == Constants.ETH_ADDRESS) {
(bool success, ) = to.call{value: amount}(new bytes(0));
require(success, "STE");
} else {
(bool success, bytes memory data) = underlying.call(
abi.encodeWithSelector(
ERC20Interface.transfer.selector,
to,
amount
)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"ST"
);
}
}
function getCashPrior(address underlying_) internal view returns (uint256) {
if (underlying_ == Constants.ETH_ADDRESS) {
uint256 startingBalance = sub(address(this).balance, msg.value);
return startingBalance;
} else {
ERC20Interface token = ERC20Interface(underlying_);
return token.balanceOf(address(this));
}
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
interface ERC721Interface {
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
}
interface VNFTInterface {
function transferFrom(
address from,
address to,
uint256 tokenId,
uint256 units
) external returns (uint256 newTokenId);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
uint256 units,
bytes calldata data
) external returns (uint256 newTokenId);
function transferFrom(
address from,
address to,
uint256 tokenId,
uint256 targetTokenId,
uint256 units
) external;
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
uint256 targetTokenId,
uint256 units,
bytes calldata data
) external;
}
library VNFTTransferHelper {
function doTransferIn(
address underlying,
address from,
uint256 tokenId
) internal {
ERC721Interface token = ERC721Interface(underlying);
token.transferFrom(from, address(this), tokenId);
}
function doTransferOut(
address underlying,
address to,
uint256 tokenId
) internal {
ERC721Interface token = ERC721Interface(underlying);
token.transferFrom(address(this), to, tokenId);
}
function doTransferIn(
address underlying,
address from,
uint256 tokenId,
uint256 units
) internal {
VNFTInterface token = VNFTInterface(underlying);
token.safeTransferFrom(from, address(this), tokenId, units, "");
}
function doTransferOut(
address underlying,
address to,
uint256 tokenId,
uint256 units
) internal returns (uint256 newTokenId) {
VNFTInterface token = VNFTInterface(underlying);
newTokenId = token.safeTransferFrom(
address(this),
to,
tokenId,
units,
""
);
}
function doTransferOut(
address underlying,
address to,
uint256 tokenId,
uint256 targetTokenId,
uint256 units
) internal {
VNFTInterface token = VNFTInterface(underlying);
token.safeTransferFrom(
address(this),
to,
tokenId,
targetTokenId,
units,
""
);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
library Constants {
enum ClaimType {
LINEAR,
ONE_TIME,
STAGED
}
enum VoucherType {
STANDARD_VESTING,
FLEXIBLE_DATE_VESTING,
BOUNDING
}
uint32 internal constant FULL_PERCENTAGE = 10000;
address internal constant ETH_ADDRESS =
0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "./IERC165Upgradeable.sol";
import "../proxy/Initializable.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts may inherit from this and call {_registerInterface} to declare
* their support of an interface.
*/
abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
/*
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
*/
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
/**
* @dev Mapping of interface ids to whether or not it's supported.
*/
mapping(bytes4 => bool) private _supportedInterfaces;
function __ERC165_init() internal initializer {
__ERC165_init_unchained();
}
function __ERC165_init_unchained() internal initializer {
// Derived contracts need only register support for their own interfaces,
// we register support for ERC165 itself here
_registerInterface(_INTERFACE_ID_ERC165);
}
/**
* @dev See {IERC165-supportsInterface}.
*
* Time complexity O(1), guaranteed to always use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return _supportedInterfaces[interfaceId];
}
/**
* @dev Registers the contract as an implementer of the interface defined by
* `interfaceId`. Support of the actual ERC165 interface is automatic and
* registering its interface id is not required.
*
* See {IERC165-supportsInterface}.
*
* Requirements:
*
* - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
*/
function _registerInterface(bytes4 interfaceId) internal virtual {
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true;
}
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165Upgradeable {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMathUpgradeable {
/**
* @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) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
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) {
// 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) {
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) {
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) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @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) {
require(b <= a, "SafeMath: subtraction overflow");
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) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @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. 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) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
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) {
require(b > 0, "SafeMath: modulo by zero");
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) {
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.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryDiv}.
*
* 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) {
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) {
require(b > 0, errorMessage);
return a % b;
}
}// SPDX-License-Identifier: MIT
// solhint-disable-next-line compiler-version
pragma solidity >=0.4.24 <0.8.0;
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 a proxied contract can't have 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.
*
* 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 {UpgradeableProxy-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.
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
/// @dev Returns true if and only if the function is running in the constructor
function _isConstructor() private view returns (bool) {
return !AddressUpgradeable.isContract(address(this));
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "../../utils/ContextUpgradeable.sol";
import "./IERC20Upgradeable.sol";
import "../../math/SafeMathUpgradeable.sol";
import "../../proxy/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 guidelines: functions revert instead
* of 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 {
using SafeMathUpgradeable for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
/**
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with
* a default value of 18.
*
* To select a different value for {decimals}, use {_setupDecimals}.
*
* All three of these values are immutable: they can only be set once during
* construction.
*/
function __ERC20_init(string memory name_, string memory symbol_) internal initializer {
__Context_init_unchained();
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {
_name = name_;
_symbol = symbol_;
_decimals = 18;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual 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 {_setupDecimals} is
* called.
*
* 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 returns (uint8) {
return _decimals;
}
/**
* @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:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, 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}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), 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}.
*
* Requirements:
*
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
* - the caller must have allowance for ``sender``'s tokens of at least
* `amount`.
*/
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
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) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
/**
* @dev Moves tokens `amount` from `sender` to `recipient`.
*
* This is 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:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, 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:
*
* - `to` 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 = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(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);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(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 Sets {decimals} to a value other than the default one of 18.
*
* WARNING: This function should only be called from the constructor. Most
* applications that interact with token contracts will not expect
* {decimals} to ever change, and may work incorrectly if it does.
*/
function _setupDecimals(uint8 decimals_) internal virtual {
_decimals = decimals_;
}
/**
* @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 to 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 { }
uint256[44] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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 `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount) external returns (bool);
/**
* @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);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @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 `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount) external returns (bool);
/**
* @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);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "../../utils/ContextUpgradeable.sol";
import "./IERC721Upgradeable.sol";
import "./IERC721MetadataUpgradeable.sol";
import "./IERC721EnumerableUpgradeable.sol";
import "./IERC721ReceiverUpgradeable.sol";
import "../../introspection/ERC165Upgradeable.sol";
import "../../math/SafeMathUpgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/EnumerableSetUpgradeable.sol";
import "../../utils/EnumerableMapUpgradeable.sol";
import "../../utils/StringsUpgradeable.sol";
import "../../proxy/Initializable.sol";
/**
* @title ERC721 Non-Fungible Token Standard basic implementation
* @dev see https://eips.ethereum.org/EIPS/eip-721
*/
contract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable, IERC721EnumerableUpgradeable {
using SafeMathUpgradeable for uint256;
using AddressUpgradeable for address;
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;
using EnumerableMapUpgradeable for EnumerableMapUpgradeable.UintToAddressMap;
using StringsUpgradeable for uint256;
// Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
// which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
// Mapping from holder address to their (enumerable) set of owned tokens
mapping (address => EnumerableSetUpgradeable.UintSet) private _holderTokens;
// Enumerable mapping from token ids to their owners
EnumerableMapUpgradeable.UintToAddressMap private _tokenOwners;
// Mapping from token ID to approved address
mapping (uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping (address => mapping (address => bool)) private _operatorApprovals;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Optional mapping for token URIs
mapping (uint256 => string) private _tokenURIs;
// Base URI
string private _baseURI;
/*
* bytes4(keccak256('balanceOf(address)')) == 0x70a08231
* bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
* bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
* bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
* bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
* bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
* bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
* bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
* bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
*
* => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
* 0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
*/
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
/*
* bytes4(keccak256('name()')) == 0x06fdde03
* bytes4(keccak256('symbol()')) == 0x95d89b41
* bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
*
* => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
*/
bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
/*
* bytes4(keccak256('totalSupply()')) == 0x18160ddd
* bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
* bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
*
* => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
*/
bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
function __ERC721_init(string memory name_, string memory symbol_) internal initializer {
__Context_init_unchained();
__ERC165_init_unchained();
__ERC721_init_unchained(name_, symbol_);
}
function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {
_name = name_;
_symbol = symbol_;
// register the supported interfaces to conform to ERC721 via ERC165
_registerInterface(_INTERFACE_ID_ERC721);
_registerInterface(_INTERFACE_ID_ERC721_METADATA);
_registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _holderTokens[owner].length();
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = baseURI();
// If there is no base URI, return the token URI.
if (bytes(base).length == 0) {
return _tokenURI;
}
// If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
if (bytes(_tokenURI).length > 0) {
return string(abi.encodePacked(base, _tokenURI));
}
// If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
return string(abi.encodePacked(base, tokenId.toString()));
}
/**
* @dev Returns the base URI set via {_setBaseURI}. This will be
* automatically added as a prefix in {tokenURI} to each token's URI, or
* to the token ID if no specific URI is set for that token ID.
*/
function baseURI() public view virtual returns (string memory) {
return _baseURI;
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
return _holderTokens[owner].at(index);
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
// _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds
return _tokenOwners.length();
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
(uint256 tokenId, ) = _tokenOwners.at(index);
return tokenId;
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721Upgradeable.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(_msgSender() == owner || ERC721Upgradeable.isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
require(operator != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _tokenOwners.contains(tokenId);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721Upgradeable.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || ERC721Upgradeable.isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
d*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {
_mint(to, tokenId);
require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_holderTokens[to].add(tokenId);
_tokenOwners.set(tokenId, to);
emit Transfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721Upgradeable.ownerOf(tokenId); // internal owner
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
// Clear metadata (if any)
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
_holderTokens[owner].remove(tokenId);
_tokenOwners.remove(tokenId);
emit Transfer(owner, address(0), tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal virtual {
require(ERC721Upgradeable.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); // internal owner
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_holderTokens[from].remove(tokenId);
_holderTokens[to].add(tokenId);
_tokenOwners.set(tokenId, to);
emit Transfer(from, to, tokenId);
}
/**
* @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
/**
* @dev Internal function to set the base URI for all token IDs. It is
* automatically added as a prefix to the value returned in {tokenURI},
* or to the token ID if {tokenURI} is empty.
*/
function _setBaseURI(string memory baseURI_) internal virtual {
_baseURI = baseURI_;
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
private returns (bool)
{
if (!to.isContract()) {
return true;
}
bytes memory returndata = to.functionCall(abi.encodeWithSelector(
IERC721ReceiverUpgradeable(to).onERC721Received.selector,
_msgSender(),
from,
tokenId,
_data
), "ERC721: transfer to non ERC721Receiver implementer");
bytes4 retval = abi.decode(returndata, (bytes4));
return (retval == _ERC721_RECEIVED);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits an {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId); // internal owner
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }
uint256[41] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
import "./IERC721Upgradeable.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721EnumerableUpgradeable is IERC721Upgradeable {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
import "./IERC721Upgradeable.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721MetadataUpgradeable is IERC721Upgradeable {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721ReceiverUpgradeable {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
*/
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
import "../../introspection/IERC165Upgradeable.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721Upgradeable is IERC165Upgradeable {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
/**
* @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
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 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");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(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");
// solhint-disable-next-line avoid-low-level-calls
(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");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "../proxy/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 GSN 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 initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {
}
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Library for managing an enumerable variant of Solidity's
* https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
* type.
*
* Maps have the following properties:
*
* - Entries are added, removed, and checked for existence in constant time
* (O(1)).
* - Entries are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableMap for EnumerableMap.UintToAddressMap;
*
* // Declare a set state variable
* EnumerableMap.UintToAddressMap private myMap;
* }
* ```
*
* As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are
* supported.
*/
library EnumerableMapUpgradeable {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Map type with
// bytes32 keys and values.
// The Map implementation uses private functions, and user-facing
// implementations (such as Uint256ToAddressMap) are just wrappers around
// the underlying Map.
// This means that we can only create new EnumerableMaps for types that fit
// in bytes32.
struct MapEntry {
bytes32 _key;
bytes32 _value;
}
struct Map {
// Storage of map keys and values
MapEntry[] _entries;
// Position of the entry defined by a key in the `entries` array, plus 1
// because index 0 means a key is not in the map.
mapping (bytes32 => uint256) _indexes;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {
// We read and store the key's index to prevent multiple reads from the same storage slot
uint256 keyIndex = map._indexes[key];
if (keyIndex == 0) { // Equivalent to !contains(map, key)
map._entries.push(MapEntry({ _key: key, _value: value }));
// The entry is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
map._indexes[key] = map._entries.length;
return true;
} else {
map._entries[keyIndex - 1]._value = value;
return false;
}
}
/**
* @dev Removes a key-value pair from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function _remove(Map storage map, bytes32 key) private returns (bool) {
// We read and store the key's index to prevent multiple reads from the same storage slot
uint256 keyIndex = map._indexes[key];
if (keyIndex != 0) { // Equivalent to contains(map, key)
// To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one
// in the array, and then remove the last entry (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = keyIndex - 1;
uint256 lastIndex = map._entries.length - 1;
// When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
MapEntry storage lastEntry = map._entries[lastIndex];
// Move the last entry to the index where the entry to delete is
map._entries[toDeleteIndex] = lastEntry;
// Update the index for the moved entry
map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based
// Delete the slot where the moved entry was stored
map._entries.pop();
// Delete the index for the deleted slot
delete map._indexes[key];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function _contains(Map storage map, bytes32 key) private view returns (bool) {
return map._indexes[key] != 0;
}
/**
* @dev Returns the number of key-value pairs in the map. O(1).
*/
function _length(Map storage map) private view returns (uint256) {
return map._entries.length;
}
/**
* @dev Returns the key-value pair stored at position `index` in the map. O(1).
*
* Note that there are no guarantees on the ordering of entries inside the
* array, and it may change when more entries are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
require(map._entries.length > index, "EnumerableMap: index out of bounds");
MapEntry storage entry = map._entries[index];
return (entry._key, entry._value);
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {
uint256 keyIndex = map._indexes[key];
if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)
return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function _get(Map storage map, bytes32 key) private view returns (bytes32) {
uint256 keyIndex = map._indexes[key];
require(keyIndex != 0, "EnumerableMap: nonexistent key"); // Equivalent to contains(map, key)
return map._entries[keyIndex - 1]._value; // All indexes are 1-based
}
/**
* @dev Same as {_get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {_tryGet}.
*/
function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {
uint256 keyIndex = map._indexes[key];
require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)
return map._entries[keyIndex - 1]._value; // All indexes are 1-based
}
// UintToAddressMap
struct UintToAddressMap {
Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
return _remove(map._inner, bytes32(key));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
return _contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToAddressMap storage map) internal view returns (uint256) {
return _length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
(bytes32 key, bytes32 value) = _at(map._inner, index);
return (uint256(key), address(uint160(uint256(value))));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*
* _Available since v3.4._
*/
function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
(bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));
return (success, address(uint160(uint256(value))));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
return address(uint160(uint256(_get(map._inner, bytes32(key)))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {
return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/
library EnumerableSetUpgradeable {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping (bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) { // Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
require(set._values.length > index, "EnumerableSet: index out of bounds");
return set._values[index];
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "../proxy/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 initializer {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal initializer {
_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 make 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;
}
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev String operations.
*/
library StringsUpgradeable {
/**
* @dev Converts a `uint256` to its ASCII `string` representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
uint256 index = digits - 1;
temp = value;
while (temp != 0) {
buffer[index--] = bytes1(uint8(48 + temp % 10));
temp /= 10;
}
return string(buffer);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
interface ISolver {
event SetOperationPaused (
address product,
string operation,
bool setPaused
);
function isSolver() external pure returns (bool);
function setOperationPaused(address product_, string calldata operation_, bool setPaused_) external;
function operationAllowed(string calldata operation_, bytes calldata data_) external returns (uint256);
function operationVerify(string calldata operation_, bytes calldata data_) external returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
import "@solv/v2-solidity-utils/contracts/openzeppelin/token/ERC721/ERC721Upgradeable.sol";
import "@solv/v2-solidity-utils/contracts/openzeppelin/utils/EnumerableSetUpgradeable.sol";
import "./interface/IVNFT.sol";
import "./interface/optional/IVNFTMetadata.sol";
abstract contract VNFTCoreV2 is IVNFT, IVNFTMetadata, ERC721Upgradeable {
using SafeMathUpgradeable for uint256;
using AddressUpgradeable for address;
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;
struct ApproveUnits {
address[] approvals;
mapping(address => uint256) allowances;
}
/// @dev tokenId => units
mapping(uint256 => uint256) internal _units;
/// @dev tokenId => operator => units
mapping(uint256 => ApproveUnits) private _tokenApprovalUnits;
/// @dev slot => tokenIds
mapping(uint256 => EnumerableSetUpgradeable.UintSet) private _slotTokens;
uint8 internal _unitDecimals;
function _initialize(
string memory name_,
string memory symbol_,
uint8 unitDecimals_
) internal virtual {
ERC721Upgradeable.__ERC721_init(name_, symbol_);
ERC165Upgradeable._registerInterface(type(IVNFT).interfaceId);
_unitDecimals = unitDecimals_;
}
function _safeTransferUnitsFrom(
address from_,
address to_,
uint256 tokenId_,
uint256 targetTokenId_,
uint256 transferUnits_,
bytes memory data_
) internal virtual {
_transferUnitsFrom(
from_,
to_,
tokenId_,
targetTokenId_,
transferUnits_
);
require(
_checkOnVNFTReceived(
from_,
to_,
targetTokenId_,
transferUnits_,
data_
),
"to non VNFTReceiver implementer"
);
}
function _transferUnitsFrom(
address from_,
address to_,
uint256 tokenId_,
uint256 targetTokenId_,
uint256 transferUnits_
) internal virtual {
require(from_ == ownerOf(tokenId_), "source token owner mismatch");
require(to_ != address(0), "transfer to the zero address");
_beforeTransferUnits(
from_,
to_,
tokenId_,
targetTokenId_,
transferUnits_
);
// approve all后可不需要approve units
if (_msgSender() != from_ && !isApprovedForAll(from_, _msgSender())) {
_tokenApprovalUnits[tokenId_].allowances[
_msgSender()
] = _tokenApprovalUnits[tokenId_].allowances[_msgSender()].sub(
transferUnits_,
"transfer units exceeds allowance"
);
}
_units[tokenId_] = _units[tokenId_].sub(
transferUnits_,
"transfer excess units"
);
if (!_exists(targetTokenId_)) {
_mintUnits(to_, targetTokenId_, _slotOf(tokenId_), transferUnits_);
} else {
require(
ownerOf(targetTokenId_) == to_,
"target token owner mismatch"
);
require(
_slotOf(tokenId_) == _slotOf(targetTokenId_),
"slot mismatch"
);
_units[targetTokenId_] = _units[targetTokenId_].add(transferUnits_);
}
emit TransferUnits(
from_,
to_,
tokenId_,
targetTokenId_,
transferUnits_
);
}
function _merge(uint256 tokenId_, uint256 targetTokenId_) internal virtual {
require(
_isApprovedOrOwner(_msgSender(), tokenId_),
"VNFT: not owner nor approved"
);
require(tokenId_ != targetTokenId_, "self merge not allowed");
require(_slotOf(tokenId_) == _slotOf(targetTokenId_), "slot mismatch");
address owner = ownerOf(tokenId_);
require(owner == ownerOf(targetTokenId_), "not same owner");
uint256 mergeUnits = _units[tokenId_];
_units[targetTokenId_] = _units[tokenId_].add(_units[targetTokenId_]);
_burn(tokenId_);
emit Merge(owner, tokenId_, targetTokenId_, mergeUnits);
}
function _split(
uint256 tokenId_,
uint256 newTokenId_,
uint256 splitUnits_
) internal virtual {
require(
_isApprovedOrOwner(_msgSender(), tokenId_),
"VNFT: not owner nor approved"
);
require(!_exists(newTokenId_), "new token already exists");
_units[tokenId_] = _units[tokenId_].sub(splitUnits_);
address owner = ownerOf(tokenId_);
_mintUnits(owner, newTokenId_, _slotOf(tokenId_), splitUnits_);
emit Split(owner, tokenId_, newTokenId_, splitUnits_);
}
function _mintUnits(
address minter_,
uint256 tokenId_,
uint256 slot_,
uint256 units_
) internal virtual {
if (!_exists(tokenId_)) {
ERC721Upgradeable._mint(minter_, tokenId_);
_slotTokens[slot_].add(tokenId_);
}
_units[tokenId_] = _units[tokenId_].add(units_);
emit TransferUnits(address(0), minter_, 0, tokenId_, units_);
}
function _burn(uint256 tokenId_) internal virtual override {
address owner = ownerOf(tokenId_);
uint256 slot = _slotOf(tokenId_);
uint256 burnUnits = _units[tokenId_];
_slotTokens[slot].remove(tokenId_);
delete _units[tokenId_];
ERC721Upgradeable._burn(tokenId_);
emit TransferUnits(owner, address(0), tokenId_, 0, burnUnits);
}
function _burnUnits(uint256 tokenId_, uint256 burnUnits_)
internal
virtual
returns (uint256 balance)
{
address owner = ownerOf(tokenId_);
_units[tokenId_] = _units[tokenId_].sub(
burnUnits_,
"burn excess units"
);
emit TransferUnits(owner, address(0), tokenId_, 0, burnUnits_);
return _units[tokenId_];
}
function approve(
address to_,
uint256 tokenId_,
uint256 allowance_
) public virtual override {
require(_msgSender() == ownerOf(tokenId_), "VNFT: only owner");
_approveUnits(to_, tokenId_, allowance_);
}
function allowance(uint256 tokenId_, address spender_)
public
view
virtual
override
returns (uint256)
{
return _tokenApprovalUnits[tokenId_].allowances[spender_];
}
/**
* @dev Approve `to_` to operate on `tokenId_` within range of `allowance_`
*/
function _approveUnits(
address to_,
uint256 tokenId_,
uint256 allowance_
) internal virtual {
if (_tokenApprovalUnits[tokenId_].allowances[to_] == 0) {
_tokenApprovalUnits[tokenId_].approvals.push(to_);
}
_tokenApprovalUnits[tokenId_].allowances[to_] = allowance_;
emit ApprovalUnits(to_, tokenId_, allowance_);
}
/**
* @dev Clear existing approveUnits for `tokenId_`, including approved addresses and their approved units.
*/
function _clearApproveUnits(uint256 tokenId_) internal virtual {
ApproveUnits storage approveUnits = _tokenApprovalUnits[tokenId_];
for (uint256 i = 0; i < approveUnits.approvals.length; i++) {
delete approveUnits.allowances[approveUnits.approvals[i]];
delete approveUnits.approvals[i];
}
}
function unitDecimals() public view override returns (uint8) {
return _unitDecimals;
}
function unitsInSlot(uint256 slot_)
public
view
override
returns (uint256 units_)
{
for (uint256 i = 0; i < tokensInSlot(slot_); i++) {
units_ = units_.add(unitsInToken(tokenOfSlotByIndex(slot_, i)));
}
}
function unitsInToken(uint256 tokenId_)
public
view
virtual
override
returns (uint256)
{
return _units[tokenId_];
}
function tokensInSlot(uint256 slot_)
public
view
override
returns (uint256)
{
return _slotTokens[slot_].length();
}
function tokenOfSlotByIndex(uint256 slot_, uint256 index_)
public
view
override
returns (uint256)
{
return _slotTokens[slot_].at(index_);
}
function slotOf(uint256 tokenId_) public view override returns (uint256) {
return _slotOf(tokenId_);
}
function _slotOf(uint256 tokenId_) internal view virtual returns (uint256);
/**
* @dev Before transferring or burning a token, the existing approveUnits should be cleared.
*/
function _beforeTokenTransfer(
address from_,
address to_,
uint256 tokenId_
) internal virtual override {
if (from_ != address(0)) {
_clearApproveUnits(tokenId_);
}
}
function _beforeTransferUnits(
address from_,
address to_,
uint256 tokenId_,
uint256 targetTokenId_,
uint256 transferUnits_
) internal virtual {}
function _checkOnVNFTReceived(
address from_,
address to_,
uint256 tokenId_,
uint256 units_,
bytes memory _data
) internal returns (bool) {
if (!to_.isContract()) {
return true;
}
bytes memory returndata = to_.functionCall(
abi.encodeWithSelector(
IVNFTReceiver(to_).onVNFTReceived.selector,
_msgSender(),
from_,
tokenId_,
units_,
_data
),
"non VNFTReceiver implementer"
);
bytes4 retval = abi.decode(returndata, (bytes4));
/*b382cdcd => onVNFTReceived(address,address,uint256,uint256,bytes)*/
return (retval == type(IVNFTReceiver).interfaceId);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
/* is ERC721, ERC165 */
interface IVNFT {
event TransferUnits(
address indexed from,
address indexed to,
uint256 indexed tokenId,
uint256 targetTokenId,
uint256 transferUnits
);
event Split(
address indexed owner,
uint256 indexed tokenId,
uint256 newTokenId,
uint256 splitUnits
);
event Merge(
address indexed owner,
uint256 indexed tokenId,
uint256 indexed targetTokenId,
uint256 mergeUnits
);
event ApprovalUnits(
address indexed approval,
uint256 indexed tokenId,
uint256 allowance
);
function slotOf(uint256 tokenId) external view returns (uint256 slot);
function unitDecimals() external view returns (uint8);
function unitsInSlot(uint256 slot) external view returns (uint256);
function tokensInSlot(uint256 slot)
external
view
returns (uint256 tokenCount);
function tokenOfSlotByIndex(uint256 slot, uint256 index)
external
view
returns (uint256 tokenId);
function unitsInToken(uint256 tokenId)
external
view
returns (uint256 units);
function approve(
address to,
uint256 tokenId,
uint256 units
) external;
function allowance(uint256 tokenId, address spender)
external
view
returns (uint256 allowed);
function split(uint256 tokenId, uint256[] calldata units)
external
returns (uint256[] memory newTokenIds);
function merge(uint256[] calldata tokenIds, uint256 targetTokenId) external;
function transferFrom(
address from,
address to,
uint256 tokenId,
uint256 units
) external returns (uint256 newTokenId);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
uint256 units,
bytes calldata data
) external returns (uint256 newTokenId);
function transferFrom(
address from,
address to,
uint256 tokenId,
uint256 targetTokenId,
uint256 units
) external;
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
uint256 targetTokenId,
uint256 units,
bytes calldata data
) external;
}
interface IVNFTReceiver {
function onVNFTReceived(
address operator,
address from,
uint256 tokenId,
uint256 units,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
interface IUnderlyingContainer {
function totalUnderlyingAmount() external view returns (uint256);
function underlying() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
interface IVNFTMetadata /* is IERC721Metadata */ {
function contractURI() external view returns (string memory);
function slotURI(uint256 slot) external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
import "@solv/v2-solidity-utils/contracts/access/AdminControl.sol";
import "@solv/v2-solidity-utils/contracts/misc/Constants.sol";
import "@solv/v2-vnft-core/contracts/VNFTCoreV2.sol";
abstract contract VoucherCore is VNFTCoreV2, AdminControl {
/// @dev tokenId => slot
mapping(uint256 => uint256) public voucherSlotMapping;
uint32 public nextTokenId;
function _initialize(
string memory name_,
string memory symbol_,
uint8 unitDecimals_
) internal override {
AdminControl.__AdminControl_init(_msgSender());
VNFTCoreV2._initialize(name_, symbol_, unitDecimals_);
nextTokenId = 1;
}
function _generateTokenId() internal virtual returns (uint256) {
return nextTokenId++;
}
function split(uint256 tokenId_, uint256[] calldata splitUnits_)
public
virtual
override
returns (uint256[] memory newTokenIds)
{
require(splitUnits_.length > 0, "empty splitUnits");
newTokenIds = new uint256[](splitUnits_.length);
for (uint256 i = 0; i < splitUnits_.length; i++) {
uint256 newTokenId = _generateTokenId();
newTokenIds[i] = newTokenId;
VNFTCoreV2._split(tokenId_, newTokenId, splitUnits_[i]);
voucherSlotMapping[newTokenId] = voucherSlotMapping[tokenId_];
}
}
function merge(uint256[] calldata tokenIds_, uint256 targetTokenId_)
public
virtual
override
{
require(tokenIds_.length > 0, "empty tokenIds");
for (uint256 i = 0; i < tokenIds_.length; i++) {
VNFTCoreV2._merge(tokenIds_[i], targetTokenId_);
delete voucherSlotMapping[tokenIds_[i]];
}
}
/**
* @notice Transfer part of units of a Voucher to target address.
* @param from_ Address of the Voucher sender
* @param to_ Address of the Voucher recipient
* @param tokenId_ Id of the Voucher to transfer
* @param transferUnits_ Amount of units to transfer
*/
function transferFrom(
address from_,
address to_,
uint256 tokenId_,
uint256 transferUnits_
) public virtual override returns (uint256 newTokenId) {
newTokenId = _generateTokenId();
_transferUnitsFrom(from_, to_, tokenId_, newTokenId, transferUnits_);
}
/**
* @notice Transfer part of units of a Voucher to another Voucher.
* @param from_ Address of the Voucher sender
* @param to_ Address of the Voucher recipient
* @param tokenId_ Id of the Voucher to transfer
* @param targetTokenId_ Id of the Voucher to receive
* @param transferUnits_ Amount of units to transfer
*/
function transferFrom(
address from_,
address to_,
uint256 tokenId_,
uint256 targetTokenId_,
uint256 transferUnits_
) public virtual override {
require(_exists(targetTokenId_), "target token not exists");
_transferUnitsFrom(
from_,
to_,
tokenId_,
targetTokenId_,
transferUnits_
);
}
function safeTransferFrom(
address from_,
address to_,
uint256 tokenId_,
uint256 transferUnits_,
bytes memory data_
) public virtual override returns (uint256 newTokenId) {
newTokenId = transferFrom(from_, to_, tokenId_, transferUnits_);
require(
_checkOnVNFTReceived(from_, to_, newTokenId, transferUnits_, data_),
"to non VNFTReceiver"
);
return newTokenId;
}
function safeTransferFrom(
address from_,
address to_,
uint256 tokenId_,
uint256 targetTokenId_,
uint256 transferUnits_,
bytes memory data_
) public virtual override {
transferFrom(from_, to_, tokenId_, targetTokenId_, transferUnits_);
require(
_checkOnVNFTReceived(
from_,
to_,
targetTokenId_,
transferUnits_,
data_
),
"to non VNFTReceiver"
);
}
function _transferUnitsFrom(
address from_,
address to_,
uint256 tokenId_,
uint256 targetTokenId_,
uint256 transferUnits_
) internal virtual override {
VNFTCoreV2._transferUnitsFrom(
from_,
to_,
tokenId_,
targetTokenId_,
transferUnits_
);
voucherSlotMapping[targetTokenId_] = voucherSlotMapping[tokenId_];
}
function _mint(
address minter_,
uint256 slot_,
uint256 units_
) internal virtual returns (uint256 tokenId) {
tokenId = _generateTokenId();
voucherSlotMapping[tokenId] = slot_;
VNFTCoreV2._mintUnits(minter_, tokenId, slot_, units_);
}
function burn(uint256 tokenId_) external virtual {
require(_msgSender() == ownerOf(tokenId_), "only owner");
_burnVoucher(tokenId_);
}
function _burnVoucher(uint256 tokenId_) internal virtual {
delete voucherSlotMapping[tokenId_];
VNFTCoreV2._burn(tokenId_);
}
function _slotOf(uint256 tokenId_)
internal
view
virtual
override
returns (uint256)
{
return voucherSlotMapping[tokenId_];
}
function owner() external view virtual returns (address) {
return admin;
}
function voucherType() external view virtual returns (Constants.VoucherType) {}
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
pragma abicoder v2;
import "@solv/v2-solidity-utils/contracts/access/AdminControl.sol";
import "@solv/v2-solidity-utils/contracts/misc/Constants.sol";
import "@solv/v2-solidity-utils/contracts/openzeppelin/utils/ReentrancyGuardUpgradeable.sol";
import "@solv/v2-solidity-utils/contracts/openzeppelin/utils/EnumerableSetUpgradeable.sol";
import "@solv/v2-solidity-utils/contracts/openzeppelin/math/SafeMathUpgradeable.sol";
import "@solv/v2-solidity-utils/contracts/helpers/ERC20TransferHelper.sol";
import "@solv/v2-solidity-utils/contracts/helpers/VNFTTransferHelper.sol";
import "@solv/v2-vnft-core/contracts/interface/optional/IUnderlyingContainer.sol";
import "@solv/v2-solidity-utils/contracts/openzeppelin/token/ERC20/ERC20Upgradeable.sol";
import "./interface/IConvertiblePool.sol";
import "./interface/IPriceOracleManager.sol";
import "./interface/external/IICToken.sol";
import "hardhat/console.sol";
contract ConvertiblePool is
IConvertiblePool,
AdminControl,
ReentrancyGuardUpgradeable
{
using SafeMathUpgradeable for uint256;
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;
mapping(uint256 => SlotDetail) internal _slotDetails;
mapping(address => EnumerableSetUpgradeable.UintSet) internal _issuerSlots;
mapping(address => bool) public fundCurrencies;
/// @notice slot => currency => balance
mapping(uint256 => mapping(address => uint256)) public slotBalances;
IPriceOracleManager public oracle;
address public underlyingVestingVoucher;
address public underlyingToken;
uint8 public priceDecimals;
uint8 public valueDecimals;
address public voucher;
modifier onlyVoucher() {
require(_msgSender() == voucher, "only voucher");
_;
}
function initialize(
address underlyingToken_,
address oracle_,
uint8 priceDecimals_,
uint8 valueDecimals_
) external initializer {
AdminControl.__AdminControl_init(_msgSender());
oracle = IPriceOracleManager(oracle_);
underlyingToken = underlyingToken_;
priceDecimals = priceDecimals_;
valueDecimals = valueDecimals_;
}
function createSlot(
address issuer_,
address fundCurrency_,
uint128 lowestPrice_,
uint128 highestPrice_,
uint64 effectiveTime_,
uint64 maturity_,
uint8 collateralType_
) external onlyVoucher returns (uint256 slot) {
validateSlotParams(
issuer_,
fundCurrency_,
lowestPrice_,
highestPrice_,
effectiveTime_,
maturity_,
collateralType_
);
slot = getSlot(
issuer_,
fundCurrency_,
lowestPrice_,
highestPrice_,
effectiveTime_,
maturity_,
collateralType_
);
require(!_slotDetails[slot].isValid, "slot already existed");
SlotDetail storage slotDetail = _slotDetails[slot];
slotDetail.issuer = issuer_;
slotDetail.fundCurrency = fundCurrency_;
slotDetail.lowestPrice = lowestPrice_;
slotDetail.highestPrice = highestPrice_;
slotDetail.effectiveTime = effectiveTime_;
slotDetail.maturity = maturity_;
slotDetail.collateralType = CollateralType(collateralType_);
slotDetail.isValid = true;
_issuerSlots[issuer_].add(slot);
emit CreateSlot(
slot,
issuer_,
fundCurrency_,
lowestPrice_,
highestPrice_,
effectiveTime_,
maturity_,
CollateralType(collateralType_)
);
}
function validateSlotParams(
address issuer_,
address fundCurrency_,
uint128 lowestPrice_,
uint128 highestPrice_,
uint64 effectiveTime_,
uint64 maturity_,
uint8 collateralType_
) public view {
require(issuer_ != address(0), "issuer cannot be 0 address");
require(fundCurrencies[fundCurrency_], "unsupported fund currency");
require(collateralType_ < 2, "invalid collateral type");
require(
lowestPrice_ > 0 && lowestPrice_ < highestPrice_,
"invalid price bounds"
);
require(
effectiveTime_ > 0 && effectiveTime_ < maturity_,
"invalid time setting"
);
}
function mintWithUnderlyingToken(
address minter_,
uint256 slot_,
uint256 tokenInAmount_
) external override nonReentrant onlyVoucher returns (uint256 totalValue) {
require(minter_ != address(0), "minter cannot be 0 address");
require(tokenInAmount_ != 0, "tokenInAmount cannot be 0");
SlotDetail storage slotDetail = _slotDetails[slot_];
require(slotDetail.isValid, "invalid slot");
require(
!slotDetail.isIssuerRefunded && block.timestamp < slotDetail.maturity,
"non-mintable slot"
);
totalValue = tokenInAmount_.mul(slotDetail.lowestPrice);
slotDetail.totalValue = slotDetail.totalValue.add(totalValue);
slotBalances[slot_][underlyingToken] = slotBalances[slot_][
underlyingToken
].add(tokenInAmount_);
ERC20TransferHelper.doTransferIn(
underlyingToken,
minter_,
tokenInAmount_
);
emit Mint(minter_, slot_, totalValue);
}
/**
* @dev Allow issuers to refund convertible vouchers with fund currency.
* Refunding is only allowed before the first holder claiming. Once refunded,
* holders will claim in terms of
*/
function refund(uint256 slot_) external override nonReentrant {
require(_issuerSlots[_msgSender()].contains(slot_), "only issuer");
SlotDetail storage slotDetail = _slotDetails[slot_];
require(slotDetail.isValid, "invalid slot");
require(!slotDetail.isIssuerRefunded, "already refunded");
require(slotDetail.settlePrice == 0, "already settled");
slotDetail.isIssuerRefunded = true;
// Calculation of currencyAmount only supports ERC20 stable coins (USDT/USDC/DAI/...)
uint8 currencyDecimals = ERC20Upgradeable(slotDetail.fundCurrency)
.decimals();
uint256 currencyAmount = slotDetail
.totalValue
.mul(10**currencyDecimals)
.div(10**valueDecimals);
slotBalances[slot_][slotDetail.fundCurrency] = slotBalances[slot_][
slotDetail.fundCurrency
].add(currencyAmount);
ERC20TransferHelper.doTransferIn(
slotDetail.fundCurrency,
_msgSender(),
currencyAmount
);
emit Refund(slot_, _msgSender(), currencyAmount);
}
function getWithdrawableAmount(uint256 slot_)
public
view
returns (uint256 withdrawCurrencyAmount, uint256 withdrawTokenAmount)
{
SlotDetail storage slotDetail = _slotDetails[slot_];
if (
block.timestamp >= slotDetail.maturity &&
!slotDetail.isIssuerWithdrawn
) {
uint128 settlePrice = slotDetail.settlePrice;
if (settlePrice == 0) {
settlePrice = getSettlePrice(slot_);
if (settlePrice == 0) {
return (0, 0);
}
}
if (slotDetail.isIssuerRefunded && settlePrice > slotDetail.highestPrice) {
// Calculation of currencyAmount only supports ERC20 stable coins (USDT/USDC/DAI/...)
uint8 currencyDecimals = ERC20Upgradeable(
slotDetail.fundCurrency
).decimals();
uint256 reservedCurrencyAmount = slotBalances[slot_][
slotDetail.fundCurrency
];
withdrawCurrencyAmount = slotDetail
.totalValue
.mul(10**currencyDecimals)
.div(10**valueDecimals);
if (withdrawCurrencyAmount > reservedCurrencyAmount) {
withdrawCurrencyAmount = reservedCurrencyAmount;
}
}
if (slotDetail.isIssuerRefunded && settlePrice <= slotDetail.highestPrice) {
withdrawTokenAmount = slotDetail.totalValue.div(slotDetail.lowestPrice);
} else if (settlePrice > slotDetail.lowestPrice) {
if (settlePrice > slotDetail.highestPrice) {
settlePrice = slotDetail.highestPrice;
}
withdrawTokenAmount = slotDetail
.totalValue
.div(slotDetail.lowestPrice)
.sub(slotDetail.totalValue.div(settlePrice));
}
uint256 reservedTokenAmount = slotBalances[slot_][underlyingToken];
if (withdrawTokenAmount > reservedTokenAmount) {
withdrawTokenAmount = reservedTokenAmount;
}
}
}
/**
* @notice Allow issuers to withdraw fund currency (if refunded) and remaining underlying token after maturity.
*/
function withdraw(uint256 slot_)
external
override
nonReentrant
returns (uint256 withdrawCurrencyAmount, uint256 withdrawTokenAmount)
{
require(_issuerSlots[_msgSender()].contains(slot_), "only issuer");
SlotDetail storage slotDetail = _slotDetails[slot_];
require(!slotDetail.isIssuerWithdrawn, "already withdrawn");
uint128 settlePrice = slotDetail.settlePrice;
if (settlePrice == 0) {
settleConvertiblePrice(slot_);
settlePrice = slotDetail.settlePrice;
if (settlePrice == 0) {
revert("price not settled");
}
}
(withdrawCurrencyAmount, withdrawTokenAmount) = getWithdrawableAmount(
slot_
);
slotDetail.isIssuerWithdrawn = true;
if (withdrawCurrencyAmount > 0) {
slotBalances[slot_][slotDetail.fundCurrency] = slotBalances[slot_][
slotDetail.fundCurrency
].sub(withdrawCurrencyAmount);
ERC20TransferHelper.doTransferOut(
slotDetail.fundCurrency,
_msgSender(),
withdrawCurrencyAmount
);
}
if (withdrawTokenAmount > 0) {
slotBalances[slot_][underlyingToken] = slotBalances[slot_][
underlyingToken
].sub(withdrawTokenAmount);
ERC20TransferHelper.doTransferOut(
underlyingToken,
_msgSender(),
withdrawTokenAmount
);
}
emit Withdraw(
slot_,
_msgSender(),
withdrawCurrencyAmount,
withdrawTokenAmount
);
}
/**
* @notice Allow CV holders to claim fund currency or underlying token after maturity.
*/
function claim(
uint256 slot_,
address to_,
uint256 claimValue_
)
external
override
onlyVoucher
nonReentrant
returns (uint256 claimCurrencyAmount, uint256 claimTokenAmount)
{
SlotDetail storage slotDetail = _slotDetails[slot_];
require(slotDetail.isValid, "invalid slot");
uint128 settlePrice = slotDetail.settlePrice;
if (settlePrice == 0) {
settleConvertiblePrice(slot_);
settlePrice = slotDetail.settlePrice;
if (settlePrice == 0) {
revert("price not settled");
}
}
if (!slotDetail.isClaimed) {
slotDetail.isClaimed = true;
}
if (
settlePrice <= slotDetail.highestPrice && slotDetail.isIssuerRefunded
) {
uint256 reservedCurrencyAmount = slotBalances[slot_][
slotDetail.fundCurrency
];
claimCurrencyAmount = claimValue_
.mul(10 ** ERC20Upgradeable(slotDetail.fundCurrency).decimals())
.div(10 ** valueDecimals);
if (claimCurrencyAmount > reservedCurrencyAmount) {
claimCurrencyAmount = reservedCurrencyAmount;
}
slotBalances[slot_][
slotDetail.fundCurrency
] = reservedCurrencyAmount.sub(claimCurrencyAmount);
ERC20TransferHelper.doTransferOut(
slotDetail.fundCurrency,
payable(to_),
claimCurrencyAmount
);
} else {
if (settlePrice < slotDetail.lowestPrice) {
settlePrice = slotDetail.lowestPrice;
} else if (settlePrice > slotDetail.highestPrice) {
settlePrice = slotDetail.highestPrice;
}
uint256 reservedTokenAmount = slotBalances[slot_][underlyingToken];
claimTokenAmount = claimValue_.div(settlePrice);
if (claimTokenAmount > reservedTokenAmount) {
claimTokenAmount = reservedTokenAmount;
}
slotBalances[slot_][underlyingToken] = reservedTokenAmount.sub(
claimTokenAmount
);
ERC20TransferHelper.doTransferOut(
underlyingToken,
payable(to_),
claimTokenAmount
);
}
}
function settleConvertiblePrice(uint256 slot_) public override {
SlotDetail storage slotDetail = _slotDetails[slot_];
uint128 price = getSettlePrice(slot_);
if (price > 0) {
slotDetail.settlePrice = price;
emit SettlePrice(slot_, slotDetail.settlePrice);
}
}
function getSettlePrice(uint256 slot_)
public
view
override
returns (uint128)
{
SlotDetail storage slotDetail = _slotDetails[slot_];
require(block.timestamp >= slotDetail.maturity, "premature");
int256 iPrice = oracle.getPriceOfMaturity(
voucher,
slotDetail.maturity
);
if (iPrice < 0) {
revert("negative price");
}
return uint128(iPrice);
}
function getSlot(
address issuer_,
address fundCurrency_,
uint128 lowestPrice_,
uint128 highestPrice_,
uint64 effectiveTime_,
uint64 maturity_,
uint8 collateralType_
) public view returns (uint256) {
return
uint256(
keccak256(
abi.encode(
underlyingToken,
underlyingVestingVoucher,
issuer_,
fundCurrency_,
lowestPrice_,
highestPrice_,
effectiveTime_,
maturity_,
collateralType_
)
)
);
}
function getSlotDetail(uint256 slot_)
external
view
returns (SlotDetail memory)
{
return _slotDetails[slot_];
}
function getIssuerSlots(address issuer_)
external
view
returns (uint256[] memory slots)
{
slots = new uint256[](_issuerSlots[issuer_].length());
for (uint256 i = 0; i < slots.length; i++) {
slots[i] = _issuerSlots[issuer_].at(i);
}
}
function getIssuerSlotDetails(address issuer_)
external
view
returns (SlotDetail[] memory slotDetails)
{
slotDetails = new SlotDetail[](_issuerSlots[issuer_].length());
for (uint256 i = 0; i < slotDetails.length; i++) {
slotDetails[i] = _slotDetails[_issuerSlots[issuer_].at(i)];
}
}
function setUnderlyingVestingVoucher(address underlyingVestingVoucher_)
external
onlyAdmin
{
underlyingVestingVoucher = underlyingVestingVoucher_;
}
function setFundCurrency(address fundCurrency_, bool enable_)
external
onlyAdmin
{
fundCurrencies[fundCurrency_] = enable_;
emit SetFundCurrency(fundCurrency_, enable_);
}
function setVoucher(address newVoucher_) external onlyAdmin {
require(newVoucher_ != address(0), "new voucher cannot be 0 address");
emit NewVoucher(voucher, newVoucher_);
voucher = newVoucher_;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
pragma abicoder v2;
interface IConvertiblePool {
enum CollateralType {
ERC20,
VESTING_VOUCHER
}
/**
* @notice Params for Convertible Vouchers.
* totalValue total issue value, decimals = price decimals + underlying token decimals
* @param currency currency address of the fund
* @param lowestPrice decimals fixed at 8
* @param highestPrice decimals fixed at 8
* @param settlePrice settlement price set after maturity, decimals fixed at 8
* @param settings uint16 type settings representing 16 boolean settings
* bit0: isValid
* bit1: isRefunded (if refunded, CV holders will receive currency instead of token)
* bit2: isRedeemed
* bit3: isClaimed, identify if the CV has been claimed by any holder
* bit4 ~ bit15: reserved
*/
struct SlotDetail {
address issuer;
address fundCurrency;
uint256 totalValue;
uint128 lowestPrice;
uint128 highestPrice;
uint128 settlePrice;
uint64 effectiveTime;
uint64 maturity;
CollateralType collateralType;
bool isIssuerRefunded;
bool isIssuerWithdrawn;
bool isClaimed;
bool isValid;
}
/** ===== Begin of events emited by ConvertiblePool ===== */
event NewVoucher(address oldVoucher, address newVoucher);
event SetFundCurrency(address indexed currency, bool enabled);
event CreateSlot(
uint256 indexed slot,
address indexed issuer,
address fundCurrency,
uint128 lowestPrice,
uint128 highestPrice,
uint64 effectiveTime,
uint64 maturity,
CollateralType collateralType
);
event Mint(
address indexed minter,
uint256 indexed slot,
uint256 totalValue
);
event Refund(uint256 indexed slot, address sender, uint256 refundAmount);
event Withdraw(
uint256 indexed slot,
address sender,
uint256 redeemCurrencyAmount,
uint256 redeemUnderlyingTokenAmount
);
event SettlePrice(uint256 indexed slot, uint128 settlePrice);
/** ===== End of events emited by ConvertiblePool ===== */
function mintWithUnderlyingToken(
address minter_,
uint256 slot_,
uint256 tokenInAmount_
) external returns (uint256 totalValue);
function refund(uint256 slot_) external;
function withdraw(uint256 slot_) external returns (uint256, uint256);
function claim(
uint256 slot_,
address to_,
uint256 claimValue_
) external returns (uint256, uint256);
function settleConvertiblePrice(uint256 slot_) external;
function getSettlePrice(uint256 slot_) external view returns (uint128);
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
pragma abicoder v2;
import "./IConvertiblePool.sol";
interface IConvertibleVoucher {
struct ConvertibleVoucherSnapshot {
IConvertiblePool.SlotDetail slotDetail;
uint256 tokenId;
uint256 parValue;
}
/** ===== Begin of events emited by ConvertiblePool ===== */
event SetDescriptor(address oldDescriptor, address newDescriptor);
event SetSolver(address oldSolver, address newSolver);
event Claim (
uint256 indexed tokenId,
address indexed to,
uint256 claimUnits,
uint256 claimCurrencyAmount,
uint256 claimTokenAmount
);
/** ===== End of events emited by ConvertiblePool ===== */
function mint(
address issuer_,
address fundCurrency_,
uint128 lowestPrice_,
uint128 highestPrice_,
uint64 effectiveTime_,
uint64 maturity_,
uint256 tokenInAmount_
)
external
returns (uint256 slot, uint256 tokenId);
function claimAll(uint256 tokenId_) external;
function claim(uint256 tokenId_, uint256 claimUnits_) external;
function claimTo(uint256 tokenId_, address to_, uint256 claimUnits_) external;
function getSlot(
address issuer_,
address fundCurrency_,
uint128 lowestPrice_,
uint128 highestPrice_,
uint64 effectiveTime_,
uint64 maturity_,
uint8 collateralType_
)
external
view
returns (uint256 slot);
function getSlotDetail(uint256 slot_)
external
view
returns (IConvertiblePool.SlotDetail memory);
function getIssuerSlots(address issuer_)
external
view
returns (uint256[] memory slots);
function getSnapshot(uint256 tokenId_)
external
view
returns (ConvertibleVoucherSnapshot memory);
function underlying() external view returns (address);
function underlyingVestingVoucher() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
interface IPriceOracleManager {
function getPriceOfTokenId(address voucher_, uint256 tokenId_)
external
view
returns (int256 price_);
function getPriceOfMaturity(address voucher_, uint64 maturity_)
external
view
returns (int256 price_);
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
interface IVNFTDescriptor {
function contractURI() external view returns (string memory);
function slotURI(uint256 slot) external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
interface IICToken {
function mint(
uint64 term,
uint256 amount,
uint64[] calldata maturities,
uint32[] calldata percentages,
string memory originalInvestor
)
external
returns (uint256 slot, uint256 tokenId);
function vestingPool() external view returns (address);
function underlying() external view returns (address);
}// 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(int p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
}
function logUint(uint p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint)", 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(uint p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint)", 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(uint p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
}
function log(uint p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
}
function log(uint p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
}
function log(uint p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
}
function log(string memory p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint)", 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, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", 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, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint)", 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(uint p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
}
function log(uint p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
}
function log(uint p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
}
function log(uint p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
}
function log(uint p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
}
function log(uint p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
}
function log(uint p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
}
function log(uint p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
}
function log(uint p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
}
function log(uint p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
}
function log(uint p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
}
function log(uint p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
}
function log(uint p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
}
function log(uint p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
}
function log(uint p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
}
function log(uint p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
}
function log(string memory p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
}
function log(string memory p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
}
function log(string memory p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
}
function log(string memory p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", 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, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", 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, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", 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, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
}
function log(bool p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
}
function log(bool p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
}
function log(bool p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", 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, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", 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, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", 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, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
}
function log(address p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
}
function log(address p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
}
function log(address p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", 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, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", 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, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", 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(uint p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", 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, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", 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, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", 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, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", 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, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", 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, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", 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, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", 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, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", 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, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", 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));
}
}{
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1
},
"remappings": [],
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"approval","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allowance","type":"uint256"}],"name":"ApprovalUnits","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"claimUnits","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"claimCurrencyAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"claimTokenAmount","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"targetTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mergeUnits","type":"uint256"}],"name":"Merge","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPendingAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"NewPendingAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldDescriptor","type":"address"},{"indexed":false,"internalType":"address","name":"newDescriptor","type":"address"}],"name":"SetDescriptor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldSolver","type":"address"},{"indexed":false,"internalType":"address","name":"newSolver","type":"address"}],"name":"SetSolver","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"splitUnits","type":"uint256"}],"name":"Split","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"transferUnits","type":"uint256"}],"name":"TransferUnits","type":"event"},{"inputs":[],"name":"acceptAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"spender_","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"allowance_","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"claimUnits_","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"claimAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"claimUnits_","type":"uint256"}],"name":"claimTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"convertiblePool","outputs":[{"internalType":"contract ConvertiblePool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"issuer_","type":"address"}],"name":"getIssuerSlots","outputs":[{"internalType":"uint256[]","name":"slots","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"issuer_","type":"address"},{"internalType":"address","name":"fundCurrency_","type":"address"},{"internalType":"uint128","name":"lowestPrice_","type":"uint128"},{"internalType":"uint128","name":"highestPrice_","type":"uint128"},{"internalType":"uint64","name":"effectiveTime_","type":"uint64"},{"internalType":"uint64","name":"maturity_","type":"uint64"},{"internalType":"uint8","name":"collateralType_","type":"uint8"}],"name":"getSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot_","type":"uint256"}],"name":"getSlotDetail","outputs":[{"components":[{"internalType":"address","name":"issuer","type":"address"},{"internalType":"address","name":"fundCurrency","type":"address"},{"internalType":"uint256","name":"totalValue","type":"uint256"},{"internalType":"uint128","name":"lowestPrice","type":"uint128"},{"internalType":"uint128","name":"highestPrice","type":"uint128"},{"internalType":"uint128","name":"settlePrice","type":"uint128"},{"internalType":"uint64","name":"effectiveTime","type":"uint64"},{"internalType":"uint64","name":"maturity","type":"uint64"},{"internalType":"enum IConvertiblePool.CollateralType","name":"collateralType","type":"uint8"},{"internalType":"bool","name":"isIssuerRefunded","type":"bool"},{"internalType":"bool","name":"isIssuerWithdrawn","type":"bool"},{"internalType":"bool","name":"isClaimed","type":"bool"},{"internalType":"bool","name":"isValid","type":"bool"}],"internalType":"struct IConvertiblePool.SlotDetail","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"getSnapshot","outputs":[{"components":[{"components":[{"internalType":"address","name":"issuer","type":"address"},{"internalType":"address","name":"fundCurrency","type":"address"},{"internalType":"uint256","name":"totalValue","type":"uint256"},{"internalType":"uint128","name":"lowestPrice","type":"uint128"},{"internalType":"uint128","name":"highestPrice","type":"uint128"},{"internalType":"uint128","name":"settlePrice","type":"uint128"},{"internalType":"uint64","name":"effectiveTime","type":"uint64"},{"internalType":"uint64","name":"maturity","type":"uint64"},{"internalType":"enum IConvertiblePool.CollateralType","name":"collateralType","type":"uint8"},{"internalType":"bool","name":"isIssuerRefunded","type":"bool"},{"internalType":"bool","name":"isIssuerWithdrawn","type":"bool"},{"internalType":"bool","name":"isClaimed","type":"bool"},{"internalType":"bool","name":"isValid","type":"bool"}],"internalType":"struct IConvertiblePool.SlotDetail","name":"slotDetail","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"parValue","type":"uint256"}],"internalType":"struct IConvertibleVoucher.ConvertibleVoucherSnapshot","name":"snapshot","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"convertiblePool_","type":"address"},{"internalType":"address","name":"voucherDescriptor_","type":"address"},{"internalType":"address","name":"solver_","type":"address"},{"internalType":"uint8","name":"unitDecimals_","type":"uint8"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds_","type":"uint256[]"},{"internalType":"uint256","name":"targetTokenId_","type":"uint256"}],"name":"merge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"issuer_","type":"address"},{"internalType":"address","name":"fundCurrency_","type":"address"},{"internalType":"uint128","name":"lowestPrice_","type":"uint128"},{"internalType":"uint128","name":"highestPrice_","type":"uint128"},{"internalType":"uint64","name":"effectiveTime_","type":"uint64"},{"internalType":"uint64","name":"maturity_","type":"uint64"},{"internalType":"uint256","name":"tokenInAmount_","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"slot","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextTokenId","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"targetTokenId_","type":"uint256"},{"internalType":"uint256","name":"transferUnits_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"transferUnits_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"safeTransferFrom","outputs":[{"internalType":"uint256","name":"newTokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPendingAdmin_","type":"address"}],"name":"setPendingAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISolver","name":"newSolver_","type":"address"}],"name":"setSolver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newDescriptor_","type":"address"}],"name":"setVoucherDescriptor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"slotOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot_","type":"uint256"}],"name":"slotURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"solver","outputs":[{"internalType":"contract ISolver","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256[]","name":"splitUnits_","type":"uint256[]"}],"name":"split","outputs":[{"internalType":"uint256[]","name":"newTokenIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot_","type":"uint256"},{"internalType":"uint256","name":"index_","type":"uint256"}],"name":"tokenOfSlotByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot_","type":"uint256"}],"name":"tokensInSlot","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":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"targetTokenId_","type":"uint256"},{"internalType":"uint256","name":"transferUnits_","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"transferUnits_","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"uint256","name":"newTokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlyingVestingVoucher","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unitDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot_","type":"uint256"}],"name":"unitsInSlot","outputs":[{"internalType":"uint256","name":"units_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"unitsInToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"voucherDescriptor","outputs":[{"internalType":"contract IVNFTDescriptor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"voucherSlotMapping","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voucherType","outputs":[{"internalType":"enum Constants.VoucherType","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b506155ec806100206000396000f3fe608060405234801561001057600080fd5b50600436106102a95760003560e01c806301ffc9a7146102ae57806305271a2a146102d757806306fdde03146102ec578063076d948c14610301578063081812fc14610321578063095ea7b31461034157806309c3dd87146103565780630e18b6811461036957806318160ddd146103715780631f8794331461037957806323b872dd1461038c578063263f3e7e1461039f57806326782247146103b25780632f745c59146103ba578063360454c5146103cd578063426a8493146103d557806342842e0e146103e857806342966c68146103fb57806349a7a26d1461040e5780634aed53c2146104165780634d47fddb146104295780634dd18bf51461043c5780634f6ccce71461044f57806354fd4d50146104625780636352211e1461046a5780636930fd2a1461047d57806369c67247146104905780636c0360eb146104b05780636f307dc3146104b857806370a08231146104c0578063728c6d2a146104d357806375794a3c146104db57806376f10ad0146104f05780637d47a66a146105105780637e2985f3146105235780638da5cb5b1461053657806390b5a72b1461053e57806394af25eb1461055157806395d89b4114610566578063a22cb4651461056e578063a880042514610581578063b88d4fde14610594578063b9dacaf3146105a7578063bbe33ea5146105c8578063bd819ccd146105db578063bde4c3cb146105e3578063becef607146105f6578063c349026314610609578063c87b56dd1461061c578063d149cc301461062f578063d3b1e9a414610642578063d3ceafb914610655578063e345e0bc14610675578063e8a3d48514610688578063e985e9c514610690578063ecaf82a5146106a3578063f242432a146106b6578063f851a440146106c9578063fe99049a146106d1575b600080fd5b6102c16102bc366004614a86565b6106e4565b6040516102ce919061500c565b60405180910390f35b6102df610707565b6040516102ce919061523f565b6102f4610710565b6040516102ce919061502b565b61031461030f366004614c11565b6107a6565b6040516102ce91906151e2565b61033461032f366004614c11565b6107e1565b6040516102ce9190614e6d565b61035461034f366004614922565b610843565b005b6102f4610364366004614c11565b610919565b6103546109a4565b610314610a8b565b610354610387366004614488565b610a9c565b61035461039a3660046146c9565b610bfc565b6103146103ad366004614c11565b610c53565b610334610c5e565b6103146103c8366004614922565b610c6d565b610334610c96565b6103546103e336600461494d565b610ca5565b6103546103f63660046146c9565b610d18565b610354610409366004614c11565b610d33565b610334610da1565b61035461042436600461482a565b610db0565b61035461043736600461487a565b610e18565b61035461044a366004614488565b610e81565b61031461045d366004614c11565b610f4c565b6102f4610f62565b610334610478366004614c11565b610f81565b61035461048b366004614c11565b610fa9565b6104a361049e366004614c8b565b610fb6565b6040516102ce9190614fc8565b6102f46110ab565b61033461110c565b6103146104ce366004614488565b611189565b6103346111f1565b6104e3611236565b6040516102ce919061522e565b6105036104fe366004614c11565b611242565b6040516102ce91906151a4565b61031461051e366004614638565b6112f7565b610354610531366004614c65565b611390565b6103346116d7565b61035461054c366004614488565b6116eb565b6105596117db565b6040516102ce9190615017565b6102f46117e0565b61035461057c3660046148f5565b611841565b61031461058f366004614c11565b611942565b6103546105a2366004614709565b611959565b6105ba6105b53660046145ac565b6119b7565b6040516102ce92919061520a565b6103546105d6366004614981565b611cfa565b610334611d9a565b6103146105f1366004614c11565b611da9565b610314610604366004614c11565b611dbb565b610354610617366004614cd4565b611dcd565b6102f461062a366004614c11565b611de3565b61031461063d366004614cd4565b611e3a565b6103546106503660046144f8565b611e52565b610668610663366004614c11565b611fc6565b6040516102ce91906151d3565b610314610683366004614c41565b61204f565b6102f461207b565b6102c161069e3660046144c0565b6120fc565b6104a36106b1366004614488565b61212a565b6103146106c43660046147b7565b6121af565b61033461221c565b6103146106df366004614772565b612230565b6001600160e01b0319811660009081526033602052604090205460ff165b919050565b609a5460ff1690565b606a8054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561079c5780601f106107715761010080835404028352916020019161079c565b820191906000526020600020905b81548152906001019060200180831161077f57829003601f168201915b5050505050905090565b6000805b6107b383611942565b8110156107db576107d16107ca6106048584611e3a565b8390612251565b91506001016107aa565b50919050565b60006107ec826122a9565b6108275760405162461bcd60e51b815260040180806020018281038252602c8152602001806154d0602c913960400191505060405180910390fd5b506000908152606860205260409020546001600160a01b031690565b600061084e82610f81565b9050806001600160a01b0316836001600160a01b031614156108a15760405162461bcd60e51b81526004018080602001828103825260218152602001806155456021913960400191505060405180910390fd5b806001600160a01b03166108b36122b6565b6001600160a01b031614806108cf57506108cf8161069e6122b6565b61090a5760405162461bcd60e51b81526004018080602001828103825260388152602001806153f56038913960400191505060405180910390fd5b61091483836122ba565b505050565b60d1546040516309c3dd8760e01b81526060916001600160a01b0316906309c3dd879061094a9085906004016151e2565b60006040518083038186803b15801561096257600080fd5b505afa158015610976573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261099e9190810190614aae565b92915050565b609b546001600160a01b03166109b86122b6565b6001600160a01b031614610a08576040805162461bcd60e51b815260206004820152601260248201527137b7363c903832b73234b7339030b236b4b760711b604482015290519081900360640190fd5b609a54609b54604080516101009093046001600160a01b039081168452909116602083015280517ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc9281900390910190a1609b8054609a8054610100600160a81b0319166101006001600160a01b038416021790556001600160a01b0319169055565b6000610a976066612328565b905090565b609a5461010090046001600160a01b0316610ab56122b6565b6001600160a01b031614610afd576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b806001600160a01b031663060aa71e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b3657600080fd5b505afa158015610b4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6e9190614a6a565b610b935760405162461bcd60e51b8152600401610b8a9061514e565b60405180910390fd5b60d2546040517f83e13471f78e9191627ca7b1f6e515be1905a328ba88749ea97b203d5334e97d91610bd2916001600160a01b03909116908490614f59565b60405180910390a160d280546001600160a01b0319166001600160a01b0392909216919091179055565b610c0d610c076122b6565b82612333565b610c485760405162461bcd60e51b81526004018080602001828103825260318152602001806155666031913960400191505060405180910390fd5b6109148383836123cf565b600061099e82612509565b609b546001600160a01b031681565b6001600160a01b0382166000908152606560205260408120610c8f908361251b565b9392505050565b60d0546001600160a01b031681565b610cae82610f81565b6001600160a01b0316610cbf6122b6565b6001600160a01b031614610d0d576040805162461bcd60e51b815260206004820152601060248201526f2b27232a1d1037b7363c9037bbb732b960811b604482015290519081900360640190fd5b610914838383612527565b61091483838360405180602001604052806000815250611959565b610d3c81610f81565b6001600160a01b0316610d4d6122b6565b6001600160a01b031614610d95576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b604482015290519081900360640190fd5b610d9e816125ec565b50565b60d2546001600160a01b031681565b610db9826122a9565b610e04576040805162461bcd60e51b815260206004820152601760248201527674617267657420746f6b656e206e6f742065786973747360481b604482015290519081900360640190fd5b610e118585858585612604565b5050505050565b610e258686868686610db0565b610e32868685858561262d565b610e79576040805162461bcd60e51b81526020600482015260136024820152723a37903737b7102b27232a2932b1b2b4bb32b960691b604482015290519081900360640190fd5b505050505050565b609a5461010090046001600160a01b0316610e9a6122b6565b6001600160a01b031614610ee2576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b609b54604080516001600160a01b039283168152918316602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a1609b80546001600160a01b0319166001600160a01b0392909216919091179055565b600080610f5a6066846127c2565b509392505050565b604080518082019091526005815264312e302e3160d81b602082015290565b600061099e8260405180606001604052806029815260200161545760299139606691906127e0565b610d9e8161061783611dbb565b606081610ffd576040805162461bcd60e51b815260206004820152601060248201526f656d7074792073706c6974556e69747360801b604482015290519081900360640190fd5b816001600160401b038111801561101357600080fd5b5060405190808252806020026020018201604052801561103d578160200160208202803683370190505b50905060005b82811015610f5a5760006110556127ed565b90508083838151811061106457fe5b60200260200101818152505061108d868287878681811061108157fe5b90506020020135612810565b6000868152609c602052604080822054928252902055600101611043565b606d8054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561079c5780601f106107715761010080835404028352916020019161079c565b60d05460408051632495a59960e01b815290516000926001600160a01b031691632495a599916004808301926020929190829003018186803b15801561115157600080fd5b505afa158015611165573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9791906144a4565b60006001600160a01b0382166111d05760405162461bcd60e51b815260040180806020018281038252602a81526020018061542d602a913960400191505060405180910390fd5b6001600160a01b038216600090815260656020526040902061099e90612328565b60d05460408051633946369560e11b815290516000926001600160a01b03169163728c6d2a916004808301926020929190829003018186803b15801561115157600080fd5b609d5463ffffffff1681565b61124a6141f6565b6020810182905261125a82611dbb565b60408083019190915260d0546000848152609c60205282902054915163d3ceafb960e01b81526001600160a01b039091169163d3ceafb99161129f91906004016151e2565b6101a06040518083038186803b1580156112b857600080fd5b505afa1580156112cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f09190614b17565b8152919050565b60d054604051633ea3d33560e11b81526000916001600160a01b031690637d47a66a90611334908b908b908b908b908b908b908b90600401614f73565b60206040518083038186803b15801561134c57600080fd5b505afa158015611360573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113849190614c29565b98975050505050505050565b6002609e5414156113d6576040805162461bcd60e51b815260206004820152601f602482015260008051602061532d833981519152604482015290519081900360640190fd5b6002609e556113e483610f81565b6001600160a01b03166113f56122b6565b6001600160a01b03161461141b5760405162461bcd60e51b8152600401610b8a906150fb565b61142483611dbb565b8111156114435760405162461bcd60e51b8152600401610b8a9061506b565b60d2546000906001600160a01b031663a4888f1761145f6122b6565b8686866040516020016114759493929190614f0e565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016114a0919061511f565b602060405180830381600087803b1580156114ba57600080fd5b505af11580156114ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f29190614c29565b905080156115125760405162461bcd60e51b8152600401610b8a9061503e565b60d0546000858152609c6020526040808220549051630bce6ea960e31b8152919283926001600160a01b0390911691635e737548916115589190899089906004016151eb565b6040805180830381600087803b15801561157157600080fd5b505af1158015611585573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a99190614cf5565b915091506115b686611dbb565b8414156115cb576115c6866125ec565b6115d7565b6115d58685612961565b505b60d2546001600160a01b0316635e9d02536115f06122b6565b8888886040516020016116069493929190614f0e565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401611631919061511f565b602060405180830381600087803b15801561164b57600080fd5b505af115801561165f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116839190614c29565b50846001600160a01b0316867f318e0a24a7fc05b12e358902d9d58475434a01768f87a4319fb35dc5b533e9868685856040516116c293929190615218565b60405180910390a350506001609e5550505050565b609a5461010090046001600160a01b031690565b609a5461010090046001600160a01b03166117046122b6565b6001600160a01b03161461174c576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b6001600160a01b0381166117725760405162461bcd60e51b8152600401610b8a906150b9565b60d1546040517f7bf0986207bb712ddecd4a4710d515a2b1a1daac7c309dcc1d33544189c6ade9916117b1916001600160a01b03909116908490614f59565b60405180910390a160d180546001600160a01b0319166001600160a01b0392909216919091179055565b600290565b606b8054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561079c5780601f106107715761010080835404028352916020019161079c565b6118496122b6565b6001600160a01b0316826001600160a01b031614156118ab576040805162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b604482015290519081900360640190fd5b80606960006118b86122b6565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff1916921515929092179091556118fc6122b6565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b600081815260996020526040812061099e90612328565b61196a6119646122b6565b83612333565b6119a55760405162461bcd60e51b81526004018080602001828103825260318152602001806155666031913960400191505060405180910390fd5b6119b184848484612a1d565b50505050565b6000806002609e541415611a00576040805162461bcd60e51b815260206004820152601f602482015260008051602061532d833981519152604482015290519081900360640190fd5b6002609e5560d2546000906001600160a01b031663a4888f17611a216122b6565b8c8c8c8c8c8c8c604051602001611a3f989796959493929190614e81565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401611a6a9190615176565b602060405180830381600087803b158015611a8457600080fd5b505af1158015611a98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abc9190614c29565b90508015611adc5760405162461bcd60e51b8152600401610b8a9061503e565b611aec8a8a8a8a8a8a60006112f7565b9250611af783611fc6565b6101800151611b915760d054604051631599157d60e31b81526001600160a01b039091169063acc8abe890611b3d908d908d908d908d908d908d90600090600401614f73565b602060405180830381600087803b158015611b5757600080fd5b505af1158015611b6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b8f9190614c29565b505b60d0546000906001600160a01b0316633e7b37f1611bad6122b6565b86886040518463ffffffff1660e01b8152600401611bcd93929190614f38565b602060405180830381600087803b158015611be757600080fd5b505af1158015611bfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1f9190614c29565b9050611c33611c2c6122b6565b8583612a6f565b60d2549093506001600160a01b0316635e9d0253611c4f6122b6565b8d878786604051602001611c67959493929190614edd565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401611c929190615176565b602060405180830381600087803b158015611cac57600080fd5b505af1158015611cc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce49190614c29565b50506001609e5550909890975095505050505050565b81611d3d576040805162461bcd60e51b815260206004820152600e60248201526d656d70747920746f6b656e49647360901b604482015290519081900360640190fd5b60005b828110156119b157611d64848483818110611d5757fe5b9050602002013583612a98565b609c6000858584818110611d7457fe5b905060200201358152602001908152602001600020600090558080600101915050611d40565b60d1546001600160a01b031681565b609c6020526000908152604090205481565b60009081526097602052604090205490565b611ddf82611dd96122b6565b83611390565b5050565b6060611dee826122a9565b611e0a5760405162461bcd60e51b8152600401610b8a9061508f565b60d15460405163c87b56dd60e01b81526001600160a01b039091169063c87b56dd9061094a9085906004016151e2565b6000828152609960205260408120610c8f908361251b565b600054610100900460ff1680611e6b5750611e6b612c89565b80611e79575060005460ff16155b611eb45760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff16158015611edf576000805460ff1961ff0019909116610100171660011790555b611ee7612c9a565b611f5c85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f890181900481028201810190925287815292508791508690819084018382808284376000920191909152508b9250612d43915050565b60d080546001600160a01b03808c166001600160a01b03199283161790925560d180548b841690831617905560d28054928a1692909116919091179055611fa9632270908360e11b612d73565b8015611fbb576000805461ff00191690555b505050505050505050565b611fce61421d565b60d05460405163d3ceafb960e01b81526001600160a01b039091169063d3ceafb990611ffe9085906004016151e2565b6101a06040518083038186803b15801561201757600080fd5b505afa15801561202b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190614b17565b60008281526098602090815260408083206001600160a01b038516845260010190915290205492915050565b60d1546040805163e8a3d48560e01b815290516060926001600160a01b03169163e8a3d485916004808301926000929190829003018186803b1580156120c057600080fd5b505afa1580156120d4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a979190810190614aae565b6001600160a01b03918216600090815260696020908152604080832093909416825291909152205460ff1690565b60d05460405163ecaf82a560e01b81526060916001600160a01b03169063ecaf82a59061215b908590600401614e6d565b60006040518083038186803b15801561217357600080fd5b505afa158015612187573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261099e91908101906149ca565b60006121bd86868686612230565b90506121cc868683868661262d565b612213576040805162461bcd60e51b81526020600482015260136024820152723a37903737b7102b27232a2932b1b2b4bb32b960691b604482015290519081900360640190fd5b95945050505050565b609a5461010090046001600160a01b031681565b600061223a6127ed565b90506122498585858486612604565b949350505050565b600082820183811015610c8f576040805162461bcd60e51b815260206004820152601b60248201527a536166654d6174683a206164646974696f6e206f766572666c6f7760281b604482015290519081900360640190fd5b600061099e606683612df6565b3390565b600081815260686020526040902080546001600160a01b0319166001600160a01b03841690811790915581906122ef82610f81565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061099e82612e02565b600061233e826122a9565b6123795760405162461bcd60e51b815260040180806020018281038252602c8152602001806153c9602c913960400191505060405180910390fd5b600061238483610f81565b9050806001600160a01b0316846001600160a01b031614806123bf5750836001600160a01b03166123b4846107e1565b6001600160a01b0316145b80612249575061224981856120fc565b826001600160a01b03166123e282610f81565b6001600160a01b0316146124275760405162461bcd60e51b81526004018080602001828103825260298152602001806154fc6029913960400191505060405180910390fd5b6001600160a01b03821661246c5760405162461bcd60e51b815260040180806020018281038252602481526020018061537f6024913960400191505060405180910390fd5b612477838383612e06565b6124826000826122ba565b6001600160a01b03831660009081526065602052604090206124a49082612e1e565b506001600160a01b03821660009081526065602052604090206124c79082612e2a565b506124d460668284612e36565b5080826001600160a01b0316846001600160a01b031660008051602061552583398151915260405160405180910390a4505050565b6000908152609c602052604090205490565b6000610c8f8383612e4c565b60008281526098602090815260408083206001600160a01b03871684526001019091529020546125895760008281526098602090815260408220805460018101825590835291200180546001600160a01b0319166001600160a01b0385161790555b60008281526098602090815260408083206001600160a01b0387168085526001909101835292819020849055805184815290518593927f8a156bd946dc74ec284c5f4b365ce75ef2a5b9d9462b4cdb1d2400cabf136541928290030190a3505050565b6000818152609c6020526040812055610d9e81612eb0565b6126118585858585612f4a565b506000918252609c602052604080832054918352909120555050565b6000612641856001600160a01b03166132b4565b61264d57506001612213565b600061278763b382cdcd60e01b6126626122b6565b8988888860405160240180866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156126d05781810151838201526020016126b8565b50505050905090810190601f1680156126fd5780820380516001836020036101000a031916815260200191505b509650505050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050506040518060400160405280601c81526020017b3737b7102b27232a2932b1b2b4bb32b91034b6b83632b6b2b73a32b960211b815250886001600160a01b03166132ba9092919063ffffffff16565b905060008180602001905160208110156127a057600080fd5b50516001600160e01b03191663b382cdcd60e01b149250505095945050505050565b60008080806127d186866132c9565b909450925050505b9250929050565b6000612249848484613344565b609d805463ffffffff198116600163ffffffff9283169081019092161790915590565b61282161281b6122b6565b84612333565b612871576040805162461bcd60e51b815260206004820152601c60248201527b159391950e881b9bdd081bdddb995c881b9bdc88185c1c1c9bdd995960221b604482015290519081900360640190fd5b61287a826122a9565b156128c7576040805162461bcd60e51b81526020600482015260186024820152776e657720746f6b656e20616c72656164792065786973747360401b604482015290519081900360640190fd5b6000838152609760205260409020546128e0908261340e565b6000848152609760205260408120919091556128fb84610f81565b9050612911818461290b87612509565b8561346b565b83816001600160a01b03167ff66885c33d648fcd0d97e0f2a18e30102169c22763473af0fb716f11b4a17dd68585604051808381526020018281526020019250505060405180910390a350505050565b60008061296d84610f81565b90506129c083604051806040016040528060118152602001706275726e2065786365737320756e69747360781b81525060976000888152602001908152602001600020546135039092919063ffffffff16565b6000858152609760209081526040808320939093558251828152908101869052825187936001600160a01b03861692600080516020615597833981519152929081900390910190a450505060009081526097602052604090205490565b612a288484846123cf565b612a348484848461355d565b6119b15760405162461bcd60e51b815260040180806020018281038252603281526020018061534d6032913960400191505060405180910390fd5b6000612a796127ed565b6000818152609c602052604090208490559050610c8f8482858561346b565b612aa36119646122b6565b612af3576040805162461bcd60e51b815260206004820152601c60248201527b159391950e881b9bdd081bdddb995c881b9bdc88185c1c1c9bdd995960221b604482015290519081900360640190fd5b80821415612b41576040805162461bcd60e51b81526020600482015260166024820152751cd95b19881b595c99d9481b9bdd08185b1b1bddd95960521b604482015290519081900360640190fd5b612b4a81612509565b612b5383612509565b14612b95576040805162461bcd60e51b815260206004820152600d60248201526c0e6d8dee840dad2e6dac2e8c6d609b1b604482015290519081900360640190fd5b6000612ba083610f81565b9050612bab82610f81565b6001600160a01b0316816001600160a01b031614612c01576040805162461bcd60e51b815260206004820152600e60248201526d3737ba1039b0b6b29037bbb732b960911b604482015290519081900360640190fd5b60008381526097602052604080822054848352908220549185905290612c28908290612251565b600084815260976020526040902055612c4084612eb0565b8284836001600160a01b03167fb3ce851d16b3bbec3774d5631a3893dfa2a80e067cfad265dd594402ac3d6096846040518082815260200191505060405180910390a450505050565b6000612c94306132b4565b15905090565b600054610100900460ff1680612cb35750612cb3612c89565b80612cc1575060005460ff16155b612cfc5760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff16158015612d27576000805460ff1961ff0019909116610100171660011790555b612d2f6136c5565b8015610d9e576000805461ff001916905550565b612d53612d4e6122b6565b61376b565b612d5e83838361382d565b5050609d805463ffffffff1916600117905550565b6001600160e01b03198082161415612dd1576040805162461bcd60e51b815260206004820152601c60248201527b115490cc4d8d4e881a5b9d985b1a59081a5b9d195c999858d9481a5960221b604482015290519081900360640190fd5b6001600160e01b0319166000908152603360205260409020805460ff19166001179055565b6000610c8f838361385f565b5490565b6001600160a01b038316156109145761091481613877565b6000610c8f83836138f9565b6000610c8f83836139bf565b600061224984846001600160a01b038516613a09565b81546000908210612e8e5760405162461bcd60e51b815260040180806020018281038252602281526020018061530b6022913960400191505060405180910390fd5b826000018281548110612e9d57fe5b9060005260206000200154905092915050565b6000612ebb82610f81565b90506000612ec883612509565b600084815260976020908152604080832054848452609990925290912091925090612ef39085612e1e565b50600084815260976020526040812055612f0c84613aa0565b604080516000808252602082018490528251879391926001600160a01b0388169260008051602061559783398151915292918290030190a450505050565b612f5383610f81565b6001600160a01b0316856001600160a01b031614612fb6576040805162461bcd60e51b815260206004820152601b60248201527a0e6deeae4c6ca40e8ded6cadc40deeedccae440dad2e6dac2e8c6d602b1b604482015290519081900360640190fd5b6001600160a01b038416613010576040805162461bcd60e51b815260206004820152601c60248201527b7472616e7366657220746f20746865207a65726f206164647265737360201b604482015290519081900360640190fd5b61301d8585858585610e11565b846001600160a01b031661302f6122b6565b6001600160a01b03161415801561304f575061304d8561069e6122b6565b155b15613104576130cf816040518060400160405280602081526020017f7472616e7366657220756e697473206578636565647320616c6c6f77616e63658152506098600087815260200190815260200160002060010160006130ae6122b6565b6001600160a01b031681526020810191909152604001600020549190613503565b6000848152609860205260408120600101906130e96122b6565b6001600160a01b031681526020810191909152604001600020555b60408051808201825260158152747472616e736665722065786365737320756e69747360581b60208083019190915260008681526097909152919091205461314d918390613503565b600084815260976020526040902055613165826122a9565b6131825761317d848361317786612509565b8461346b565b61326b565b836001600160a01b031661319583610f81565b6001600160a01b0316146131ee576040805162461bcd60e51b815260206004820152601b60248201527a0e8c2e4cecae840e8ded6cadc40deeedccae440dad2e6dac2e8c6d602b1b604482015290519081900360640190fd5b6131f782612509565b61320084612509565b14613242576040805162461bcd60e51b815260206004820152600d60248201526c0e6d8dee840dad2e6dac2e8c6d609b1b604482015290519081900360640190fd5b60008281526097602052604090205461325b9082612251565b6000838152609760205260409020555b82846001600160a01b0316866001600160a01b03166000805160206155978339815191528585604051808381526020018281526020019250505060405180910390a45050505050565b3b151590565b60606122498484600085613b5b565b81546000908190831061330d5760405162461bcd60e51b81526004018080602001828103825260228152602001806154ae6022913960400191505060405180910390fd5b600084600001848154811061331e57fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816133df5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156133a457818101518382015260200161338c565b50505050905090810190601f1680156133d15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b508460000160018203815481106133f257fe5b9060005260206000209060020201600101549150509392505050565b600082821115613465576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b613474836122a9565b61349c576134828484613cb6565b600082815260996020526040902061349a9084612e2a565b505b6000838152609760205260409020546134b59082612251565b6000848152609760209081526040808320939093558251868152908101849052825191926001600160a01b03881692849260008051602061559783398151915292908290030190a450505050565b600081848411156135555760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156133a457818101518382015260200161338c565b505050900390565b6000613571846001600160a01b03166132b4565b61357d57506001612249565b600061368b630a85bd0160e11b6135926122b6565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156135f95781810151838201526020016135e1565b50505050905090810190601f1680156136265780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b03838183161783525050505060405180606001604052806032815260200161534d603291396001600160a01b03881691906132ba565b905060008180602001905160208110156136a457600080fd5b50516001600160e01b031916630a85bd0160e11b1492505050949350505050565b600054610100900460ff16806136de57506136de612c89565b806136ec575060005460ff16155b6137275760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff16158015613752576000805460ff1961ff0019909116610100171660011790555b6001609e558015610d9e576000805461ff001916905550565b600054610100900460ff16806137845750613784612c89565b80613792575060005460ff16155b6137cd5760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff161580156137f8576000805460ff1961ff0019909116610100171660011790555b609a8054610100600160a81b0319166101006001600160a01b038516021790558015611ddf576000805461ff00191690555050565b6138378383613dd1565b613847634d84a7d760e11b612d73565b609a805460ff191660ff929092169190911790555050565b60009081526001919091016020526040902054151590565b6000818152609860205260408120905b8154811015610914578160010160008360000183815481106138a557fe5b60009182526020808320909101546001600160a01b0316835282019290925260400181205581548290829081106138d857fe5b600091825260209091200180546001600160a01b0319169055600101613887565b600081815260018301602052604081205480156139b5578354600019808301919081019060009087908390811061392c57fe5b906000526020600020015490508087600001848154811061394957fe5b60009182526020808320909101929092558281526001898101909252604090209084019055865487908061397957fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061099e565b600091505061099e565b60006139cb838361385f565b613a015750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561099e565b50600061099e565b600082815260018401602052604081205480613a6e575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055610c8f565b82856000016001830381548110613a8157fe5b9060005260206000209060020201600101819055506000915050610c8f565b6000613aab82610f81565b9050613ab981600084612e06565b613ac46000836122ba565b6000828152606c60205260409020546002600019610100600184161502019091160415613b02576000828152606c60205260408120613b0291614286565b6001600160a01b0381166000908152606560205260409020613b249083612e1e565b50613b30606683613e8e565b5060405182906000906001600160a01b03841690600080516020615525833981519152908390a45050565b606082471015613b9c5760405162461bcd60e51b81526004018080602001828103825260268152602001806153a36026913960400191505060405180910390fd5b613ba5856132b4565b613bf6576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310613c345780518252601f199092019160209182019101613c15565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613c96576040519150601f19603f3d011682016040523d82523d6000602084013e613c9b565b606091505b5091509150613cab828286613e9a565b979650505050505050565b6001600160a01b038216613d11576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b613d1a816122a9565b15613d6b576040805162461bcd60e51b815260206004820152601c60248201527b115490cdcc8c4e881d1bdad95b88185b1c9958591e481b5a5b9d195960221b604482015290519081900360640190fd5b613d7760008383612e06565b6001600160a01b0382166000908152606560205260409020613d999082612e2a565b50613da660668284612e36565b5060405181906001600160a01b03841690600090600080516020615525833981519152908290a45050565b600054610100900460ff1680613dea5750613dea612c89565b80613df8575060005460ff16155b613e335760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff16158015613e5e576000805460ff1961ff0019909116610100171660011790555b613e66613f00565b613e6e613fa0565b613e78838361403d565b8015610914576000805461ff0019169055505050565b6000610c8f8383614122565b60608315613ea9575081610c8f565b825115613eb95782518084602001fd5b60405162461bcd60e51b81526020600482018181528451602484015284518593919283926044019190850190808383600083156133a457818101518382015260200161338c565b600054610100900460ff1680613f195750613f19612c89565b80613f27575060005460ff16155b613f625760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff16158015612d2f576000805460ff1961ff0019909116610100171660011790558015610d9e576000805461ff001916905550565b600054610100900460ff1680613fb95750613fb9612c89565b80613fc7575060005460ff16155b6140025760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff1615801561402d576000805460ff1961ff0019909116610100171660011790555b612d2f6301ffc9a760e01b612d73565b600054610100900460ff16806140565750614056612c89565b80614064575060005460ff16155b61409f5760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff161580156140ca576000805460ff1961ff0019909116610100171660011790555b82516140dd90606a9060208601906142ca565b5081516140f190606b9060208501906142ca565b506141026380ac58cd60e01b612d73565b614112635b5e139f60e01b612d73565b613e7863780e9d6360e01b612d73565b600081815260018301602052604081205480156139b5578354600019808301919081019060009087908390811061415557fe5b906000526020600020906002020190508087600001848154811061417557fe5b6000918252602080832084546002909302019182556001938401549184019190915583548252898301905260409020908401905586548790806141b457fe5b600082815260208082206002600019909401938402018281556001908101839055929093558881528982019092526040822091909155945061099e9350505050565b604051806060016040528061420961421d565b815260200160008152602001600081525090565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052906101008201908152600060208201819052604082018190526060820181905260809091015290565b50805460018160011615610100020316600290046000825580601f106142ac5750610d9e565b601f016020900490600052602060002090810190610d9e9190614356565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826143005760008555614346565b82601f1061431957805160ff1916838001178555614346565b82800160010185558215614346579182015b8281111561434657825182559160200191906001019061432b565b50614352929150614356565b5090565b5b808211156143525760008155600101614357565b8051610702816152bd565b60008083601f840112614387578182fd5b5081356001600160401b0381111561439d578182fd5b60208301915083602080830285010111156127d957600080fd5b8051610702816152d2565b600082601f8301126143d2578081fd5b81356143e56143e082615270565b61524d565b8181528460208386010111156143f9578283fd5b816020850160208301379081016020019190915292915050565b80516002811061070257600080fd5b60008083601f840112614433578182fd5b5081356001600160401b03811115614449578182fd5b6020830191508360208285010111156127d957600080fd5b8051610702816152e0565b8051610702816152f5565b803560ff8116811461070257600080fd5b600060208284031215614499578081fd5b8135610c8f816152bd565b6000602082840312156144b5578081fd5b8151610c8f816152bd565b600080604083850312156144d2578081fd5b82356144dd816152bd565b915060208301356144ed816152bd565b809150509250929050565b60008060008060008060008060c0898b031215614513578384fd5b883561451e816152bd565b9750602089013561452e816152bd565b9650604089013561453e816152bd565b955061454c60608a01614477565b945060808901356001600160401b0380821115614567578586fd5b6145738c838d01614422565b909650945060a08b013591508082111561458b578384fd5b506145988b828c01614422565b999c989b5096995094979396929594505050565b600080600080600080600060e0888a0312156145c6578081fd5b87356145d1816152bd565b965060208801356145e1816152bd565b955060408801356145f1816152e0565b94506060880135614601816152e0565b93506080880135614611816152f5565b925060a0880135614621816152f5565b8092505060c0880135905092959891949750929550565b600080600080600080600060e0888a031215614652578081fd5b873561465d816152bd565b9650602088013561466d816152bd565b9550604088013561467d816152e0565b9450606088013561468d816152e0565b9350608088013561469d816152f5565b925060a08801356146ad816152f5565b91506146bb60c08901614477565b905092959891949750929550565b6000806000606084860312156146dd578081fd5b83356146e8816152bd565b925060208401356146f8816152bd565b929592945050506040919091013590565b6000806000806080858703121561471e578182fd5b8435614729816152bd565b93506020850135614739816152bd565b92506040850135915060608501356001600160401b0381111561475a578182fd5b614766878288016143c2565b91505092959194509250565b60008060008060808587031215614787578182fd5b8435614792816152bd565b935060208501356147a2816152bd565b93969395505050506040820135916060013590565b600080600080600060a086880312156147ce578283fd5b85356147d9816152bd565b945060208601356147e9816152bd565b9350604086013592506060860135915060808601356001600160401b03811115614811578182fd5b61481d888289016143c2565b9150509295509295909350565b600080600080600060a08688031215614841578283fd5b853561484c816152bd565b9450602086013561485c816152bd565b94979496505050506040830135926060810135926080909101359150565b60008060008060008060c08789031215614892578384fd5b863561489d816152bd565b955060208701356148ad816152bd565b945060408701359350606087013592506080870135915060a08701356001600160401b038111156148dc578182fd5b6148e889828a016143c2565b9150509295509295509295565b60008060408385031215614907578182fd5b8235614912816152bd565b915060208301356144ed816152d2565b60008060408385031215614934578182fd5b823561493f816152bd565b946020939093013593505050565b600080600060608486031215614961578081fd5b833561496c816152bd565b95602085013595506040909401359392505050565b600080600060408486031215614995578081fd5b83356001600160401b038111156149aa578182fd5b6149b686828701614376565b909790965060209590950135949350505050565b600060208083850312156149dc578182fd5b82516001600160401b03808211156149f2578384fd5b818501915085601f830112614a05578384fd5b815181811115614a1157fe5b8381029150614a2184830161524d565b8181528481019084860184860187018a1015614a3b578788fd5b8795505b83861015614a5d578051835260019590950194918601918601614a3f565b5098975050505050505050565b600060208284031215614a7b578081fd5b8151610c8f816152d2565b600060208284031215614a97578081fd5b81356001600160e01b031981168114610c8f578182fd5b600060208284031215614abf578081fd5b81516001600160401b03811115614ad4578182fd5b8201601f81018413614ae4578182fd5b8051614af26143e082615270565b818152856020838501011115614b06578384fd5b612213826020830160208601615291565b60006101a0808385031215614b2a578182fd5b614b338161524d565b9050614b3e8361436b565b8152614b4c6020840161436b565b602082015260408301516040820152614b6760608401614461565b6060820152614b7860808401614461565b6080820152614b8960a08401614461565b60a0820152614b9a60c0840161446c565b60c0820152614bab60e0840161446c565b60e0820152610100614bbe818501614413565b90820152610120614bd08482016143b7565b90820152610140614be28482016143b7565b90820152610160614bf48482016143b7565b90820152610180614c068482016143b7565b908201529392505050565b600060208284031215614c22578081fd5b5035919050565b600060208284031215614c3a578081fd5b5051919050565b60008060408385031215614c53578182fd5b8235915060208301356144ed816152bd565b600080600060608486031215614c79578081fd5b8335925060208401356146f8816152bd565b600080600060408486031215614c9f578081fd5b8335925060208401356001600160401b03811115614cbb578182fd5b614cc786828701614376565b9497909650939450505050565b60008060408385031215614ce6578182fd5b50508035926020909101359150565b60008060408385031215614d07578182fd5b505080516020909101519092909150565b6001600160a01b03169052565b15159052565b60008151808452614d43816020860160208601615291565b601f01601f19169290920160200192915050565b60028110614d6157fe5b9052565b614d70828251614d18565b6020810151614d826020840182614d18565b50604081015160408301526060810151614d9f6060840182614e53565b506080810151614db26080840182614e53565b5060a0810151614dc560a0840182614e53565b5060c0810151614dd860c0840182614e60565b5060e0810151614deb60e0840182614e60565b5061010080820151614dff82850182614d57565b505061012080820151614e1482850182614d25565b505061014080820151614e2982850182614d25565b505061016080820151614e3e82850182614d25565b5050610180808201516119b182850182614d25565b6001600160801b03169052565b6001600160401b03169052565b6001600160a01b0391909116815260200190565b6001600160a01b03988916815296881660208801529490961660408601526001600160801b039283166060860152911660808401526001600160401b0390811660a084015290921660c082015260e08101919091526101000190565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b6001600160a01b039485168152602081019390935292166040820152606081019190915260800190565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0397881681529590961660208601526001600160801b0393841660408601529190921660608401526001600160401b0391821660808401521660a082015260ff90911660c082015260e00190565b6020808252825182820181905260009190848201906040850190845b8181101561500057835183529284019291840191600101614fe4565b50909695505050505050565b901515815260200190565b602081016003831061502557fe5b91905290565b600060208252610c8f6020830184614d2b565b60208082526013908201527214dbdb1d995c8e881b9bdd08185b1b1bddd959606a1b604082015260600190565b6020808252600a90820152696f76657220636c61696d60b01b604082015260600190565b60208082526010908201526f746f6b656e206e6f742065786973747360801b604082015260600190565b60208082526022908201527f6e657744657363726970746f722063616e206e6f742062652030206164647265604082015261737360f01b606082015260800190565b6020808252600a908201526937b7363c9037bbb732b960b11b604082015260600190565b6000604082526005604083015264636c61696d60d81b606083015260806020830152610c8f6080830184614d2b565b6020808252600e908201526d34b73b30b634b21039b7b63b32b960911b604082015260600190565b60006040825260046040830152631b5a5b9d60e21b606083015260806020830152610c8f6080830184614d2b565b60006101e0820190506151b8828451614d65565b60208301516101a08301526040909201516101c09091015290565b6101a0810161099e8284614d65565b90815260200190565b9283526001600160a01b03919091166020830152604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b6040518181016001600160401b038111828210171561526857fe5b604052919050565b60006001600160401b0382111561528357fe5b50601f01601f191660200190565b60005b838110156152ac578181015183820152602001615294565b838111156119b15750506000910152565b6001600160a01b0381168114610d9e57600080fd5b8015158114610d9e57600080fd5b6001600160801b0381168114610d9e57600080fd5b6001600160401b0381168114610d9e57600080fdfe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64735265656e7472616e637947756172643a207265656e7472616e742063616c6c004552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a207472616e7366657220746f20746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564823a343d1c899e61a4db12247636a6882bf1fefae78bef39170f8d0f5b53e456a2646970667358221220772ef00c728ecf879ba340a79beacba83f766c21d1f1235574678aca027c38f364736f6c63430007060033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102a95760003560e01c806301ffc9a7146102ae57806305271a2a146102d757806306fdde03146102ec578063076d948c14610301578063081812fc14610321578063095ea7b31461034157806309c3dd87146103565780630e18b6811461036957806318160ddd146103715780631f8794331461037957806323b872dd1461038c578063263f3e7e1461039f57806326782247146103b25780632f745c59146103ba578063360454c5146103cd578063426a8493146103d557806342842e0e146103e857806342966c68146103fb57806349a7a26d1461040e5780634aed53c2146104165780634d47fddb146104295780634dd18bf51461043c5780634f6ccce71461044f57806354fd4d50146104625780636352211e1461046a5780636930fd2a1461047d57806369c67247146104905780636c0360eb146104b05780636f307dc3146104b857806370a08231146104c0578063728c6d2a146104d357806375794a3c146104db57806376f10ad0146104f05780637d47a66a146105105780637e2985f3146105235780638da5cb5b1461053657806390b5a72b1461053e57806394af25eb1461055157806395d89b4114610566578063a22cb4651461056e578063a880042514610581578063b88d4fde14610594578063b9dacaf3146105a7578063bbe33ea5146105c8578063bd819ccd146105db578063bde4c3cb146105e3578063becef607146105f6578063c349026314610609578063c87b56dd1461061c578063d149cc301461062f578063d3b1e9a414610642578063d3ceafb914610655578063e345e0bc14610675578063e8a3d48514610688578063e985e9c514610690578063ecaf82a5146106a3578063f242432a146106b6578063f851a440146106c9578063fe99049a146106d1575b600080fd5b6102c16102bc366004614a86565b6106e4565b6040516102ce919061500c565b60405180910390f35b6102df610707565b6040516102ce919061523f565b6102f4610710565b6040516102ce919061502b565b61031461030f366004614c11565b6107a6565b6040516102ce91906151e2565b61033461032f366004614c11565b6107e1565b6040516102ce9190614e6d565b61035461034f366004614922565b610843565b005b6102f4610364366004614c11565b610919565b6103546109a4565b610314610a8b565b610354610387366004614488565b610a9c565b61035461039a3660046146c9565b610bfc565b6103146103ad366004614c11565b610c53565b610334610c5e565b6103146103c8366004614922565b610c6d565b610334610c96565b6103546103e336600461494d565b610ca5565b6103546103f63660046146c9565b610d18565b610354610409366004614c11565b610d33565b610334610da1565b61035461042436600461482a565b610db0565b61035461043736600461487a565b610e18565b61035461044a366004614488565b610e81565b61031461045d366004614c11565b610f4c565b6102f4610f62565b610334610478366004614c11565b610f81565b61035461048b366004614c11565b610fa9565b6104a361049e366004614c8b565b610fb6565b6040516102ce9190614fc8565b6102f46110ab565b61033461110c565b6103146104ce366004614488565b611189565b6103346111f1565b6104e3611236565b6040516102ce919061522e565b6105036104fe366004614c11565b611242565b6040516102ce91906151a4565b61031461051e366004614638565b6112f7565b610354610531366004614c65565b611390565b6103346116d7565b61035461054c366004614488565b6116eb565b6105596117db565b6040516102ce9190615017565b6102f46117e0565b61035461057c3660046148f5565b611841565b61031461058f366004614c11565b611942565b6103546105a2366004614709565b611959565b6105ba6105b53660046145ac565b6119b7565b6040516102ce92919061520a565b6103546105d6366004614981565b611cfa565b610334611d9a565b6103146105f1366004614c11565b611da9565b610314610604366004614c11565b611dbb565b610354610617366004614cd4565b611dcd565b6102f461062a366004614c11565b611de3565b61031461063d366004614cd4565b611e3a565b6103546106503660046144f8565b611e52565b610668610663366004614c11565b611fc6565b6040516102ce91906151d3565b610314610683366004614c41565b61204f565b6102f461207b565b6102c161069e3660046144c0565b6120fc565b6104a36106b1366004614488565b61212a565b6103146106c43660046147b7565b6121af565b61033461221c565b6103146106df366004614772565b612230565b6001600160e01b0319811660009081526033602052604090205460ff165b919050565b609a5460ff1690565b606a8054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561079c5780601f106107715761010080835404028352916020019161079c565b820191906000526020600020905b81548152906001019060200180831161077f57829003601f168201915b5050505050905090565b6000805b6107b383611942565b8110156107db576107d16107ca6106048584611e3a565b8390612251565b91506001016107aa565b50919050565b60006107ec826122a9565b6108275760405162461bcd60e51b815260040180806020018281038252602c8152602001806154d0602c913960400191505060405180910390fd5b506000908152606860205260409020546001600160a01b031690565b600061084e82610f81565b9050806001600160a01b0316836001600160a01b031614156108a15760405162461bcd60e51b81526004018080602001828103825260218152602001806155456021913960400191505060405180910390fd5b806001600160a01b03166108b36122b6565b6001600160a01b031614806108cf57506108cf8161069e6122b6565b61090a5760405162461bcd60e51b81526004018080602001828103825260388152602001806153f56038913960400191505060405180910390fd5b61091483836122ba565b505050565b60d1546040516309c3dd8760e01b81526060916001600160a01b0316906309c3dd879061094a9085906004016151e2565b60006040518083038186803b15801561096257600080fd5b505afa158015610976573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261099e9190810190614aae565b92915050565b609b546001600160a01b03166109b86122b6565b6001600160a01b031614610a08576040805162461bcd60e51b815260206004820152601260248201527137b7363c903832b73234b7339030b236b4b760711b604482015290519081900360640190fd5b609a54609b54604080516101009093046001600160a01b039081168452909116602083015280517ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc9281900390910190a1609b8054609a8054610100600160a81b0319166101006001600160a01b038416021790556001600160a01b0319169055565b6000610a976066612328565b905090565b609a5461010090046001600160a01b0316610ab56122b6565b6001600160a01b031614610afd576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b806001600160a01b031663060aa71e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b3657600080fd5b505afa158015610b4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6e9190614a6a565b610b935760405162461bcd60e51b8152600401610b8a9061514e565b60405180910390fd5b60d2546040517f83e13471f78e9191627ca7b1f6e515be1905a328ba88749ea97b203d5334e97d91610bd2916001600160a01b03909116908490614f59565b60405180910390a160d280546001600160a01b0319166001600160a01b0392909216919091179055565b610c0d610c076122b6565b82612333565b610c485760405162461bcd60e51b81526004018080602001828103825260318152602001806155666031913960400191505060405180910390fd5b6109148383836123cf565b600061099e82612509565b609b546001600160a01b031681565b6001600160a01b0382166000908152606560205260408120610c8f908361251b565b9392505050565b60d0546001600160a01b031681565b610cae82610f81565b6001600160a01b0316610cbf6122b6565b6001600160a01b031614610d0d576040805162461bcd60e51b815260206004820152601060248201526f2b27232a1d1037b7363c9037bbb732b960811b604482015290519081900360640190fd5b610914838383612527565b61091483838360405180602001604052806000815250611959565b610d3c81610f81565b6001600160a01b0316610d4d6122b6565b6001600160a01b031614610d95576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b604482015290519081900360640190fd5b610d9e816125ec565b50565b60d2546001600160a01b031681565b610db9826122a9565b610e04576040805162461bcd60e51b815260206004820152601760248201527674617267657420746f6b656e206e6f742065786973747360481b604482015290519081900360640190fd5b610e118585858585612604565b5050505050565b610e258686868686610db0565b610e32868685858561262d565b610e79576040805162461bcd60e51b81526020600482015260136024820152723a37903737b7102b27232a2932b1b2b4bb32b960691b604482015290519081900360640190fd5b505050505050565b609a5461010090046001600160a01b0316610e9a6122b6565b6001600160a01b031614610ee2576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b609b54604080516001600160a01b039283168152918316602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a1609b80546001600160a01b0319166001600160a01b0392909216919091179055565b600080610f5a6066846127c2565b509392505050565b604080518082019091526005815264312e302e3160d81b602082015290565b600061099e8260405180606001604052806029815260200161545760299139606691906127e0565b610d9e8161061783611dbb565b606081610ffd576040805162461bcd60e51b815260206004820152601060248201526f656d7074792073706c6974556e69747360801b604482015290519081900360640190fd5b816001600160401b038111801561101357600080fd5b5060405190808252806020026020018201604052801561103d578160200160208202803683370190505b50905060005b82811015610f5a5760006110556127ed565b90508083838151811061106457fe5b60200260200101818152505061108d868287878681811061108157fe5b90506020020135612810565b6000868152609c602052604080822054928252902055600101611043565b606d8054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561079c5780601f106107715761010080835404028352916020019161079c565b60d05460408051632495a59960e01b815290516000926001600160a01b031691632495a599916004808301926020929190829003018186803b15801561115157600080fd5b505afa158015611165573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9791906144a4565b60006001600160a01b0382166111d05760405162461bcd60e51b815260040180806020018281038252602a81526020018061542d602a913960400191505060405180910390fd5b6001600160a01b038216600090815260656020526040902061099e90612328565b60d05460408051633946369560e11b815290516000926001600160a01b03169163728c6d2a916004808301926020929190829003018186803b15801561115157600080fd5b609d5463ffffffff1681565b61124a6141f6565b6020810182905261125a82611dbb565b60408083019190915260d0546000848152609c60205282902054915163d3ceafb960e01b81526001600160a01b039091169163d3ceafb99161129f91906004016151e2565b6101a06040518083038186803b1580156112b857600080fd5b505afa1580156112cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f09190614b17565b8152919050565b60d054604051633ea3d33560e11b81526000916001600160a01b031690637d47a66a90611334908b908b908b908b908b908b908b90600401614f73565b60206040518083038186803b15801561134c57600080fd5b505afa158015611360573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113849190614c29565b98975050505050505050565b6002609e5414156113d6576040805162461bcd60e51b815260206004820152601f602482015260008051602061532d833981519152604482015290519081900360640190fd5b6002609e556113e483610f81565b6001600160a01b03166113f56122b6565b6001600160a01b03161461141b5760405162461bcd60e51b8152600401610b8a906150fb565b61142483611dbb565b8111156114435760405162461bcd60e51b8152600401610b8a9061506b565b60d2546000906001600160a01b031663a4888f1761145f6122b6565b8686866040516020016114759493929190614f0e565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016114a0919061511f565b602060405180830381600087803b1580156114ba57600080fd5b505af11580156114ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f29190614c29565b905080156115125760405162461bcd60e51b8152600401610b8a9061503e565b60d0546000858152609c6020526040808220549051630bce6ea960e31b8152919283926001600160a01b0390911691635e737548916115589190899089906004016151eb565b6040805180830381600087803b15801561157157600080fd5b505af1158015611585573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a99190614cf5565b915091506115b686611dbb565b8414156115cb576115c6866125ec565b6115d7565b6115d58685612961565b505b60d2546001600160a01b0316635e9d02536115f06122b6565b8888886040516020016116069493929190614f0e565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401611631919061511f565b602060405180830381600087803b15801561164b57600080fd5b505af115801561165f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116839190614c29565b50846001600160a01b0316867f318e0a24a7fc05b12e358902d9d58475434a01768f87a4319fb35dc5b533e9868685856040516116c293929190615218565b60405180910390a350506001609e5550505050565b609a5461010090046001600160a01b031690565b609a5461010090046001600160a01b03166117046122b6565b6001600160a01b03161461174c576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b6001600160a01b0381166117725760405162461bcd60e51b8152600401610b8a906150b9565b60d1546040517f7bf0986207bb712ddecd4a4710d515a2b1a1daac7c309dcc1d33544189c6ade9916117b1916001600160a01b03909116908490614f59565b60405180910390a160d180546001600160a01b0319166001600160a01b0392909216919091179055565b600290565b606b8054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561079c5780601f106107715761010080835404028352916020019161079c565b6118496122b6565b6001600160a01b0316826001600160a01b031614156118ab576040805162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b604482015290519081900360640190fd5b80606960006118b86122b6565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff1916921515929092179091556118fc6122b6565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b600081815260996020526040812061099e90612328565b61196a6119646122b6565b83612333565b6119a55760405162461bcd60e51b81526004018080602001828103825260318152602001806155666031913960400191505060405180910390fd5b6119b184848484612a1d565b50505050565b6000806002609e541415611a00576040805162461bcd60e51b815260206004820152601f602482015260008051602061532d833981519152604482015290519081900360640190fd5b6002609e5560d2546000906001600160a01b031663a4888f17611a216122b6565b8c8c8c8c8c8c8c604051602001611a3f989796959493929190614e81565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401611a6a9190615176565b602060405180830381600087803b158015611a8457600080fd5b505af1158015611a98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abc9190614c29565b90508015611adc5760405162461bcd60e51b8152600401610b8a9061503e565b611aec8a8a8a8a8a8a60006112f7565b9250611af783611fc6565b6101800151611b915760d054604051631599157d60e31b81526001600160a01b039091169063acc8abe890611b3d908d908d908d908d908d908d90600090600401614f73565b602060405180830381600087803b158015611b5757600080fd5b505af1158015611b6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b8f9190614c29565b505b60d0546000906001600160a01b0316633e7b37f1611bad6122b6565b86886040518463ffffffff1660e01b8152600401611bcd93929190614f38565b602060405180830381600087803b158015611be757600080fd5b505af1158015611bfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1f9190614c29565b9050611c33611c2c6122b6565b8583612a6f565b60d2549093506001600160a01b0316635e9d0253611c4f6122b6565b8d878786604051602001611c67959493929190614edd565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401611c929190615176565b602060405180830381600087803b158015611cac57600080fd5b505af1158015611cc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce49190614c29565b50506001609e5550909890975095505050505050565b81611d3d576040805162461bcd60e51b815260206004820152600e60248201526d656d70747920746f6b656e49647360901b604482015290519081900360640190fd5b60005b828110156119b157611d64848483818110611d5757fe5b9050602002013583612a98565b609c6000858584818110611d7457fe5b905060200201358152602001908152602001600020600090558080600101915050611d40565b60d1546001600160a01b031681565b609c6020526000908152604090205481565b60009081526097602052604090205490565b611ddf82611dd96122b6565b83611390565b5050565b6060611dee826122a9565b611e0a5760405162461bcd60e51b8152600401610b8a9061508f565b60d15460405163c87b56dd60e01b81526001600160a01b039091169063c87b56dd9061094a9085906004016151e2565b6000828152609960205260408120610c8f908361251b565b600054610100900460ff1680611e6b5750611e6b612c89565b80611e79575060005460ff16155b611eb45760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff16158015611edf576000805460ff1961ff0019909116610100171660011790555b611ee7612c9a565b611f5c85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f890181900481028201810190925287815292508791508690819084018382808284376000920191909152508b9250612d43915050565b60d080546001600160a01b03808c166001600160a01b03199283161790925560d180548b841690831617905560d28054928a1692909116919091179055611fa9632270908360e11b612d73565b8015611fbb576000805461ff00191690555b505050505050505050565b611fce61421d565b60d05460405163d3ceafb960e01b81526001600160a01b039091169063d3ceafb990611ffe9085906004016151e2565b6101a06040518083038186803b15801561201757600080fd5b505afa15801561202b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190614b17565b60008281526098602090815260408083206001600160a01b038516845260010190915290205492915050565b60d1546040805163e8a3d48560e01b815290516060926001600160a01b03169163e8a3d485916004808301926000929190829003018186803b1580156120c057600080fd5b505afa1580156120d4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a979190810190614aae565b6001600160a01b03918216600090815260696020908152604080832093909416825291909152205460ff1690565b60d05460405163ecaf82a560e01b81526060916001600160a01b03169063ecaf82a59061215b908590600401614e6d565b60006040518083038186803b15801561217357600080fd5b505afa158015612187573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261099e91908101906149ca565b60006121bd86868686612230565b90506121cc868683868661262d565b612213576040805162461bcd60e51b81526020600482015260136024820152723a37903737b7102b27232a2932b1b2b4bb32b960691b604482015290519081900360640190fd5b95945050505050565b609a5461010090046001600160a01b031681565b600061223a6127ed565b90506122498585858486612604565b949350505050565b600082820183811015610c8f576040805162461bcd60e51b815260206004820152601b60248201527a536166654d6174683a206164646974696f6e206f766572666c6f7760281b604482015290519081900360640190fd5b600061099e606683612df6565b3390565b600081815260686020526040902080546001600160a01b0319166001600160a01b03841690811790915581906122ef82610f81565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061099e82612e02565b600061233e826122a9565b6123795760405162461bcd60e51b815260040180806020018281038252602c8152602001806153c9602c913960400191505060405180910390fd5b600061238483610f81565b9050806001600160a01b0316846001600160a01b031614806123bf5750836001600160a01b03166123b4846107e1565b6001600160a01b0316145b80612249575061224981856120fc565b826001600160a01b03166123e282610f81565b6001600160a01b0316146124275760405162461bcd60e51b81526004018080602001828103825260298152602001806154fc6029913960400191505060405180910390fd5b6001600160a01b03821661246c5760405162461bcd60e51b815260040180806020018281038252602481526020018061537f6024913960400191505060405180910390fd5b612477838383612e06565b6124826000826122ba565b6001600160a01b03831660009081526065602052604090206124a49082612e1e565b506001600160a01b03821660009081526065602052604090206124c79082612e2a565b506124d460668284612e36565b5080826001600160a01b0316846001600160a01b031660008051602061552583398151915260405160405180910390a4505050565b6000908152609c602052604090205490565b6000610c8f8383612e4c565b60008281526098602090815260408083206001600160a01b03871684526001019091529020546125895760008281526098602090815260408220805460018101825590835291200180546001600160a01b0319166001600160a01b0385161790555b60008281526098602090815260408083206001600160a01b0387168085526001909101835292819020849055805184815290518593927f8a156bd946dc74ec284c5f4b365ce75ef2a5b9d9462b4cdb1d2400cabf136541928290030190a3505050565b6000818152609c6020526040812055610d9e81612eb0565b6126118585858585612f4a565b506000918252609c602052604080832054918352909120555050565b6000612641856001600160a01b03166132b4565b61264d57506001612213565b600061278763b382cdcd60e01b6126626122b6565b8988888860405160240180866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156126d05781810151838201526020016126b8565b50505050905090810190601f1680156126fd5780820380516001836020036101000a031916815260200191505b509650505050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050506040518060400160405280601c81526020017b3737b7102b27232a2932b1b2b4bb32b91034b6b83632b6b2b73a32b960211b815250886001600160a01b03166132ba9092919063ffffffff16565b905060008180602001905160208110156127a057600080fd5b50516001600160e01b03191663b382cdcd60e01b149250505095945050505050565b60008080806127d186866132c9565b909450925050505b9250929050565b6000612249848484613344565b609d805463ffffffff198116600163ffffffff9283169081019092161790915590565b61282161281b6122b6565b84612333565b612871576040805162461bcd60e51b815260206004820152601c60248201527b159391950e881b9bdd081bdddb995c881b9bdc88185c1c1c9bdd995960221b604482015290519081900360640190fd5b61287a826122a9565b156128c7576040805162461bcd60e51b81526020600482015260186024820152776e657720746f6b656e20616c72656164792065786973747360401b604482015290519081900360640190fd5b6000838152609760205260409020546128e0908261340e565b6000848152609760205260408120919091556128fb84610f81565b9050612911818461290b87612509565b8561346b565b83816001600160a01b03167ff66885c33d648fcd0d97e0f2a18e30102169c22763473af0fb716f11b4a17dd68585604051808381526020018281526020019250505060405180910390a350505050565b60008061296d84610f81565b90506129c083604051806040016040528060118152602001706275726e2065786365737320756e69747360781b81525060976000888152602001908152602001600020546135039092919063ffffffff16565b6000858152609760209081526040808320939093558251828152908101869052825187936001600160a01b03861692600080516020615597833981519152929081900390910190a450505060009081526097602052604090205490565b612a288484846123cf565b612a348484848461355d565b6119b15760405162461bcd60e51b815260040180806020018281038252603281526020018061534d6032913960400191505060405180910390fd5b6000612a796127ed565b6000818152609c602052604090208490559050610c8f8482858561346b565b612aa36119646122b6565b612af3576040805162461bcd60e51b815260206004820152601c60248201527b159391950e881b9bdd081bdddb995c881b9bdc88185c1c1c9bdd995960221b604482015290519081900360640190fd5b80821415612b41576040805162461bcd60e51b81526020600482015260166024820152751cd95b19881b595c99d9481b9bdd08185b1b1bddd95960521b604482015290519081900360640190fd5b612b4a81612509565b612b5383612509565b14612b95576040805162461bcd60e51b815260206004820152600d60248201526c0e6d8dee840dad2e6dac2e8c6d609b1b604482015290519081900360640190fd5b6000612ba083610f81565b9050612bab82610f81565b6001600160a01b0316816001600160a01b031614612c01576040805162461bcd60e51b815260206004820152600e60248201526d3737ba1039b0b6b29037bbb732b960911b604482015290519081900360640190fd5b60008381526097602052604080822054848352908220549185905290612c28908290612251565b600084815260976020526040902055612c4084612eb0565b8284836001600160a01b03167fb3ce851d16b3bbec3774d5631a3893dfa2a80e067cfad265dd594402ac3d6096846040518082815260200191505060405180910390a450505050565b6000612c94306132b4565b15905090565b600054610100900460ff1680612cb35750612cb3612c89565b80612cc1575060005460ff16155b612cfc5760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff16158015612d27576000805460ff1961ff0019909116610100171660011790555b612d2f6136c5565b8015610d9e576000805461ff001916905550565b612d53612d4e6122b6565b61376b565b612d5e83838361382d565b5050609d805463ffffffff1916600117905550565b6001600160e01b03198082161415612dd1576040805162461bcd60e51b815260206004820152601c60248201527b115490cc4d8d4e881a5b9d985b1a59081a5b9d195c999858d9481a5960221b604482015290519081900360640190fd5b6001600160e01b0319166000908152603360205260409020805460ff19166001179055565b6000610c8f838361385f565b5490565b6001600160a01b038316156109145761091481613877565b6000610c8f83836138f9565b6000610c8f83836139bf565b600061224984846001600160a01b038516613a09565b81546000908210612e8e5760405162461bcd60e51b815260040180806020018281038252602281526020018061530b6022913960400191505060405180910390fd5b826000018281548110612e9d57fe5b9060005260206000200154905092915050565b6000612ebb82610f81565b90506000612ec883612509565b600084815260976020908152604080832054848452609990925290912091925090612ef39085612e1e565b50600084815260976020526040812055612f0c84613aa0565b604080516000808252602082018490528251879391926001600160a01b0388169260008051602061559783398151915292918290030190a450505050565b612f5383610f81565b6001600160a01b0316856001600160a01b031614612fb6576040805162461bcd60e51b815260206004820152601b60248201527a0e6deeae4c6ca40e8ded6cadc40deeedccae440dad2e6dac2e8c6d602b1b604482015290519081900360640190fd5b6001600160a01b038416613010576040805162461bcd60e51b815260206004820152601c60248201527b7472616e7366657220746f20746865207a65726f206164647265737360201b604482015290519081900360640190fd5b61301d8585858585610e11565b846001600160a01b031661302f6122b6565b6001600160a01b03161415801561304f575061304d8561069e6122b6565b155b15613104576130cf816040518060400160405280602081526020017f7472616e7366657220756e697473206578636565647320616c6c6f77616e63658152506098600087815260200190815260200160002060010160006130ae6122b6565b6001600160a01b031681526020810191909152604001600020549190613503565b6000848152609860205260408120600101906130e96122b6565b6001600160a01b031681526020810191909152604001600020555b60408051808201825260158152747472616e736665722065786365737320756e69747360581b60208083019190915260008681526097909152919091205461314d918390613503565b600084815260976020526040902055613165826122a9565b6131825761317d848361317786612509565b8461346b565b61326b565b836001600160a01b031661319583610f81565b6001600160a01b0316146131ee576040805162461bcd60e51b815260206004820152601b60248201527a0e8c2e4cecae840e8ded6cadc40deeedccae440dad2e6dac2e8c6d602b1b604482015290519081900360640190fd5b6131f782612509565b61320084612509565b14613242576040805162461bcd60e51b815260206004820152600d60248201526c0e6d8dee840dad2e6dac2e8c6d609b1b604482015290519081900360640190fd5b60008281526097602052604090205461325b9082612251565b6000838152609760205260409020555b82846001600160a01b0316866001600160a01b03166000805160206155978339815191528585604051808381526020018281526020019250505060405180910390a45050505050565b3b151590565b60606122498484600085613b5b565b81546000908190831061330d5760405162461bcd60e51b81526004018080602001828103825260228152602001806154ae6022913960400191505060405180910390fd5b600084600001848154811061331e57fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816133df5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156133a457818101518382015260200161338c565b50505050905090810190601f1680156133d15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b508460000160018203815481106133f257fe5b9060005260206000209060020201600101549150509392505050565b600082821115613465576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b613474836122a9565b61349c576134828484613cb6565b600082815260996020526040902061349a9084612e2a565b505b6000838152609760205260409020546134b59082612251565b6000848152609760209081526040808320939093558251868152908101849052825191926001600160a01b03881692849260008051602061559783398151915292908290030190a450505050565b600081848411156135555760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156133a457818101518382015260200161338c565b505050900390565b6000613571846001600160a01b03166132b4565b61357d57506001612249565b600061368b630a85bd0160e11b6135926122b6565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156135f95781810151838201526020016135e1565b50505050905090810190601f1680156136265780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b03838183161783525050505060405180606001604052806032815260200161534d603291396001600160a01b03881691906132ba565b905060008180602001905160208110156136a457600080fd5b50516001600160e01b031916630a85bd0160e11b1492505050949350505050565b600054610100900460ff16806136de57506136de612c89565b806136ec575060005460ff16155b6137275760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff16158015613752576000805460ff1961ff0019909116610100171660011790555b6001609e558015610d9e576000805461ff001916905550565b600054610100900460ff16806137845750613784612c89565b80613792575060005460ff16155b6137cd5760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff161580156137f8576000805460ff1961ff0019909116610100171660011790555b609a8054610100600160a81b0319166101006001600160a01b038516021790558015611ddf576000805461ff00191690555050565b6138378383613dd1565b613847634d84a7d760e11b612d73565b609a805460ff191660ff929092169190911790555050565b60009081526001919091016020526040902054151590565b6000818152609860205260408120905b8154811015610914578160010160008360000183815481106138a557fe5b60009182526020808320909101546001600160a01b0316835282019290925260400181205581548290829081106138d857fe5b600091825260209091200180546001600160a01b0319169055600101613887565b600081815260018301602052604081205480156139b5578354600019808301919081019060009087908390811061392c57fe5b906000526020600020015490508087600001848154811061394957fe5b60009182526020808320909101929092558281526001898101909252604090209084019055865487908061397957fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061099e565b600091505061099e565b60006139cb838361385f565b613a015750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561099e565b50600061099e565b600082815260018401602052604081205480613a6e575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055610c8f565b82856000016001830381548110613a8157fe5b9060005260206000209060020201600101819055506000915050610c8f565b6000613aab82610f81565b9050613ab981600084612e06565b613ac46000836122ba565b6000828152606c60205260409020546002600019610100600184161502019091160415613b02576000828152606c60205260408120613b0291614286565b6001600160a01b0381166000908152606560205260409020613b249083612e1e565b50613b30606683613e8e565b5060405182906000906001600160a01b03841690600080516020615525833981519152908390a45050565b606082471015613b9c5760405162461bcd60e51b81526004018080602001828103825260268152602001806153a36026913960400191505060405180910390fd5b613ba5856132b4565b613bf6576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310613c345780518252601f199092019160209182019101613c15565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613c96576040519150601f19603f3d011682016040523d82523d6000602084013e613c9b565b606091505b5091509150613cab828286613e9a565b979650505050505050565b6001600160a01b038216613d11576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b613d1a816122a9565b15613d6b576040805162461bcd60e51b815260206004820152601c60248201527b115490cdcc8c4e881d1bdad95b88185b1c9958591e481b5a5b9d195960221b604482015290519081900360640190fd5b613d7760008383612e06565b6001600160a01b0382166000908152606560205260409020613d999082612e2a565b50613da660668284612e36565b5060405181906001600160a01b03841690600090600080516020615525833981519152908290a45050565b600054610100900460ff1680613dea5750613dea612c89565b80613df8575060005460ff16155b613e335760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff16158015613e5e576000805460ff1961ff0019909116610100171660011790555b613e66613f00565b613e6e613fa0565b613e78838361403d565b8015610914576000805461ff0019169055505050565b6000610c8f8383614122565b60608315613ea9575081610c8f565b825115613eb95782518084602001fd5b60405162461bcd60e51b81526020600482018181528451602484015284518593919283926044019190850190808383600083156133a457818101518382015260200161338c565b600054610100900460ff1680613f195750613f19612c89565b80613f27575060005460ff16155b613f625760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff16158015612d2f576000805460ff1961ff0019909116610100171660011790558015610d9e576000805461ff001916905550565b600054610100900460ff1680613fb95750613fb9612c89565b80613fc7575060005460ff16155b6140025760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff1615801561402d576000805460ff1961ff0019909116610100171660011790555b612d2f6301ffc9a760e01b612d73565b600054610100900460ff16806140565750614056612c89565b80614064575060005460ff16155b61409f5760405162461bcd60e51b815260040180806020018281038252602e815260200180615480602e913960400191505060405180910390fd5b600054610100900460ff161580156140ca576000805460ff1961ff0019909116610100171660011790555b82516140dd90606a9060208601906142ca565b5081516140f190606b9060208501906142ca565b506141026380ac58cd60e01b612d73565b614112635b5e139f60e01b612d73565b613e7863780e9d6360e01b612d73565b600081815260018301602052604081205480156139b5578354600019808301919081019060009087908390811061415557fe5b906000526020600020906002020190508087600001848154811061417557fe5b6000918252602080832084546002909302019182556001938401549184019190915583548252898301905260409020908401905586548790806141b457fe5b600082815260208082206002600019909401938402018281556001908101839055929093558881528982019092526040822091909155945061099e9350505050565b604051806060016040528061420961421d565b815260200160008152602001600081525090565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052906101008201908152600060208201819052604082018190526060820181905260809091015290565b50805460018160011615610100020316600290046000825580601f106142ac5750610d9e565b601f016020900490600052602060002090810190610d9e9190614356565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826143005760008555614346565b82601f1061431957805160ff1916838001178555614346565b82800160010185558215614346579182015b8281111561434657825182559160200191906001019061432b565b50614352929150614356565b5090565b5b808211156143525760008155600101614357565b8051610702816152bd565b60008083601f840112614387578182fd5b5081356001600160401b0381111561439d578182fd5b60208301915083602080830285010111156127d957600080fd5b8051610702816152d2565b600082601f8301126143d2578081fd5b81356143e56143e082615270565b61524d565b8181528460208386010111156143f9578283fd5b816020850160208301379081016020019190915292915050565b80516002811061070257600080fd5b60008083601f840112614433578182fd5b5081356001600160401b03811115614449578182fd5b6020830191508360208285010111156127d957600080fd5b8051610702816152e0565b8051610702816152f5565b803560ff8116811461070257600080fd5b600060208284031215614499578081fd5b8135610c8f816152bd565b6000602082840312156144b5578081fd5b8151610c8f816152bd565b600080604083850312156144d2578081fd5b82356144dd816152bd565b915060208301356144ed816152bd565b809150509250929050565b60008060008060008060008060c0898b031215614513578384fd5b883561451e816152bd565b9750602089013561452e816152bd565b9650604089013561453e816152bd565b955061454c60608a01614477565b945060808901356001600160401b0380821115614567578586fd5b6145738c838d01614422565b909650945060a08b013591508082111561458b578384fd5b506145988b828c01614422565b999c989b5096995094979396929594505050565b600080600080600080600060e0888a0312156145c6578081fd5b87356145d1816152bd565b965060208801356145e1816152bd565b955060408801356145f1816152e0565b94506060880135614601816152e0565b93506080880135614611816152f5565b925060a0880135614621816152f5565b8092505060c0880135905092959891949750929550565b600080600080600080600060e0888a031215614652578081fd5b873561465d816152bd565b9650602088013561466d816152bd565b9550604088013561467d816152e0565b9450606088013561468d816152e0565b9350608088013561469d816152f5565b925060a08801356146ad816152f5565b91506146bb60c08901614477565b905092959891949750929550565b6000806000606084860312156146dd578081fd5b83356146e8816152bd565b925060208401356146f8816152bd565b929592945050506040919091013590565b6000806000806080858703121561471e578182fd5b8435614729816152bd565b93506020850135614739816152bd565b92506040850135915060608501356001600160401b0381111561475a578182fd5b614766878288016143c2565b91505092959194509250565b60008060008060808587031215614787578182fd5b8435614792816152bd565b935060208501356147a2816152bd565b93969395505050506040820135916060013590565b600080600080600060a086880312156147ce578283fd5b85356147d9816152bd565b945060208601356147e9816152bd565b9350604086013592506060860135915060808601356001600160401b03811115614811578182fd5b61481d888289016143c2565b9150509295509295909350565b600080600080600060a08688031215614841578283fd5b853561484c816152bd565b9450602086013561485c816152bd565b94979496505050506040830135926060810135926080909101359150565b60008060008060008060c08789031215614892578384fd5b863561489d816152bd565b955060208701356148ad816152bd565b945060408701359350606087013592506080870135915060a08701356001600160401b038111156148dc578182fd5b6148e889828a016143c2565b9150509295509295509295565b60008060408385031215614907578182fd5b8235614912816152bd565b915060208301356144ed816152d2565b60008060408385031215614934578182fd5b823561493f816152bd565b946020939093013593505050565b600080600060608486031215614961578081fd5b833561496c816152bd565b95602085013595506040909401359392505050565b600080600060408486031215614995578081fd5b83356001600160401b038111156149aa578182fd5b6149b686828701614376565b909790965060209590950135949350505050565b600060208083850312156149dc578182fd5b82516001600160401b03808211156149f2578384fd5b818501915085601f830112614a05578384fd5b815181811115614a1157fe5b8381029150614a2184830161524d565b8181528481019084860184860187018a1015614a3b578788fd5b8795505b83861015614a5d578051835260019590950194918601918601614a3f565b5098975050505050505050565b600060208284031215614a7b578081fd5b8151610c8f816152d2565b600060208284031215614a97578081fd5b81356001600160e01b031981168114610c8f578182fd5b600060208284031215614abf578081fd5b81516001600160401b03811115614ad4578182fd5b8201601f81018413614ae4578182fd5b8051614af26143e082615270565b818152856020838501011115614b06578384fd5b612213826020830160208601615291565b60006101a0808385031215614b2a578182fd5b614b338161524d565b9050614b3e8361436b565b8152614b4c6020840161436b565b602082015260408301516040820152614b6760608401614461565b6060820152614b7860808401614461565b6080820152614b8960a08401614461565b60a0820152614b9a60c0840161446c565b60c0820152614bab60e0840161446c565b60e0820152610100614bbe818501614413565b90820152610120614bd08482016143b7565b90820152610140614be28482016143b7565b90820152610160614bf48482016143b7565b90820152610180614c068482016143b7565b908201529392505050565b600060208284031215614c22578081fd5b5035919050565b600060208284031215614c3a578081fd5b5051919050565b60008060408385031215614c53578182fd5b8235915060208301356144ed816152bd565b600080600060608486031215614c79578081fd5b8335925060208401356146f8816152bd565b600080600060408486031215614c9f578081fd5b8335925060208401356001600160401b03811115614cbb578182fd5b614cc786828701614376565b9497909650939450505050565b60008060408385031215614ce6578182fd5b50508035926020909101359150565b60008060408385031215614d07578182fd5b505080516020909101519092909150565b6001600160a01b03169052565b15159052565b60008151808452614d43816020860160208601615291565b601f01601f19169290920160200192915050565b60028110614d6157fe5b9052565b614d70828251614d18565b6020810151614d826020840182614d18565b50604081015160408301526060810151614d9f6060840182614e53565b506080810151614db26080840182614e53565b5060a0810151614dc560a0840182614e53565b5060c0810151614dd860c0840182614e60565b5060e0810151614deb60e0840182614e60565b5061010080820151614dff82850182614d57565b505061012080820151614e1482850182614d25565b505061014080820151614e2982850182614d25565b505061016080820151614e3e82850182614d25565b5050610180808201516119b182850182614d25565b6001600160801b03169052565b6001600160401b03169052565b6001600160a01b0391909116815260200190565b6001600160a01b03988916815296881660208801529490961660408601526001600160801b039283166060860152911660808401526001600160401b0390811660a084015290921660c082015260e08101919091526101000190565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b6001600160a01b039485168152602081019390935292166040820152606081019190915260800190565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0397881681529590961660208601526001600160801b0393841660408601529190921660608401526001600160401b0391821660808401521660a082015260ff90911660c082015260e00190565b6020808252825182820181905260009190848201906040850190845b8181101561500057835183529284019291840191600101614fe4565b50909695505050505050565b901515815260200190565b602081016003831061502557fe5b91905290565b600060208252610c8f6020830184614d2b565b60208082526013908201527214dbdb1d995c8e881b9bdd08185b1b1bddd959606a1b604082015260600190565b6020808252600a90820152696f76657220636c61696d60b01b604082015260600190565b60208082526010908201526f746f6b656e206e6f742065786973747360801b604082015260600190565b60208082526022908201527f6e657744657363726970746f722063616e206e6f742062652030206164647265604082015261737360f01b606082015260800190565b6020808252600a908201526937b7363c9037bbb732b960b11b604082015260600190565b6000604082526005604083015264636c61696d60d81b606083015260806020830152610c8f6080830184614d2b565b6020808252600e908201526d34b73b30b634b21039b7b63b32b960911b604082015260600190565b60006040825260046040830152631b5a5b9d60e21b606083015260806020830152610c8f6080830184614d2b565b60006101e0820190506151b8828451614d65565b60208301516101a08301526040909201516101c09091015290565b6101a0810161099e8284614d65565b90815260200190565b9283526001600160a01b03919091166020830152604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b6040518181016001600160401b038111828210171561526857fe5b604052919050565b60006001600160401b0382111561528357fe5b50601f01601f191660200190565b60005b838110156152ac578181015183820152602001615294565b838111156119b15750506000910152565b6001600160a01b0381168114610d9e57600080fd5b8015158114610d9e57600080fd5b6001600160801b0381168114610d9e57600080fd5b6001600160401b0381168114610d9e57600080fdfe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64735265656e7472616e637947756172643a207265656e7472616e742063616c6c004552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a207472616e7366657220746f20746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564823a343d1c899e61a4db12247636a6882bf1fefae78bef39170f8d0f5b53e456a2646970667358221220772ef00c728ecf879ba340a79beacba83f766c21d1f1235574678aca027c38f364736f6c63430007060033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 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.