Source Code
Latest 25 from a total of 1,211 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Redeem By Margin... | 26298989 | 92 days ago | IN | 0 ETH | 0 | ||||
| Mint Pairs | 26248889 | 93 days ago | IN | 0 ETH | 0 | ||||
| Redeem By Usb | 21693127 | 199 days ago | IN | 0 ETH | 0.00000001 | ||||
| Redeem By Usb | 21693075 | 199 days ago | IN | 0 ETH | 0.00000001 | ||||
| Redeem By Usb | 21615800 | 200 days ago | IN | 0 ETH | 0 | ||||
| Redeem By Usb | 21588724 | 201 days ago | IN | 0 ETH | 0 | ||||
| Redeem By Usb | 21587127 | 201 days ago | IN | 0 ETH | 0.00000001 | ||||
| Redeem By Margin... | 21586436 | 201 days ago | IN | 0 ETH | 0.00000001 | ||||
| Redeem By Pairs ... | 21586425 | 201 days ago | IN | 0 ETH | 0.00000001 | ||||
| Redeem By Margin... | 21578967 | 201 days ago | IN | 0 ETH | 0.00000052 | ||||
| Redeem By Usb | 21578913 | 201 days ago | IN | 0 ETH | 0.00000054 | ||||
| Redeem By Usb | 21572657 | 201 days ago | IN | 0 ETH | 0.00000067 | ||||
| Redeem By Pairs ... | 21568371 | 202 days ago | IN | 0 ETH | 0.00000059 | ||||
| Mint Usb | 21565968 | 202 days ago | IN | 0 ETH | 0.00000065 | ||||
| Redeem By Margin... | 21565942 | 202 days ago | IN | 0 ETH | 0.0000008 | ||||
| Redeem By Pairs ... | 21565919 | 202 days ago | IN | 0 ETH | 0.00000097 | ||||
| Mint Usb | 21565890 | 202 days ago | IN | 0 ETH | 0.00000064 | ||||
| Redeem By Pairs ... | 21565581 | 202 days ago | IN | 0 ETH | 0.00000091 | ||||
| Mint Usb | 21565503 | 202 days ago | IN | 0 ETH | 0.00000061 | ||||
| Redeem By Pairs ... | 21565482 | 202 days ago | IN | 0 ETH | 0.00000094 | ||||
| Mint Usb | 21565378 | 202 days ago | IN | 0 ETH | 0.00000009 | ||||
| Redeem By Pairs ... | 21565340 | 202 days ago | IN | 0 ETH | 0.00000012 | ||||
| Redeem By Usb | 21523952 | 203 days ago | IN | 0 ETH | 0.00000667 | ||||
| Redeem By Usb | 21416467 | 205 days ago | IN | 0 ETH | 0.00000672 | ||||
| Redeem By Usb | 21308980 | 208 days ago | IN | 0 ETH | 0.00000675 |
Latest 2 internal transactions
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 14915228 | 356 days ago | 0 ETH | ||||
| 1866021 | 658 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
StableVaultV2
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 100 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
// import "hardhat/console.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "../libs/Constants.sol";
import "../libs/TokensTransfer.sol";
import "../libs/StableVaultCalculatorV2.sol";
import "../interfaces/IBlast.sol";
import "../interfaces/IWandProtocol.sol";
import "../interfaces/IVault.sol";
import "../interfaces/IPriceFeed.sol";
import "../interfaces/IProtocolSettings.sol";
import "../interfaces/IUsb.sol";
import "../interfaces/IMarginToken.sol";
import "../settings/ProtocolOwner.sol";
import "./TokenPot.sol";
contract StableVaultV2 is IVault, ReentrancyGuard, ProtocolOwner {
using SafeMath for uint256;
using StableVaultCalculatorV2 for StableVaultV2;
bool internal _mintPaused;
bool internal _redeemPaused;
bool internal _usbToMarginTokensPaused;
IProtocolSettings public immutable settings;
TokenPot public immutable tokenPot;
address internal immutable _assetToken;
address internal immutable _usbToken;
address internal immutable _marginToken;
uint256 internal _usbTotalSupply;
uint256 internal _lastYieldsSettlementTime;
uint256 internal _previousAAR;
uint256 internal _aarBelowSafeLineTime;
IPriceFeed public priceFeed;
constructor(
address _wandProtocol,
address _settings,
address _assetToken_,
address _marginToken_,
address _assetTokenPriceFeed_
) ProtocolOwner(_wandProtocol) {
require(
_wandProtocol != address(0) && _settings != address(0) && _assetToken_ != address(0) && _marginToken_ != address(0) && _assetTokenPriceFeed_ != address(0),
"Zero address detected"
);
require((tx.origin == wandProtocol.protocolOwner()) || (_msgSender() == wandProtocol.protocolOwner()) , "Vault should only be created by protocol owner");
tokenPot = new TokenPot(_wandProtocol, _settings);
_assetToken = _assetToken_;
_marginToken = _marginToken_;
_usbToken = wandProtocol.usbToken();
settings = IProtocolSettings(_settings);
_mintPaused = false;
_redeemPaused = false;
_usbToMarginTokensPaused = false;
priceFeed = IPriceFeed(_assetTokenPriceFeed_);
}
receive() external payable {
require(_assetToken == Constants.NATIVE_TOKEN);
TokensTransfer.transferTokens(_assetToken, address(this), address(tokenPot), msg.value);
}
/* ================= VIEWS ================ */
function paused() external view virtual returns (bool, bool, bool) {
return (_mintPaused, _redeemPaused, _usbToMarginTokensPaused);
}
function vaultType() external pure override returns (Constants.VaultType) {
return Constants.VaultType.Stable;
}
function usbToken() external view override returns (address) {
return _usbToken;
}
function usbTotalSupply() public view override returns (uint256) {
return _usbTotalSupply;
}
function assetBalance() external view override returns (uint256) {
return tokenPot.balance(_assetToken);
}
function assetToken() public view override returns (address) {
return _assetToken;
}
function assetTokenDecimals() public view override returns (uint8) {
if (_assetToken == Constants.NATIVE_TOKEN) {
return 18;
}
return IERC20Metadata(_assetToken).decimals();
}
function assetTokenPrice() external view override returns (uint256, uint256) {
return _assetTokenPrice();
}
function marginToken() public view override returns (address) {
return _marginToken;
}
function paramValue(bytes32 param) public view override returns (uint256) {
return settings.vaultParamValue(address(this), param);
}
function vaultMode() external pure override returns (Constants.VaultMode) {
revert("Not supported");
}
function AARDecimals() public pure returns (uint256) {
return Constants.PROTOCOL_DECIMALS;
}
function AARBelowSafeLineTime() public view returns (uint256) {
return _aarBelowSafeLineTime;
}
function AARBelowCircuitBreakerLineTime() public pure returns (uint256) {
revert("Not supported");
}
/* ========== MUTATIVE FUNCTIONS ========== */
function mintUsb(uint256 assetAmount) external payable nonReentrant whenMintNotPaused noneZeroValue(assetAmount) validMsgValue(assetAmount) onUserAction(true) {
(Constants.StableVaultState memory S, uint256 usbOutAmount) = this.calcMintUsbFromStableVault(assetAmount);
require(S.aar >= S.AARS, "AAR Below AARS");
if (_assetToken == Constants.NATIVE_TOKEN) {
TokensTransfer.transferTokens(_assetToken, address(this), address(tokenPot), assetAmount);
}
else {
TokensTransfer.transferTokens(_assetToken, _msgSender(), address(tokenPot), assetAmount);
}
uint256 usbSharesAmount = IUsb(_usbToken).mint(_msgSender(), usbOutAmount);
_usbTotalSupply = _usbTotalSupply.add(usbOutAmount);
emit UsbMinted(_msgSender(), assetAmount, usbOutAmount, usbSharesAmount, S.P_USDC, S.P_USDC_DECIMALS);
}
function mintMarginTokens(uint256 assetAmount) external payable nonReentrant whenMintNotPaused noneZeroValue(assetAmount) validMsgValue(assetAmount) onUserAction(true) {
(Constants.StableVaultState memory S, uint256 marginTokenOutAmount) = this.calcMintMarginTokensFromStableVault(assetAmount);
if (_assetToken == Constants.NATIVE_TOKEN) {
TokensTransfer.transferTokens(_assetToken, address(this), address(tokenPot), assetAmount);
}
else {
TokensTransfer.transferTokens(_assetToken, _msgSender(), address(tokenPot), assetAmount);
}
IMarginToken(_marginToken).mint(_msgSender(), marginTokenOutAmount);
emit MarginTokenMinted(_msgSender(), assetAmount, marginTokenOutAmount, S.P_USDC, S.P_USDC_DECIMALS);
}
function mintPairs(uint256 assetAmount) external payable nonReentrant whenMintNotPaused noneZeroValue(assetAmount) validMsgValue(assetAmount) onUserAction(true) {
(Constants.StableVaultState memory S, uint256 usbOutAmount, uint256 marginTokenOutAmount) = this.calcMintPairsFromStableVault(assetAmount);
if (_assetToken == Constants.NATIVE_TOKEN) {
TokensTransfer.transferTokens(_assetToken, address(this), address(tokenPot), assetAmount);
}
else {
TokensTransfer.transferTokens(_assetToken, _msgSender(), address(tokenPot), assetAmount);
}
uint256 usbSharesAmount = IUsb(_usbToken).mint(_msgSender(), usbOutAmount);
_usbTotalSupply = _usbTotalSupply.add(usbOutAmount);
emit UsbMinted(_msgSender(), assetAmount, usbOutAmount, usbSharesAmount, S.P_USDC, S.P_USDC_DECIMALS);
IMarginToken(_marginToken).mint(_msgSender(), marginTokenOutAmount);
emit MarginTokenMinted(_msgSender(), assetAmount, marginTokenOutAmount, S.P_USDC, S.P_USDC_DECIMALS);
}
function redeemByUsb(uint256 usbAmount) external nonReentrant whenRedeemNotPaused noneZeroValue(usbAmount) onUserAction(true) {
require(usbAmount <= IUsb(_usbToken).balanceOf(_msgSender()), "Not enough USB balance");
(Constants.StableVaultState memory S, , uint256 netRedeemAmount, uint256 feesToTreasury) = this.calcRedeemByUsbFromStableVault(settings, usbAmount);
_doRedeem(netRedeemAmount, feesToTreasury, S, usbAmount, 0);
emit AssetRedeemedWithUsb(_msgSender(), usbAmount, netRedeemAmount, feesToTreasury, S.P_USDC, S.P_USDC_DECIMALS);
}
function redeemByMarginTokens(uint256 marginTokenAmount) external nonReentrant whenRedeemNotPaused noneZeroValue(marginTokenAmount) onUserAction(true) {
require(marginTokenAmount <= IMarginToken(_marginToken).balanceOf(_msgSender()), "Not enough margin token balance");
(Constants.StableVaultState memory S, , uint256 netRedeemAmount, uint256 feesToTreasury) = this.calcRedeemByMarginTokensFromStableVault(settings, marginTokenAmount);
require(S.aar >= S.AARS, "AAR Below AARS");
_doRedeem(netRedeemAmount, feesToTreasury, S, 0, marginTokenAmount);
emit AssetRedeemedWithMarginTokens(_msgSender(), marginTokenAmount, netRedeemAmount, feesToTreasury, S.P_USDC, S.P_USDC_DECIMALS);
}
function redeemByPairsWithExpectedUsbAmount(uint256 usbAmount) external nonReentrant whenRedeemNotPaused noneZeroValue(usbAmount) onUserAction(true) {
require(usbAmount <= IUsb(_usbToken).balanceOf(_msgSender()), "Not enough USB balance");
uint256 pairdMarginTokenAmount = this.calcPairdMarginTokenAmountForStableVault(usbAmount);
require(pairdMarginTokenAmount <= IMarginToken(_marginToken).balanceOf(_msgSender()), "Not enough margin token balance");
(Constants.StableVaultState memory S, , uint256 netRedeemAmount, uint256 feesToTreasury) = this.calcRedeemByPairsAssetAmountForStableVault(settings, pairdMarginTokenAmount);
_doRedeem(netRedeemAmount, feesToTreasury, S, usbAmount, pairdMarginTokenAmount);
emit AssetRedeemedWithPairs(_msgSender(), usbAmount, pairdMarginTokenAmount, netRedeemAmount, feesToTreasury, S.P_USDC, S.P_USDC_DECIMALS);
}
function redeemByPairsWithExpectedMarginTokenAmount(uint256 marginTokenAmount) external nonReentrant whenRedeemNotPaused noneZeroValue(marginTokenAmount) onUserAction(true) {
require(marginTokenAmount <= IMarginToken(_marginToken).balanceOf(_msgSender()), "Not enough margin token balance");
uint256 pairedUSBAmount = this.calcPairedUsbAmountForStableVault(marginTokenAmount);
require(pairedUSBAmount <= IUsb(_usbToken).balanceOf(_msgSender()), "Not enough USB balance");
(Constants.StableVaultState memory S, , uint256 netRedeemAmount, uint256 feesToTreasury) = this.calcRedeemByPairsAssetAmountForStableVault(settings, marginTokenAmount);
_doRedeem(netRedeemAmount, feesToTreasury, S, pairedUSBAmount, marginTokenAmount);
emit AssetRedeemedWithPairs(_msgSender(), pairedUSBAmount, marginTokenAmount, netRedeemAmount, feesToTreasury, S.P_USDC, S.P_USDC_DECIMALS);
}
function usbToMarginTokens(uint256 usbAmount) external nonReentrant whenUsbToMarginTokensNotPaused noneZeroValue(usbAmount) onUserAction(false) {
require(usbAmount <= IUsb(_usbToken).balanceOf(_msgSender()), "Not enough USB balance");
(Constants.StableVaultState memory S, uint256 marginTokenOut) = this.calcUsbToMarginTokensForStableVault(settings, usbAmount);
uint256 usbSharesAmount = IUsb(_usbToken).burn(_msgSender(), usbAmount);
_usbTotalSupply = _usbTotalSupply.sub(usbAmount);
emit UsbBurned(_msgSender(), usbAmount, usbSharesAmount, S.P_USDC, S.P_USDC_DECIMALS);
IMarginToken(_marginToken).mint(_msgSender(), marginTokenOut);
emit MarginTokenMinted(_msgSender(), 0, marginTokenOut, S.P_USDC, S.P_USDC_DECIMALS);
emit UsbToMarginTokens(_msgSender(), usbAmount, marginTokenOut, S.P_USDC, S.P_USDC_DECIMALS);
}
/* ========== RESTRICTED FUNCTIONS ========== */
function configureBlastYieldsAndGas() external onlyOwnerOrProtocol nonReentrant {
address blastAddress = wandProtocol.blastAddress();
if (blastAddress != address(0)) {
IBlast blast = IBlast(wandProtocol.blastAddress());
if (_assetToken == Constants.NATIVE_TOKEN) {
blast.configureAutomaticYield();
}
blast.configureClaimableGas();
tokenPot.configureBlastYieldsAndGas();
IMarginToken(_marginToken).configureBlastYieldsAndGas();
}
}
function configureBlastPoints() external onlyOwnerOrProtocol nonReentrant {
address blastPointsAddress = wandProtocol.blastPointsAddress();
address blastPointsOperatorAddress = wandProtocol.blastPointsOperator();
if (blastPointsAddress != address(0) && blastPointsOperatorAddress != address(0)) {
tokenPot.configureBlastPoints();
}
}
function pauseMint() external nonReentrant onlyOwner {
_mintPaused = true;
emit MintPaused();
}
function unpauseMint() external nonReentrant onlyOwner {
_mintPaused = false;
emit MintUnpaused();
}
function pauseRedeem() external nonReentrant onlyOwner {
_redeemPaused = true;
emit RedeemPaused();
}
function unpauseRedeem() external nonReentrant onlyOwner {
_redeemPaused = false;
emit RedeemUnpaused();
}
function pauseUsbToMarginTokens() external nonReentrant onlyOwner {
_usbToMarginTokensPaused = true;
emit UsbToMarginTokensPaused();
}
function unpauseUsbToMarginTokens() external nonReentrant onlyOwner {
_usbToMarginTokensPaused = false;
emit UsbToMarginTokensUnpaused();
}
function updatePriceFeed(address _assetTokenPriceFeed_) external nonReentrant onlyOwner {
require(_assetTokenPriceFeed_ != address(0), "Zero address detected");
priceFeed = IPriceFeed(_assetTokenPriceFeed_);
}
function _doRedeem(uint256 netRedeemAmount, uint256 feesToTreasury, Constants.StableVaultState memory S, uint256 usbAmount, uint256 marginTokenAmount) internal {
require(netRedeemAmount.add(feesToTreasury) <= tokenPot.balance(_assetToken), "Not enough asset balance");
if (netRedeemAmount > 0) {
tokenPot.withdraw(_msgSender(), _assetToken, netRedeemAmount);
}
if (feesToTreasury > 0) {
tokenPot.withdraw(settings.treasury(), _assetToken, feesToTreasury);
}
if (usbAmount > 0) {
uint256 usbBurnShares = IUsb(_usbToken).burn(_msgSender(), usbAmount);
_usbTotalSupply = _usbTotalSupply.sub(usbAmount);
emit UsbBurned(_msgSender(), usbAmount, usbBurnShares, S.P_USDC, S.P_USDC_DECIMALS);
}
if (marginTokenAmount > 0) {
IMarginToken(_marginToken).burn(_msgSender(), marginTokenAmount);
emit MarginTokenBurned(_msgSender(), marginTokenAmount, S.P_USDC, S.P_USDC_DECIMALS);
}
}
function _doSettleYields(uint256 yieldsBaseAssetAmount) internal {
uint256 timeElapsed = block.timestamp.sub(_lastYieldsSettlementTime);
uint256 Y = paramValue("Y");
uint256 deltaAssetAmount = timeElapsed.mul(Y).mul(yieldsBaseAssetAmount).div(365 days).div(10 ** settings.decimals());
if (deltaAssetAmount > 0) {
(, uint256 usbOutAmount) = this.calcMintUsbFromStableVault(deltaAssetAmount);
IUsb(_usbToken).rebase(usbOutAmount);
_usbTotalSupply = _usbTotalSupply.add(usbOutAmount);
emit YieldsSettlement(usbOutAmount);
}
}
function _updateStateOnUserAction(uint256 previousAAR, uint256 afterAAR) internal {
uint256 AARS = paramValue("AARS");
if (previousAAR >= AARS && afterAAR < AARS) {
_aarBelowSafeLineTime = block.timestamp;
}
else if (previousAAR < AARS && afterAAR >= AARS) {
_aarBelowSafeLineTime = 0;
}
}
function _assetTokenPrice() internal view returns (uint256, uint256) {
return (priceFeed.latestPrice(), priceFeed.decimals());
}
/* ============== MODIFIERS =============== */
modifier whenMintNotPaused() {
require(!_mintPaused, "Mint paused");
_;
}
modifier whenRedeemNotPaused() {
require(!_redeemPaused, "Redeem paused");
_;
}
modifier whenUsbToMarginTokensNotPaused() {
require(!_usbToMarginTokensPaused, "USB to Margin Tokens paused");
_;
}
modifier noneZeroValue(uint256 value) {
require(value > 0, "Value must be greater than 0");
_;
}
modifier validMsgValue(uint256 value) {
if (_assetToken == Constants.NATIVE_TOKEN) {
require(msg.value == value, "Invalid msg value");
}
else {
require(msg.value == 0, "msg.value should be 0");
}
_;
}
modifier noneZeroAddress(address addr) {
require(addr != address(0), "Zero address detected");
_;
}
modifier onlyOwnerOrProtocol() {
require(_msgSender() == address(wandProtocol) || _msgSender() == owner());
_;
}
modifier onUserAction(bool settleYields) {
uint256 yieldsBaseAssetAmount = tokenPot.balance(_assetToken);
_;
if (settleYields) {
if (_lastYieldsSettlementTime != 0) {
_doSettleYields(yieldsBaseAssetAmount);
}
_lastYieldsSettlementTime = block.timestamp;
}
uint256 afterAAR = this.AAR();
_updateStateOnUserAction(_previousAAR, afterAAR);
_previousAAR = this.AAR();
address blastAddress = wandProtocol.blastAddress();
if (blastAddress != address(0)) {
IBlast blast = IBlast(blastAddress);
(uint256 etherSeconds, uint256 etherBalance, ,) = blast.readGasParams(address(this));
if (etherSeconds > 0 && etherBalance > 0) {
blast.claimAllGas(address(this), settings.treasury());
}
}
}
/* =============== EVENTS ============= */
event MintPaused();
event MintUnpaused();
event RedeemPaused();
event RedeemUnpaused();
event UsbToMarginTokensPaused();
event UsbToMarginTokensUnpaused();
event UsbMinted(address indexed user, uint256 assetTokenAmount, uint256 usbTokenAmount, uint256 usbSharesAmount, uint256 assetTokenPrice, uint256 assetTokenPriceDecimals);
event MarginTokenMinted(address indexed user, uint256 assetTokenAmount, uint256 marginTokenAmount, uint256 assetTokenPrice, uint256 assetTokenPriceDecimals);
event UsbBurned(address indexed user, uint256 usbTokenAmount, uint256 usbSharesAmount, uint256 assetTokenPrice, uint256 assetTokenPriceDecimals);
event MarginTokenBurned(address indexed user, uint256 marginTokenAmount, uint256 assetTokenPrice, uint256 assetTokenPriceDecimals);
event AssetRedeemedWithUsb(address indexed user, uint256 usbTokenAmount, uint256 netAssetAmount, uint256 feesToTreasury, uint256 assetTokenPrice, uint256 assetTokenPriceDecimals);
event AssetRedeemedWithMarginTokens(address indexed user, uint256 marginTokenAmount, uint256 netAssetAmount, uint256 feesToTreasury, uint256 assetTokenPrice, uint256 assetTokenPriceDecimals);
event AssetRedeemedWithPairs(address indexed user, uint256 usbAmount, uint256 marginTokenAmount, uint256 netAssetAmount, uint256 feesToTreasury, uint256 assetTokenPrice, uint256 assetTokenPriceDecimals);
event UsbToMarginTokens(address indexed user, uint256 usbAmount, uint256 xTokenAmount, uint256 assetTokenPrice, uint256 assetTokenPriceDecimals);
event YieldsSettlement(uint256 usbYieldsAmount);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to
* 0 before setting it to a non-zero value.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
enum YieldMode {
AUTOMATIC,
VOID,
CLAIMABLE
}
enum GasMode {
VOID,
CLAIMABLE
}
interface IBlast{
// configure
function configureContract(address contractAddress, YieldMode _yield, GasMode gasMode, address governor) external;
function configure(YieldMode _yield, GasMode gasMode, address governor) external;
// base configuration options
function configureClaimableYield() external;
function configureClaimableYieldOnBehalf(address contractAddress) external;
function configureAutomaticYield() external;
function configureAutomaticYieldOnBehalf(address contractAddress) external;
function configureVoidYield() external;
function configureVoidYieldOnBehalf(address contractAddress) external;
function configureClaimableGas() external;
function configureClaimableGasOnBehalf(address contractAddress) external;
function configureVoidGas() external;
function configureVoidGasOnBehalf(address contractAddress) external;
function configureGovernor(address _governor) external;
function configureGovernorOnBehalf(address _newGovernor, address contractAddress) external;
// claim yield
function claimYield(address contractAddress, address recipientOfYield, uint256 amount) external returns (uint256);
function claimAllYield(address contractAddress, address recipientOfYield) external returns (uint256);
// claim gas
function claimAllGas(address contractAddress, address recipientOfGas) external returns (uint256);
function claimGasAtMinClaimRate(address contractAddress, address recipientOfGas, uint256 minClaimRateBips) external returns (uint256);
function claimMaxGas(address contractAddress, address recipientOfGas) external returns (uint256);
function claimGas(address contractAddress, address recipientOfGas, uint256 gasToClaim, uint256 gasSecondsToConsume) external returns (uint256);
// read functions
function readClaimableYield(address contractAddress) external view returns (uint256);
function readYieldConfiguration(address contractAddress) external view returns (uint8);
function readGasParams(address contractAddress) external view returns (uint256 etherSeconds, uint256 etherBalance, uint256 lastUpdated, GasMode);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
interface IBlastPoints {
function configurePointsOperator(address operator) external;
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IMarginToken is IERC20 {
function configureBlastYieldsAndGas() external;
function mint(address to, uint256 amount) external;
function burn(address account, uint256 amount) external;
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
interface IPriceFeed {
/**
* @notice The number of decimals in the returned price
*/
function decimals() external view returns (uint8);
/**
* @notice Returns the latest price of the asset in USD
*/
function latestPrice() external view returns (uint256);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
interface IProtocolSettings {
function treasury() external view returns (address);
function decimals() external view returns (uint256);
function isValidParam(bytes32 param, uint256 value) external view returns (bool);
function paramDefaultValue(bytes32 param) external view returns (uint256);
function vaultParamValue(address vault, bytes32 param) external view returns (uint256);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
interface IPtyPool {
function vault() external view returns (address);
function totalStakingShares() external view returns (uint256);
function totalStakingBalance() external view returns (uint256);
function addStakingYields(uint256 yieldsAmount) external;
function addMatchingYields(uint256 yieldsAmount) external;
function configureBlastYieldsAndGas() external;
function configureBlastPoints() external;
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IUsb is IERC20 {
function decimals() external view returns (uint8);
function getBalanceByShares(uint256 sharesAmount) external view returns (uint256);
function getSharesByBalance(uint256 balance) external view returns (uint256);
function configureBlastYieldsAndGas() external;
function mint(address to, uint256 amount) external returns (uint256);
function burn(address account, uint256 amount) external returns (uint256);
function transferShares(address to, uint256 sharesAmount) external returns (uint256);
function rebase(uint256 addedSupply) external;
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
import "../libs/Constants.sol";
interface IVault {
function vaultType() external pure returns (Constants.VaultType);
function AARDecimals() external pure returns (uint256);
function usbToken() external view returns (address);
function assetToken() external view returns (address);
function assetTokenDecimals() external view returns (uint8);
function assetTokenPrice() external view returns (uint256, uint256);
function assetBalance() external view returns (uint256);
function usbTotalSupply() external view returns (uint256);
function marginToken() external view returns (address);
function vaultMode() external view returns (Constants.VaultMode);
function paramValue(bytes32 param) external view returns (uint256);
function AARBelowSafeLineTime() external view returns (uint256);
function AARBelowCircuitBreakerLineTime() external view returns (uint256);
function configureBlastYieldsAndGas() external;
function configureBlastPoints() external;
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
interface IWandProtocol {
function protocolOwner() external view returns (address);
function usbToken() external view returns (address);
function blastAddress() external view returns (address);
function blastPointsAddress() external view returns (address);
function blastPointsOperator() external view returns (address);
function isVault(address vaultAddress) external view returns (bool);
function isVaultAsset(address assetToken) external view returns (bool);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
library Constants {
/**
* @notice The address interpreted as native token of the chain.
*/
address public constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
uint256 public constant PROTOCOL_DECIMALS = 10;
struct Terms {
uint256 T1;
uint256 T2;
uint256 T3;
uint256 T4;
uint256 T5;
uint256 T6;
uint256 T7;
uint256 T8;
}
enum VaultType {
Volatile,
Stable
}
enum VaultMode {
Empty,
Stability,
AdjustmentBelowAARS,
AdjustmentAboveAARU
}
struct VaultState {
uint256 M_ETH;
uint256 P_ETH;
uint256 P_ETH_DECIMALS;
uint256 M_USB_ETH;
uint256 M_ETHx;
uint256 aar;
uint256 AART;
uint256 AARS;
uint256 AARU;
uint256 AARC;
uint256 AARDecimals;
uint256 RateR;
uint256 AARBelowSafeLineTime;
uint256 AARBelowCircuitBreakerLineTime;
}
struct StableVaultState {
uint256 M_USDC;
uint256 P_USDC;
uint256 P_USDC_DECIMALS;
uint256 M_USB_USDC;
uint256 M_USDCx;
uint256 aar;
// uint256 AART;
uint256 AARS;
// uint256 AARU;
// uint256 AARC;
uint256 AARDecimals;
uint256 RateR;
uint256 AARBelowSafeLineTime;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
// import "hardhat/console.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "./Constants.sol";
import "../interfaces/IProtocolSettings.sol";
import "../interfaces/IPtyPool.sol";
import "../interfaces/IUsb.sol";
import "../interfaces/IVault.sol";
library StableVaultCalculatorV2 {
using SafeMath for uint256;
// 𝑟 = self.RateR() × 𝑡(h𝑟𝑠), since aar drop below AARS;
// r = 0 since aar above AARS;
function _r(uint256 aarBelowSafeLineTime, uint256 rateR) internal view returns (uint256) {
if (aarBelowSafeLineTime == 0) {
return 0;
}
return rateR.mul(block.timestamp.sub(aarBelowSafeLineTime)).div(1 hours);
}
function AAR(IVault self) public view returns (uint256) {
uint256 assetTotalAmount = self.assetBalance();
if (assetTotalAmount == 0) {
return 0;
}
if (self.usbTotalSupply() == 0) {
return type(uint256).max;
}
(uint256 assetTokenPrice, uint256 assetTokenPriceDecimals) = self.assetTokenPrice();
return assetTotalAmount.mul(assetTokenPrice).div(10 ** assetTokenPriceDecimals).mul(10 ** self.AARDecimals()).div(self.usbTotalSupply());
}
function getStableVaultState(IVault self) public view returns (Constants.StableVaultState memory) {
Constants.StableVaultState memory S;
S.M_USDC = self.assetBalance();
(S.P_USDC, S.P_USDC_DECIMALS) = self.assetTokenPrice() ;
S.M_USB_USDC = self.usbTotalSupply();
S.M_USDCx = IERC20(self.marginToken()).totalSupply();
S.aar = AAR(self);
// S.AART = self.paramValue("AART");
S.AARS = self.paramValue("AARS");
// S.AARU = self.paramValue("AARU");
// S.AARC = self.paramValue("AARC");
S.AARDecimals = self.AARDecimals();
S.RateR = self.paramValue("RateR");
S.AARBelowSafeLineTime = self.AARBelowSafeLineTime();
return S;
}
function calcMintUsbFromStableVault(IVault self, uint256 assetAmount) public view returns (Constants.StableVaultState memory, uint256) {
require(assetAmount > 0, "Amount must be greater than 0");
Constants.StableVaultState memory S = getStableVaultState(self);
require(S.M_USDCx > 0, "Margin token balance is 0");
// ΔUSB = ΔUSDC * P_USDC
uint256 usbOutAmount = assetAmount.mul(S.P_USDC).div(10 ** S.P_USDC_DECIMALS);
return (S, usbOutAmount);
}
function calcMintMarginTokensFromStableVault(IVault self, uint256 assetAmount) public view returns (Constants.StableVaultState memory, uint256) {
require(assetAmount > 0, "Amount must be greater than 0");
Constants.StableVaultState memory S = getStableVaultState(self);
uint256 marginTokenOutAmount;
if (S.M_USDCx == 0) {
// ΔUSDCx = ΔUSDC
marginTokenOutAmount = assetAmount;
}
else {
uint256 aar101 = (101 * (10 ** (S.AARDecimals - 2)));
if (S.aar >= aar101) { // aar >= 101% {
// ΔUSDCx = ΔUSDC * P_USDC * M_USDCx / (M_USDC * P_USDC - M_USB_USDC)
marginTokenOutAmount = assetAmount.mul(S.P_USDC).div(10 ** S.P_USDC_DECIMALS).mul(S.M_USDCx).div(
S.M_USDC.mul(S.P_USDC).div(10 ** S.P_USDC_DECIMALS).sub(S.M_USB_USDC)
);
}
else {
// ΔUSDCx = ΔUSDC * P_USDC * M_USDCx * 100 / M_USB_USDC
marginTokenOutAmount = assetAmount.mul(S.P_USDC).div(10 ** S.P_USDC_DECIMALS).mul(S.M_USDCx).mul(100).div(S.M_USB_USDC);
}
}
return (S, marginTokenOutAmount);
}
function calcMintPairsFromStableVault(IVault self, uint256 assetAmount) public view returns (Constants.StableVaultState memory, uint256, uint256) {
require(assetAmount > 0, "Amount must be greater than 0");
Constants.StableVaultState memory S = getStableVaultState(self);
require(S.M_USDCx > 0, "Margin token balance is 0");
// require(S.aar < S.AARS, "AAR Above AARS");
// ΔUSB = ΔUSDC * M_USB_USDC / M_USDC
// ΔUSDCx = ΔUSB * M_USDCx / M_USB_USDC
uint256 usbOutAmount = assetAmount.mul(S.M_USB_USDC).div(S.M_USDC);
uint256 marginTokenOutAmount = usbOutAmount.mul(S.M_USDCx).div(S.M_USB_USDC);
return (S, usbOutAmount, marginTokenOutAmount);
}
function calcRedeemFeesFromStableVault(IVault self, IProtocolSettings settings, uint256 assetAmount) public view returns (uint256, uint256) {
uint256 totalFees = assetAmount.mul(self.paramValue("C")).div(10 ** settings.decimals());
uint256 feesToTreasury = totalFees.mul(self.paramValue("TreasuryFeeRate")).div(10 ** settings.decimals());
uint256 netRedeemAmount = assetAmount.sub(totalFees);
return (netRedeemAmount, feesToTreasury);
}
function calcRedeemByUsbFromStableVault(IVault self, IProtocolSettings settings, uint256 usbAmount) public view returns (Constants.StableVaultState memory, uint256, uint256, uint256) {
require(usbAmount > 0, "Amount must be greater than 0");
Constants.StableVaultState memory S = getStableVaultState(self);
uint256 assetOutAmount;
if (S.aar >= (10 ** S.AARDecimals)) {
// ΔUSDC = ΔUSB / P_USDC
assetOutAmount = usbAmount.mul(10 ** S.P_USDC_DECIMALS).div(S.P_USDC);
}
else {
// ΔUSDC = ΔUSB * M_USDC / M_USB_USDC
assetOutAmount = usbAmount.mul(S.M_USDC).div(S.M_USB_USDC);
}
(uint256 netRedeemAmount, uint256 feesToTreasury) = calcRedeemFeesFromStableVault(self, settings, assetOutAmount);
return (S, assetOutAmount, netRedeemAmount, feesToTreasury);
}
function calcRedeemByMarginTokensFromStableVault(IVault self, IProtocolSettings settings, uint256 marginTokenAmount) public view returns (Constants.StableVaultState memory, uint256, uint256, uint256) {
require(marginTokenAmount > 0, "Amount must be greater than 0");
Constants.StableVaultState memory S = getStableVaultState(self);
// ΔUSDC = M_USDC * ΔUSDCx / M_USDCx - M_USB_USDC * ΔUSDCx / (M_USDCx * P_USDC)
uint256 a = S.M_USDC.mul(marginTokenAmount).div(S.M_USDCx);
uint256 b = S.M_USB_USDC.mul(marginTokenAmount).div(S.M_USDCx.mul(S.P_USDC).div(10 ** S.P_USDC_DECIMALS));
uint256 assetOutAmount = a > b ? a - b : 0;
(uint256 netRedeemAmount, uint256 feesToTreasury) = calcRedeemFeesFromStableVault(self, settings, assetOutAmount);
return (S, assetOutAmount, netRedeemAmount, feesToTreasury);
}
function calcPairdMarginTokenAmountForStableVault(IVault self, uint256 usbAmount) public view returns (uint256) {
require(usbAmount > 0, "Amount must be greater than 0");
Constants.StableVaultState memory S = getStableVaultState(self);
// require(S.aar < S.AARS, "AAR Above AARS");
// ΔUSB = ΔUSDCx * M_USB_USDC / M_USDCx
// ΔUSDCx = ΔUSB * M_USDCx / M_USB_USDC
uint256 marginTokenOutAmount = usbAmount.mul(S.M_USDCx).div(S.M_USB_USDC);
return marginTokenOutAmount;
}
function calcPairedUsbAmountForStableVault(IVault self, uint256 marginTokenAmount) public view returns (uint256) {
require(marginTokenAmount > 0, "Amount must be greater than 0");
Constants.StableVaultState memory S = getStableVaultState(self);
// require(S.aar < S.AARS, "AAR Above AARS");
// ΔUSDCx = ΔUSB * M_USDCx / M_USB_USDC
// ΔUSB = ΔUSDCx * M_USB_USDC / M_USDCx
uint256 usbOutAmount = marginTokenAmount.mul(S.M_USB_USDC).div(S.M_USDCx);
return usbOutAmount;
}
function calcRedeemByPairsAssetAmountForStableVault(IVault self, IProtocolSettings settings, uint256 marginTokenAmount) public view returns (Constants.StableVaultState memory, uint256, uint256, uint256) {
Constants.StableVaultState memory S = getStableVaultState(self);
// ΔUSDC = ΔUSDCx * M_USDC / M_USDCx
uint256 assetOutAmount = marginTokenAmount.mul(S.M_USDC).div(S.M_USDCx);
(uint256 netRedeemAmount, uint256 feesToTreasury) = calcRedeemFeesFromStableVault(self, settings, assetOutAmount);
return (S, assetOutAmount, netRedeemAmount, feesToTreasury);
}
function calcUsbToMarginTokensForStableVault(IVault self, IProtocolSettings settings, uint256 usbAmount) public view returns (Constants.StableVaultState memory, uint256) {
Constants.StableVaultState memory S = getStableVaultState(self);
require(S.aar < S.AARS, "AAR Above AARS");
uint256 aar101 = (101 * (10 ** (S.AARDecimals - 2)));
uint256 marginTokenOutAmount;
if (S.aar >= aar101) { // aar >= 101%
// ΔUSDCx = ΔUSB * M_USDCx * (1 + r) / (M_USDC * P_USDC - M_USB-USDC)
Constants.Terms memory T;
T.T1 = usbAmount.mul(S.M_USDCx).mul((10 ** settings.decimals()).add(_r(S.AARBelowSafeLineTime, S.RateR)));
marginTokenOutAmount = T.T1.div(
S.M_USDC.mul(S.P_USDC).div(10 ** S.P_USDC_DECIMALS).sub(S.M_USB_USDC)
).div(10 ** settings.decimals());
}
else { // aar < 101%
// ΔUSDCx = ΔUSB * M_USDCx * 100 / M_USB-USDC
marginTokenOutAmount = usbAmount.mul(S.M_USDCx).mul(100).div(S.M_USB_USDC);
}
return (S, marginTokenOutAmount);
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./Constants.sol";
library TokensTransfer {
using SafeERC20 for IERC20;
/// @dev Transfers a given amount of token.
function transferTokens(
address token,
address from,
address to,
uint256 amount
) internal {
if (token == Constants.NATIVE_TOKEN) {
safeTransferNativeToken(from, to, amount);
}
else {
safeTransferERC20(token, from, to, amount);
}
}
/// @dev Transfers `amount` of native token to `to`.
function safeTransferNativeToken(address from, address to, uint256 amount) internal {
require(from != to, "Same address");
require(from != address(0) && to != address(0), "Zero address");
require(from == address(this) || to == address(this), "One of the addresses must be this contract");
require(amount > 0, "Amount must be greater than 0");
if (to == address(this)) {
require(msg.value == amount, "Incorrect msg.value");
return;
}
// solhint-disable avoid-low-level-calls
// slither-disable-next-line low-level-calls
(bool success, ) = to.call{ value: amount }("");
require(success, "Native token transfer failed");
}
/// @dev Transfer `amount` of ERC20 token from `from` to `to`.
function safeTransferERC20(
address token,
address from,
address to,
uint256 amount
) internal {
require(from != to, "Same address");
require(from != address(0) && to != address(0), "Zero address");
// require(from == address(this) || to == address(this), "One of the addresses must be this contract");
require(amount > 0, "Amount must be greater than 0");
if (from == address(this)) {
IERC20(token).safeTransfer(to, amount);
}
else {
IERC20(token).safeTransferFrom(from, to, amount);
}
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/utils/Context.sol";
import "../interfaces/IWandProtocol.sol";
abstract contract ProtocolOwner is Context {
IWandProtocol public immutable wandProtocol;
constructor(address _wandProtocol_) {
require(_wandProtocol_ != address(0), "Zero address detected");
wandProtocol = IWandProtocol(_wandProtocol_);
}
modifier onlyProtocol() {
require(_msgSender() == address(wandProtocol), "Ownable: caller is not the protocol");
_;
}
modifier onlyOwner() {
require(_msgSender() == IWandProtocol(wandProtocol).protocolOwner(), "Ownable: caller is not the owner");
_;
}
function owner() public view returns(address) {
return IWandProtocol(wandProtocol).protocolOwner();
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "../libs/Constants.sol";
import "../libs/TokensTransfer.sol";
import "../settings/ProtocolOwner.sol";
import "../interfaces/IBlast.sol";
import "../interfaces/IBlastPoints.sol";
import "../interfaces/IProtocolSettings.sol";
import "../interfaces/IWandProtocol.sol";
contract TokenPot is Context, ReentrancyGuard {
// IBlastPoints public immutable blastPoints;
IProtocolSettings public immutable settings;
address public immutable owner;
IWandProtocol public immutable wandProtocol;
constructor(address _wandProtocol, address _settings) {
require(_wandProtocol != address(0) && _settings != address(0), "Zero address detected");
owner = msg.sender;
settings = IProtocolSettings(_settings);
wandProtocol = IWandProtocol(_wandProtocol);
}
receive() external payable {}
function balance(address token) public view returns (uint256) {
if (token == Constants.NATIVE_TOKEN) {
return address(this).balance;
}
else {
return IERC20(token).balanceOf(address(this));
}
}
function configureBlastYieldsAndGas() external nonReentrant onlyOwner {
address blastAddress = wandProtocol.blastAddress();
if (blastAddress != address(0)) {
IBlast blast = IBlast(wandProtocol.blastAddress());
blast.configureAutomaticYield();
blast.configureClaimableGas();
}
}
function configureBlastPoints() external nonReentrant onlyOwner {
address blastPointsAddress = wandProtocol.blastPointsAddress();
address blastPointsOperatorAddress = wandProtocol.blastPointsOperator();
if (blastPointsAddress != address(0) && blastPointsOperatorAddress != address(0)) {
IBlastPoints blastPoints = IBlastPoints(blastPointsAddress);
blastPoints.configurePointsOperator(blastPointsOperatorAddress);
}
}
// Only owner could withdraw from this contract
function withdraw(address recipient, address token, uint256 amount) external nonReentrant onlyOwner {
require(recipient != address(0) && token != address(0), "Zero address detected");
require(amount > 0 && amount <= balance(token), "Invalid amount");
TokensTransfer.transferTokens(token, address(this), recipient, amount);
emit Withdrawn(_msgSender(), recipient, token, amount);
address blastAddress = wandProtocol.blastAddress();
if (blastAddress != address(0)) {
IBlast blast = IBlast(blastAddress);
(uint256 etherSeconds, uint256 etherBalance, ,) = blast.readGasParams(address(this));
if (etherSeconds > 0 && etherBalance > 0) {
blast.claimAllGas(address(this), settings.treasury());
}
}
}
modifier onlyOwner() {
require(_msgSender() == owner, "TokenPot: caller is not the owner");
_;
}
/* =============== EVENTS ============= */
event Withdrawn(address indexed withdrawer, address indexed recipient, address indexed token, uint256 amount);
}{
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 100,
"details": {
"yulDetails": {
"optimizerSteps": "u"
}
}
},
"viaIR": true,
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {
"contracts/libs/StableVaultCalculatorV2.sol": {
"StableVaultCalculatorV2": "0xcff94c34175a57086d48e54cf3367f5fee9a2f42"
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_wandProtocol","type":"address"},{"internalType":"address","name":"_settings","type":"address"},{"internalType":"address","name":"_assetToken_","type":"address"},{"internalType":"address","name":"_marginToken_","type":"address"},{"internalType":"address","name":"_assetTokenPriceFeed_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"marginTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"netAssetAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feesToTreasury","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPriceDecimals","type":"uint256"}],"name":"AssetRedeemedWithMarginTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"usbAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"marginTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"netAssetAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feesToTreasury","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPriceDecimals","type":"uint256"}],"name":"AssetRedeemedWithPairs","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"usbTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"netAssetAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feesToTreasury","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPriceDecimals","type":"uint256"}],"name":"AssetRedeemedWithUsb","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"marginTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPriceDecimals","type":"uint256"}],"name":"MarginTokenBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"assetTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"marginTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPriceDecimals","type":"uint256"}],"name":"MarginTokenMinted","type":"event"},{"anonymous":false,"inputs":[],"name":"MintPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"MintUnpaused","type":"event"},{"anonymous":false,"inputs":[],"name":"RedeemPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"RedeemUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"usbTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usbSharesAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPriceDecimals","type":"uint256"}],"name":"UsbBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"assetTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usbTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usbSharesAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPriceDecimals","type":"uint256"}],"name":"UsbMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"usbAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"xTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetTokenPriceDecimals","type":"uint256"}],"name":"UsbToMarginTokens","type":"event"},{"anonymous":false,"inputs":[],"name":"UsbToMarginTokensPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"UsbToMarginTokensUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"usbYieldsAmount","type":"uint256"}],"name":"YieldsSettlement","type":"event"},{"inputs":[],"name":"AARBelowCircuitBreakerLineTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"AARBelowSafeLineTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"AARDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"assetBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetTokenDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetTokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"configureBlastPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"configureBlastYieldsAndGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"marginToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetAmount","type":"uint256"}],"name":"mintMarginTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetAmount","type":"uint256"}],"name":"mintPairs","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetAmount","type":"uint256"}],"name":"mintUsb","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"param","type":"bytes32"}],"name":"paramValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseUsbToMarginTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeed","outputs":[{"internalType":"contract IPriceFeed","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marginTokenAmount","type":"uint256"}],"name":"redeemByMarginTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marginTokenAmount","type":"uint256"}],"name":"redeemByPairsWithExpectedMarginTokenAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"usbAmount","type":"uint256"}],"name":"redeemByPairsWithExpectedUsbAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"usbAmount","type":"uint256"}],"name":"redeemByUsb","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settings","outputs":[{"internalType":"contract IProtocolSettings","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenPot","outputs":[{"internalType":"contract TokenPot","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpauseMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseUsbToMarginTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_assetTokenPriceFeed_","type":"address"}],"name":"updatePriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"usbAmount","type":"uint256"}],"name":"usbToMarginTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usbToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usbTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultMode","outputs":[{"internalType":"enum Constants.VaultMode","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"vaultType","outputs":[{"internalType":"enum Constants.VaultType","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"wandProtocol","outputs":[{"internalType":"contract IWandProtocol","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6101406040523462000203576200002362000019620002e6565b93929092620004f2565b604051614a3c620008a58239608051818181610457015281816108cf015281816118eb015281816133da015281816137e90152818161385401528181613b4901528181613d0601526140c7015260a05181818161078601528181611478015281816119e90152818161297701528181612c0001528181612f3401528181613583015281816144d50152614668015260c051818181610837015281816109ba015281816112c7015281816117a001528181611e2101528181612110015281816123fc015281816127bb01528181612aad01528181612d2d0152818161307f015281816132eb0152818161397b01528181613bf80152614232015260e0518181816103140152818161095f015281816112f6015281816113ae0152818161168c015281816117cf01528181611dcc015281816120a4015281816121f401528181612390015281816124f5015281816138fb015261425d0152610100518181816103af01528181611e530152818161254d015281816128d701528181612dde015281816131d5015281816134e4015281816143f401526147340152610120518181816105a80152818161224c0152818161263301528181612b6601528181612ec6015281816130ec01528181613690015281816139e101526143180152614a3c90f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b038211176200024057604052565b62000208565b906200025d6200025560405190565b92836200021e565b565b6001600160a01b031690565b90565b6001600160a01b038116036200020357565b905051906200025d826200026e565b919060a0838203126200020357620002a8818462000280565b92620002b8826020830162000280565b926200026b620002cc846040850162000280565b93620002dc816060860162000280565b9360800162000280565b6200030962006b7380380380620002fd8162000246565b9283398101906200028f565b9091929394565b6200025f6200026b6200026b9290565b6200026b9062000310565b156200033357565b60405162461bcd60e51b815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606490fd5b6200026b906200025f906001600160a01b031682565b6200026b9062000378565b6200026b906200038e565b9060208282031262000203576200026b9162000280565b6040513d6000823e3d90fd5b15620003cf57565b60405162461bcd60e51b815260206004820152602e60248201527f5661756c742073686f756c64206f6e6c7920626520637265617465642062792060448201526d383937ba37b1b7b61037bbb732b960911b6064820152608490fd5b6001600160a01b0391821681529116602082015260400190565b9060ff905b9181191691161790565b90620004676200026b6200046f92151590565b825462000445565b9055565b9061ff009060081b6200044a565b90620004946200026b6200046f92151590565b825462000473565b9062ff00009060101b6200044a565b90620004be6200026b6200046f92151590565b82546200049c565b906001600160a01b03906200044a565b90620004ea6200026b6200046f9262000399565b8254620004c6565b9092939193620005028262000807565b6000916200054e620005148462000320565b6001600160a01b0381166001600160a01b03841614159081620007e8575b81620007c9575b81620007aa575b816200078c575b506200032b565b326200056c620005666080516001600160a01b031690565b62000399565b9063c1d6ba699160206200057f60405190565b80926200058c8660e01b90565b825260049082905afa908115620006fb57620005ca91620005bd9160009162000769575b506001600160a01b031690565b916001600160a01b031690565b1490811562000701575b50620005e090620003c7565b604051906118928201906001600160401b0382118383101762000240578662000614918493611892620052e186396200042b565b039083f0948515620006fb57620006619560c05260e05261012052602062000648620005666080516001600160a01b031690565b632e207121906200065860405190565b96879260e01b90565b825260049082905afa908115620006fb5762000699620006be9462000566936200025d97600091620006c6575b506101005262000399565b60a052620006a981600162000454565b620006b681600162000481565b6001620004ab565b6006620004d6565b620006ec915060203d8111620006f3575b620006e381836200021e565b810190620003a4565b386200068e565b503d620006d7565b620003bb565b6200072e91506020339162000722620005666080516001600160a01b031690565b60405194859260e01b90565b825260049082905afa8015620006fb57620005bd6200076191620005e0946000916200076957506001600160a01b031690565b1490620005d4565b62000785915060203d8111620006f357620006e381836200021e565b38620005b0565b6001600160a01b031690506001600160a01b03861614153862000547565b90506001600160a01b0381166001600160a01b03851614159062000540565b90506001600160a01b0381166001600160a01b03891614159062000539565b90506001600160a01b0381166001600160a01b03881614159062000532565b6200083c906200081662000841565b620005666200082a6200025f600062000320565b6001600160a01b03831614156200032b565b608052565b6200025d6200088e565b6200026b6200026b6200026b9290565b6200026b60016200084b565b90600019906200044a565b90620008866200026b6200046f926200084b565b825462000867565b6200025d6200089c6200085b565b60006200087256fe60806040526004361015610023575b361561001957600080fd5b61002161095a565b005b60003560e01c8062b190d91461025d57806302b0dbd7146102585780631083f761146102535780631a8bd2da1461024e5780632db574a1146102495780632e2071211461024457806332ec84d21461023f5780633a006cda1461023a5780633fef6dc1146102355780634ac032be146102305780634e29a3331461022b57806350eb741c1461022657806351dddf4f146102215780635c975abb1461021c5780635cd480b4146102175780636685ed87146102125780636a8f6ebb1461020d578063741bef1a146102085780637b4a7cea146102035780638d93fb21146101c75780638da5cb5b146101fe57806395877f78146101f95780639e3141d3146101f4578063a098ba73146101ef578063af3345d1146101ea578063b85fc766146101e5578063c66f2455146101e0578063cd85cdb5146101db578063d5ba6809146101d6578063ddef1953146101d1578063e06174e4146101cc578063e0851a88146101c7578063e13a4fe9146101c2578063ea00162c146101bd578063eaee8425146101b85763f7a17d930361000e57610822565b610807565b6107ef565b6107c1565b610639565b610771565b610759565b610741565b610729565b61070e565b6106f3565b6106db565b6106c3565b6106ab565b610693565b61064e565b610626565b61060b565b6105cc565b610593565b61057b565b610551565b61051e565b61050b565b6104f3565b6104d4565b610442565b6103eb565b6103d3565b61039a565b610387565b610340565b6102ff565b6102ab565b610278565b600091031261026d57565b600080fd5b9052565b565b3461026d57610288366004610262565b6102a76102936113ac565b6040519182918260ff909116815260200190565b0390f35b3461026d576102bb366004610262565b6102a76102c661151a565b6040515b9182918290815260200190565b6001600160a01b031690565b90565b610272906102d7565b60208101929161027691906102e6565b3461026d5761030f366004610262565b6102a77f00000000000000000000000000000000000000000000000000000000000000005b604051918291826102ef565b3461026d57610350366004610262565b610358613e66565b604051005b805b0361026d57565b905035906102768261035d565b9060208282031261026d576102e391610366565b610358610395366004610373565b611f9f565b3461026d576103aa366004610262565b6102a77f0000000000000000000000000000000000000000000000000000000000000000610334565b3461026d576103e3366004610262565b610358613f0a565b3461026d576103586103fe366004610373565b612ce5565b6102e3906102d7906001600160a01b031682565b6102e390610403565b6102e390610417565b61027290610420565b6020810192916102769190610429565b3461026d57610452366004610262565b6102a77f00000000000000000000000000000000000000000000000000000000000000005b60405191829182610432565b634e487b7160e01b600052602160045260246000fd5b600211156104a357565b610483565b9061027682610499565b6102e3906104a8565b610272906104b2565b60208101929161027691906104bb565b3461026d576104e4366004610262565b604051806102a76001826104c4565b3461026d57610503366004610262565b610358613b25565b610358610519366004610373565b61272d565b3461026d5761052e366004610262565b6103586140a7565b90151581529015156020820152901515604082015260600190565b3461026d57610561366004610262565b6102a761056c61125c565b60405191939193849384610536565b3461026d5761035861058e366004610373565b6137bc565b3461026d576105a3366004610262565b6102a77f0000000000000000000000000000000000000000000000000000000000000000610334565b3461026d576105dc366004610262565b6102a76102c6611512565b6102e3916008021c6102d7565b906102e391546105e7565b6102e3600060066105f4565b3461026d5761061b366004610262565b6102a76104776105ff565b610358610634366004610373565b612350565b3461026d57610649366004610262565b6114d3565b3461026d5761065e366004610262565b6102a76103346108c5565b61035f816102d7565b9050359061027682610669565b9060208282031261026d576102e391610672565b3461026d576103586106a636600461067f565b6141b3565b3461026d576103586106be366004610373565b61324e565b3461026d576103586106d6366004610373565b612a65565b3461026d576106eb366004610262565b610358613f86565b3461026d57610703366004610262565b6102a76102c6611292565b3461026d5761071e366004610262565b6102a76102c66112bd565b3461026d57610739366004610262565b610358613dea565b3461026d57610358610754366004610373565b613037565b3461026d57610769366004610262565b610358613c92565b3461026d57610781366004610262565b6102a77f0000000000000000000000000000000000000000000000000000000000000000610477565b9081526040810192916102769160200152565b0152565b3461026d576107d1366004610262565b6107d9611465565b906102a76107e660405190565b928392836107aa565b3461026d576107ff366004610262565b61035861402b565b3461026d576102a76102c661081d366004610373565b611471565b3461026d57610832366004610262565b6102a77f0000000000000000000000000000000000000000000000000000000000000000610477565b634e487b7160e01b600052604160045260246000fd5b90601f01601f1916810190811067ffffffffffffffff82111761089357604052565b61085b565b9050519061027682610669565b9060208282031261026d576102e391610898565b6040513d6000823e3d90fd5b61090b60206108f37f0000000000000000000000000000000000000000000000000000000000000000610420565b63c1d6ba699061090260405190565b93849260e01b90565b825260049082905afa90811561094e57600091610926575090565b6102e3915060203d8111610947575b61093f8183610871565b8101906108a5565b503d610935565b6108b9565b1561026d57565b6102767f00000000000000000000000000000000000000000000000000000000000000006109ac61099d6000805160206149c78339815191526102d7565b6102d7565b6109a6836102d7565b14610953565b6109b530610420565b6109de7f0000000000000000000000000000000000000000000000000000000000000000610420565b9034925b9291906109fc6000805160206149c78339815191526102d7565b610a05856102d7565b03610a14576102769350610c5e565b61027693610d75565b0190565b15610a2857565b60405162461bcd60e51b815260206004820152600c60248201526b53616d65206164647265737360a01b6044820152606490fd5b0390fd5b6102d76102e36102e39290565b6102e390610a60565b15610a7d57565b60405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606490fd5b15610ab857565b60405162461bcd60e51b815260206004820152602a60248201527f4f6e65206f662074686520616464726573736573206d757374206265207468696044820152691cc818dbdb9d1c9858dd60b21b6064820152608490fd5b6102e36102e36102e39290565b15610b2457565b60405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606490fd5b15610b7057565b60405162461bcd60e51b8152602060048201526013602482015272496e636f7272656374206d73672e76616c756560681b6044820152606490fd5b90610276610bb860405190565b9283610871565b67ffffffffffffffff811161089357602090601f01601f19160190565b90610bee610be983610bbf565b610bab565b918252565b3d15610c0d57610c023d610bdc565b903d6000602084013e565b606090565b15610c1957565b60405162461bcd60e51b815260206004820152601c60248201527f4e617469766520746f6b656e207472616e73666572206661696c6564000000006044820152606490fd5b90610c7b610c6b826102d7565b610c74846102d7565b1415610a21565b610cef600092610cae610c8d85610a6d565b610c96816102d7565b610c9f846102d7565b14159081610d5a575b50610a76565b610cb730610420565b90610cca610cc4836102d7565b916102d7565b148015610d3c575b610cdb90610ab1565b610998610ce785610b10565b865b11610b1d565b610cf8826102d7565b14610d2157819061027693610d0c60405190565b90818003925af1610d1b610bf3565b50610c12565b505061027690610d36610d32349290565b9190565b14610b69565b50610cdb610d49826102d7565b610d52856102d7565b149050610cd2565b610d6491506102d7565b610d6d856102d7565b141538610ca8565b929190610d8d610d84836102d7565b610c74836102d7565b610dcc610dc66000610dc1610da182610a6d565b610daa816102d7565b610db3876102d7565b14159081610e095750610a76565b610b10565b84610ce9565b610dd861099830610420565b610de1826102d7565b03610df85750610df361027693610420565b610e5d565b610e0461027694610420565b610ecf565b610e1391506102d7565b610d6d876102d7565b610e35610e2f6102e39263ffffffff1690565b60e01b90565b6001600160e01b03191690565b9160206102769294936107bd604082019660008301906102e6565b610ea0600492610e9161027695610e7763a9059cbb610e1c565b92610e8160405190565b9687946020860190815201610e42565b60208201810382520383610871565b610fc8565b6040906107bd6102769496959396610ec5606084019860008501906102e6565b60208301906102e6565b90610ea090610e9161027695600495610eeb6323b872dd610e1c565b93610ef560405190565b9788956020870190815201610ea5565b610f0f6020610bdc565b7f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602082015290565b6102e3610f05565b80151561035f565b9050519061027682610f40565b9060208282031261026d576102e391610f48565b15610f7057565b60405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b61027691610fd8610fe792610420565b90610fe1610f38565b91611025565b8051610ff6610d326000610b10565b14908115611005575b50610f69565b61101f91506020611014825190565b818301019101610f55565b38610fff565b6102e392916110346000610b10565b91611095565b1561104157565b60405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608490fd5b9060006102e3949381926110a7606090565b506110be6110b430610420565b839031101561103a565b60208101905191855af16110d0610bf3565b91611122565b156110dd57565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b919290156111545750815161113a610d326000610b10565b14611143575090565b61114f6102e39161115a565b6110d6565b826111d4565b3b611168610d326000610b10565b1190565b60005b83811061117f5750506000910152565b818101518382015260200161116f565b6111b06111b9602093610a1d936111a4815190565b80835293849260200190565b9586910161116c565b601f01601f191690565b60208082526102e39291019061118f565b906111dd825190565b6111ea610d326000610b10565b11156111f95750805190602001fd5b610a5c9061120660405190565b62461bcd60e51b8152918291600483016111c3565b6102e3905b60ff1690565b6102e3905461121b565b6102e39060081c611220565b6102e39054611230565b6102e39060101c611220565b6102e39054611246565b6112666001611226565b611270600161123c565b9161127b6001611252565b91929190565b6102e39081565b6102e39054611281565b6102e36002611288565b905051906102768261035d565b9060208282031261026d576102e39161129c565b61133760206112eb7f0000000000000000000000000000000000000000000000000000000000000000610420565b63e3d670d79061132c7f00000000000000000000000000000000000000000000000000000000000000009261131f60405190565b9586948593849360e01b90565b8352600483016102ef565b03915afa90811561094e5760009161134d575090565b6102e3915060203d811161136e575b6113668183610871565b8101906112a9565b503d61135c565b6112206102e36102e39290565b60ff811661035f565b9050519061027682611382565b9060208282031261026d576102e39161138b565b7f00000000000000000000000000000000000000000000000000000000000000006113e46000805160206149c78339815191526102d7565b6113ed826102d7565b1461145a57602061140861140361141793610420565b610420565b63313ce5679061090260405190565b825260049082905afa90811561094e57600091611432575090565b6102e3915060203d8111611453575b61144b8183610871565b810190611398565b503d611441565b506102e36012611375565b61146d614905565b9091565b602061149c7f0000000000000000000000000000000000000000000000000000000000000000610420565b635bec50be906114c86114ae30610420565b926113376114bb60405190565b9687958694859460e01b90565b845260048401610e42565b60405162461bcd60e51b815260206004820152600d60248201526c139bdd081cdd5c1c1bdc9d1959609a1b6044820152606490fd5b6102e3600a610b10565b6102e3611508565b6102e36005611288565b61153590611530611ffe565b611577565b610276612030565b1561154457565b60405162461bcd60e51b815260206004820152600b60248201526a135a5b9d081c185d5cd95960aa1b6044820152606490fd5b6102769061159461158f61158b6001611226565b1590565b61153d565b6115e5565b156115a057565b60405162461bcd60e51b815260206004820152601c60248201527f56616c7565206d7573742062652067726561746572207468616e2030000000006044820152606490fd5b610276906115fd6115f66000610b10565b8211611599565b611686565b1561160957565b60405162461bcd60e51b815260206004820152601560248201527406d73672e76616c75652073686f756c64206265203605c1b6044820152606490fd5b1561164d57565b60405162461bcd60e51b8152602060048201526011602482015270496e76616c6964206d73672076616c756560781b6044820152606490fd5b610276907f00000000000000000000000000000000000000000000000000000000000000006116c5610cc46000805160206149c78339815191526102d7565b036116db576116d681345b14611646565b611792565b6116d6346116ec610d326000610b10565b14611602565b90600019905b9181191691161790565b906117126102e361171992610b10565b82546116f2565b9055565b6002111561026d57565b905051906102768261171d565b60808183031261026d57611748828261129c565b926102e3611759846020850161129c565b93611767816040860161129c565b93606001611727565b91602061027692949361178b604082019660008301906102e6565b01906102e6565b6118059060019060206117c47f0000000000000000000000000000000000000000000000000000000000000000610420565b63e3d670d79061132c7f0000000000000000000000000000000000000000000000000000000000000000926117f860405190565b9788948593849360e01b90565b03915afa92831561094e57600093611b9c575b5061182290611d45565b611b5e575b503061183281610420565b9073cff94c34175a57086d48e54cf3367f5fee9a2f42630b7c48059261185760405190565b916118628560e01b90565b8352602083806118758560048301610432565b0381845af4801561094e576118c1956118a66118b692602096600091611b41575b506118a16004611288565b61487a565b6040519687948593849360e01b90565b835260048301610432565b03915af491821561094e57611927926118e491600091611b23575b506004611702565b602061190f7f0000000000000000000000000000000000000000000000000000000000000000610420565b6349d3d5e19061191e60405190565b94859260e01b90565b825260049082905afa91821561094e57600092611b03575b5060009161194f61099884610a6d565b611958826102d7565b0361196257505050565b61140361196e91610420565b9061197d63dde798a491610420565b9061199161198a60405190565b9160e01b90565b8152608081806119a485600483016102ef565b0381865afa801561094e576000918291611ad0575b506119c6610d3286610b10565b119081611abb575b506119d857505050565b611a259163954fa5ee936020611a0d7f0000000000000000000000000000000000000000000000000000000000000000610420565b6361d027b390611a1c60405190565b96879260e01b90565b825260049082905afa93841561094e57600094611a95575b50611a5f9060209495611a6a611a5260405190565b9788968795869460e01b90565b845260048401611770565b03925af1801561094e57611a7b5750565b611a929060203d811161136e576113668183610871565b50565b6020945090611ab3611a5f92863d81116109475761093f8183610871565b945090611a3d565b9050611ac9610d3285610b10565b11386119ce565b9050611af3915060803d8111611afc575b611aeb8183610871565b810190611734565b509190916119b9565b503d611ae1565b611b1c91925060203d81116109475761093f8183610871565b903861193f565b611b3b915060203d811161136e576113668183610871565b386118dc565b611b589150873d811161136e576113668183610871565b38611896565b611b686003611288565b611b75610d326000610b10565b03611b8d575b50611b87426003611702565b38611827565b611b9690614615565b38611b7b565b611822919350611bb99060203d811161136e576113668183610871565b9290611818565b9190916101408184031261026d57611c89611bdc610140610bab565b936000611be9828561129c565b908601526020611bfb8282860161129c565b908601526040611c0d8282860161129c565b908601526060611c1f8282860161129c565b908601526080611c318282860161129c565b9086015260a0611c438282860161129c565b9086015260c0611c558282860161129c565b9086015260e0611c678282860161129c565b90860152610100611c7a8282860161129c565b9086015261012080930161129c565b90830152565b91906101608382031261026d576102e390611caa8185611bc0565b936101400161129c565b9160206102769294936107bd60408201966000830190610429565b15611cd657565b60405162461bcd60e51b815260206004820152600e60248201526d4141522042656c6f77204141525360901b6044820152606490fd5b9095949261027694611d3e6107bd92611d37608096611d3060a088019c6000890152565b6020870152565b6040850152565b6060830152565b309080610160611d5484610420565b73cff94c34175a57086d48e54cf3367f5fee9a2f42611d7d632bb4c932611d886114bb60405190565b845260048401611cb4565b03915af491821561094e57611e9393600080939094611f69575b50611dc9611db160a086015190565b611dc2610d326102e360c089015190565b1015611ccf565b817f0000000000000000000000000000000000000000000000000000000000000000611e026000805160206149c78339815191526102d7565b611e0b826102d7565b03611f5957611e1c611e4b93610420565b611e457f0000000000000000000000000000000000000000000000000000000000000000610420565b916109e2565b611e776114037f0000000000000000000000000000000000000000000000000000000000000000610420565b9260206340c10f193395611e8a60405190565b97889260e01b90565b825281600081611ea7898b60048401610e42565b03925af194851561094e57600095611f35575b50611f3090611edc611ed585611ed06002611288565b612063565b6002611702565b611ef26040611eec602084015190565b92015190565b90611f1d7f63c3f185975ecdfdf59dfa778ff2ddbfe5a3f930ccc104a7b4f6d9f882fde93c96610420565b96611f2760405190565b95869586611d0c565b0390a2565b611f30919550611f529060203d811161136e576113668183610871565b9490611eba565b611f64925033611e1c565b611e4b565b909350611f8f9192506101603d8111611f98575b611f878183610871565b810190611c8f565b91909238611da2565b503d611f7d565b61027690611524565b6102e36002610b10565b15611fb957565b60405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606490fd5b61027661200b6000611288565b61201f612016611fa8565b91821415611fb2565b6000611702565b6102e36001610b10565b61027661201f612026565b634e487b7160e01b600052601160045260246000fd5b9190820180921161205e57565b61203b565b6102e39190612051565b61153590612079611ffe565b6102769061208d61158f61158b6001611226565b6102769061209e6115f66000610b10565b610276907f00000000000000000000000000000000000000000000000000000000000000006120dd610cc46000805160206149c78339815191526102d7565b036120f1576120ec81346116d0565b612102565b612102346116ec610d326000610b10565b6121349060019060206117c47f0000000000000000000000000000000000000000000000000000000000000000610420565b03915afa92831561094e57600093612151575b50611822906121a2565b61182291935061216e9060203d811161136e576113668183610871565b9290612147565b6107bd6102769461219b606094989795612194608086019a6000870152565b6020850152565b6040830152565b3090806101606121b184610420565b73cff94c34175a57086d48e54cf3367f5fee9a2f42611d7d63cd6c29b56121da6114bb60405190565b03915af492831561094e5760008092909461232c575b50827f000000000000000000000000000000000000000000000000000000000000000061222a6000805160206149c78339815191526102d7565b612233826102d7565b0361231c57611e1c61224493610420565b6122706114037f0000000000000000000000000000000000000000000000000000000000000000610420565b916340c10f193393803b1561026d5761228f9160009161090260405190565b82528183816122a2898b60048401610e42565b03925af1801561094e576122f6575b50611f306122cb60406122c5602088015190565b96015190565b6122e36000805160206149e783398151915295610420565b956122ed60405190565b94859485612175565b61230f9060005b6123078183610871565b810190610262565b386122b1565b503d6122fd565b612327925033611e1c565b612244565b90935061234891506101603d8111611f9857611f878183610871565b9092386121f0565b6102769061206d565b61153590612365611ffe565b6102769061237961158f61158b6001611226565b6102769061238a6115f66000610b10565b610276907f00000000000000000000000000000000000000000000000000000000000000006123c9610cc46000805160206149c78339815191526102d7565b036123dd576123d881346116d0565b6123ee565b6123ee346116ec610d326000610b10565b6124209060019060206117c47f0000000000000000000000000000000000000000000000000000000000000000610420565b03915afa92831561094e5760009361243d575b5061182290612494565b61182291935061245a9060203d811161136e576113668183610871565b9290612433565b90916101808284031261026d576102e361247b8484611bc0565b9361248a81610140860161129c565b936101600161129c565b80306101806124a282610420565b73cff94c34175a57086d48e54cf3367f5fee9a2f42611d7d63b7aa264c6124d86124cb60405190565b9889958694859460e01b90565b03915af491821561094e576000808093919590946126f5575b50817f000000000000000000000000000000000000000000000000000000000000000061252b6000805160206149c78339815191526102d7565b612534826102d7565b036126e557611e1c61254593610420565b6125716114037f0000000000000000000000000000000000000000000000000000000000000000610420565b936340c10f193390602061258460405190565b80986125908460e01b90565b8252816000816125a48c8960048401610e42565b03925af196871561094e576000976126c5575b506125c9611ed587611ed06002611288565b602083019260406125d8855190565b9101966125e3885190565b987f63c3f185975ecdfdf59dfa778ff2ddbfe5a3f930ccc104a7b4f6d9f882fde93c9161262861261287610420565b9b8c9561261e60405190565b9485948c86611d0c565b0390a26126576114037f0000000000000000000000000000000000000000000000000000000000000000610420565b91823b1561026d5785926114c860008094612674611a5260405190565b03925af1801561094e57611f309261269892612693926126b157505190565b945190565b6000805160206149e7833981519152946122ed60405190565b6126c19060006123078183610871565b5190565b6126de91975060203d811161136e576113668183610871565b95386125b7565b6126f0925033611e1c565b612545565b919450925061271c91506101803d8111612726575b6127148183610871565b810190612461565b91939092386124f1565b503d61270a565b61027690612359565b61153590612742611ffe565b612783565b1561274e57565b60405162461bcd60e51b815260206004820152600d60248201526c14995919595b481c185d5cd959609a1b6044820152606490fd5b6102769061279c61279761158b600161123c565b612747565b610276906127ad6115f66000610b10565b6127df9060019060206117c47f0000000000000000000000000000000000000000000000000000000000000000610420565b03915afa92831561094e576000936127fc575b50611822906128cf565b6118229193506128199060203d811161136e576113668183610871565b92906127f2565b1561282757565b60405162461bcd60e51b81526020600482015260166024820152754e6f7420656e6f756768205553422062616c616e636560501b6044820152606490fd5b6101a08183031261026d5761287a8282611bc0565b926102e361288c84610140850161129c565b9361289b81610160860161129c565b936101800161129c565b6040906107bd61027694969593966128c560608401986000850190610429565b6020830190610429565b6128fb6114037f0000000000000000000000000000000000000000000000000000000000000000610420565b61291160206370a08231335b9361090260405190565b8252818061292287600483016102ef565b03915afa90811561094e57612949916129409160009161134d575090565b835b1115612820565b61295230610420565b916101a073cff94c34175a57086d48e54cf3367f5fee9a2f429363b6f25c87946129b17f0000000000000000000000000000000000000000000000000000000000000000966129bc866129a460405190565b998a968795869560e01b90565b8552600485016128a5565b03915af490811561094e576000938492839190612a2a575b50611f30906129ef6129e66000610b10565b84838988614220565b6129ff6040611eec602084015190565b90611f1d7f83e33350dd7d2770e5ef41f54623d7ab48e7ed10992b6fcacd403ec7433b4aa096610420565b9050612a54919450611f3092506101a03d8111612a5e575b612a4c8183610871565b810190612865565b95929150926129d4565b503d612a42565b61027690612736565b61153590612a7a611ffe565b61027690612a8e61279761158b600161123c565b61027690612a9f6115f66000610b10565b612ad19060019060206117c47f0000000000000000000000000000000000000000000000000000000000000000610420565b03915afa92831561094e57600093612aee575b5061182290612b5e565b611822919350612b0b9060203d811161136e576113668183610871565b9290612ae4565b15612b1957565b60405162461bcd60e51b815260206004820152601f60248201527f4e6f7420656e6f756768206d617267696e20746f6b656e2062616c616e6365006044820152606490fd5b612b8a6114037f0000000000000000000000000000000000000000000000000000000000000000610420565b612b9a60206370a0823133612907565b82528180612bab87600483016102ef565b03915afa90811561094e57612bd291612bc99160009161134d575090565b835b1115612b12565b612bdb30610420565b916101a073cff94c34175a57086d48e54cf3367f5fee9a2f429363be008d49946129b17f000000000000000000000000000000000000000000000000000000000000000096612c2d866129a460405190565b03915af490811561094e576000938492839190612cba575b5080612c69612c5860a0611f3094015190565b611dc2610d326102e360c086015190565b612c7f83612c776000610b10565b838988614220565b612c8f6040611eec602084015190565b90611f1d7fe695803557243d1db69c47b18a9d48a4cda9a440d066d05610a559766e52690c96610420565b9050612cdb919450611f3092506101a03d8111612a5e57612a4c8183610871565b9592915092612c45565b61027690612a6e565b61153590612cfa611ffe565b61027690612d0e61279761158b600161123c565b61027690612d1f6115f66000610b10565b612d519060019060206117c47f0000000000000000000000000000000000000000000000000000000000000000610420565b03915afa92831561094e57600093612d6e575b5061182290612dd6565b611822919350612d8b9060203d811161136e576113668183610871565b9290612d64565b9194612dcf6107bd92989795612dc860a096612dc16102769a612dba60c08a019e60008b0152565b6020890152565b6040870152565b6060850152565b6080830152565b612e026114037f0000000000000000000000000000000000000000000000000000000000000000610420565b6370a0823133916020612e1460405190565b8092612e208560e01b90565b82528180612e3188600483016102ef565b03915afa90811561094e57612e5591612e4f9160009161134d575090565b84612942565b612e5e30610420565b9273cff94c34175a57086d48e54cf3367f5fee9a2f429363c9e5cf2592612e8e612e8760405190565b9460e01b90565b845260208480612ea2868660048401611cb4565b0381895af493841561094e5760009461300f575b50906020612ef292612eea6114037f0000000000000000000000000000000000000000000000000000000000000000610420565b60405161191e565b82528180612f038a600483016102ef565b03915afa801561094e57612f23612f29916101a09460009161134d575090565b85612bcb565b6394764610956129b17f000000000000000000000000000000000000000000000000000000000000000097612f6e87612f6160405190565b9a8b968795869560e01b90565b03915af493841561094e5760009485918291612fe6575b509081612f988585611f3095858b614220565b612fa86040611eec602084015190565b91612fd37f349a548d6a4fdc89e9f4cee7a49220b59a0cda0e7062c7ba8e406c4b5137b0c497610420565b97612fdd60405190565b96879687612d92565b9050611f30955061300691506101a03d8111612a5e57612a4c8183610871565b92915095612f85565b612ef29291945061302e602091823d811161136e576113668183610871565b94919250612eb6565b61027690612cee565b6115359061304c611ffe565b6102769061306061279761158b600161123c565b610276906130716115f66000610b10565b6130a39060019060206117c47f0000000000000000000000000000000000000000000000000000000000000000610420565b03915afa92831561094e576000936130c0575b50611822906130e4565b6118229193506130dd9060203d811161136e576113668183610871565b92906130b6565b6131106114037f0000000000000000000000000000000000000000000000000000000000000000610420565b6370a08231913391602061312360405190565b809261312f8760e01b90565b8252818061314088600483016102ef565b03915afa90811561094e576131649161315e9160009161134d575090565b82612bcb565b61316d30610420565b9273cff94c34175a57086d48e54cf3367f5fee9a2f429363fc6e90e09061319d61319660405190565b9260e01b90565b8252602082806131b1878560048401611cb4565b0381895af491821561094e5760009261322a575b5060206131f99293612eea6114037f0000000000000000000000000000000000000000000000000000000000000000610420565b8252818061320a8a600483016102ef565b03915afa801561094e57612e4f612f29916101a09460009161134d575090565b6131f99250613247602091823d811161136e576113668183610871565b92506131c5565b61027690613040565b61153590613263611ffe565b6132b4565b1561326f57565b60405162461bcd60e51b815260206004820152601b60248201527f55534220746f204d617267696e20546f6b656e732070617573656400000000006044820152606490fd5b610276906132cd6132c861158b6001611252565b613268565b610276906132de6115f66000610b10565b60009061330f60206112eb7f0000000000000000000000000000000000000000000000000000000000000000610420565b03915afa91821561094e57839160009361348d575b5061332e906134dc565b613450575b503061333e81610420565b73cff94c34175a57086d48e54cf3367f5fee9a2f42630b7c48059161336260405190565b9161336d8460e01b90565b8352602083806133808560048301610432565b0381845af4801561094e576133b3946133ab6118b692602096600091611b4157506118a16004611288565b60405161131f565b03915af4801561094e576133d091600091611b2357506004611702565b61340d60206133fe7f0000000000000000000000000000000000000000000000000000000000000000610420565b6349d3d5e19061090260405190565b825260049082905afa90811561094e57600091613432575b5061194f61099884610a6d565b61344a915060203d81116109475761093f8183610871565b38613425565b61345a6003611288565b613466610d3284610b10565b0361347e575b50613478426003611702565b38613333565b61348790614615565b3861346c565b61332e9193506134aa9060203d811161136e576113668183610871565b9290613324565b61027290610b10565b6107bd6102769461219b606094989795612194608086019a60008701906134b1565b6135086114037f0000000000000000000000000000000000000000000000000000000000000000610420565b906370a0823190339161351d61198a60405190565b81526020818061353086600483016102ef565b0381875afa90811561094e576135559161354f9160009161134d575090565b82612942565b61355e30610420565b9061016073cff94c34175a57086d48e54cf3367f5fee9a2f429263e80eba32936129b17f0000000000000000000000000000000000000000000000000000000000000000956135bd866135b060405190565b9889968795869560e01b90565b03915af4801561094e576135e7946000938492613795575b50604051602091639dc29fac91611e8a565b8252816000816135fb888b60048401610e42565b03925af193841561094e5761368595600095613775575b50613629611ed5846136246002611288565b6137d2565b60208201916040613638845190565b910195613643875190565b917f8331e6d9453e2cdb4da24bdc7337453d7324ddf71d1cb7949834baea5de4ba439161366f85610420565b998a9461367b60405190565b9384938a85612175565b0390a26136b46114037f0000000000000000000000000000000000000000000000000000000000000000610420565b906340c10f1990823b1561026d5785926114c8600080946136d7611a5260405190565b03925af1801561094e57611f3092613734926126939261375f575b50876000876136ff845190565b9161372d61370b8c5190565b6000805160206149e78339815191529461372460405190565b948594856134ba565b0390a25190565b7f52d7aa340d530e823911f14778f0f82b34460971ef6af5c237d103ebeae637bc946122ed60405190565b61376f9060006123078183610871565b386136f2565b61378e91955060203d811161136e576113668183610871565b9338613612565b602094506137b39192506101603d8111611f9857611f878183610871565b939190916135d5565b61027690613257565b9190820391821161205e57565b6102e391906137c5565b613825335b61380d6109987f0000000000000000000000000000000000000000000000000000000000000000610420565b613816826102d7565b1490811561382d575b50610953565b610276613844565b905061383d610cc46109986108c5565b143861381f565b61384c611ffe565b6115356138787f0000000000000000000000000000000000000000000000000000000000000000610420565b6349d3d5e161388660405190565b916138918260e01b90565b8352602083600481845afa92831561094e57600093613b05575b506000926138be610cc461099886610a6d565b036138c857505050565b6138d89160209161090260405190565b825260049082905afa801561094e576138f991600091613ae7575b50610420565b7f0000000000000000000000000000000000000000000000000000000000000000613934610cc46000805160206149c78339815191526102d7565b14613a82575b61394390610420565b634e606c4790803b1561026d5761395f91839161090260405190565b8252600490829084905af1801561094e57613a66575b5061399f7f0000000000000000000000000000000000000000000000000000000000000000610420565b634e29a33390803b1561026d57826139b660405190565b80926139c28560e01b90565b8252600490829084905af1801561094e57613a4a575b50613a056114037f0000000000000000000000000000000000000000000000000000000000000000610420565b803b1561026d57613a1b91839161090260405190565b8252600490829084905af1801561094e57613a34575050565b8161027692903d10612315576123078183610871565b613a6090833d8511612315576123078183610871565b386139d8565b613a7c90823d8411612315576123078183610871565b38613975565b613a8b81610420565b90637114177a91803b1561026d57613aa892849161191e60405190565b8252600490829084905af191821561094e5761394392613acb575b50905061393a565b613ae190843d8611612315576123078183610871565b38613ac3565b613aff915060203d81116109475761093f8183610871565b386138f3565b613b1e91935060203d81116109475761093f8183610871565b91386138ab565b6102766137dc565b613b36336137e1565b610276613b41611ffe565b611535613b6d7f0000000000000000000000000000000000000000000000000000000000000000610420565b63095f363c90613b7f61319660405190565b8252602082600481845afa90811561094e57613baf92600092613c70575b506040516020916340ae3e149161191e565b825260049082905afa91821561094e57600092613c50575b50600091613bd483610a6d565b91613be1610cc4846102d7565b14159182613c38575b5050613bf35750565b613c1c7f0000000000000000000000000000000000000000000000000000000000000000610420565b63ddef195390803b1561026d57613a1b91839161090260405190565b613c47919250610cc4906102d7565b14153880613bea565b613c6991925060203d81116109475761093f8183610871565b9038613bc7565b6020919250613c8b90823d81116109475761093f8183610871565b9190613b9d565b610276613b2d565b613ca2611ffe565b611535613cfa565b15613cb157565b60405162461bcd60e51b815280610a5c600482016020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b613d39335b6020613d2a7f0000000000000000000000000000000000000000000000000000000000000000610420565b63c1d6ba699061191e60405190565b825260049082905afa801561094e57610cc4613d6191613d6794600091613d6f575b506102d7565b14613caa565b610276613dad565b613d87915060203d81116109475761093f8183610871565b38613d5b565b9060ff906116f8565b90613da66102e361171992151590565b8254613d8d565b613db8600180613d96565b7fd7d248ba47bac931be252275aff92303dd610ca36c92c05dbac783fde1662a0e613de260405190565b80805b0390a1565b610276613c9a565b613dfa611ffe565b611535613e0633613cff565b825260049082905afa801561094e57610cc4613d6191613e2d94600091613d6f57506102d7565b610276613e3c60006001613d96565b7fd76d4045ba8d223490b9c6a5657cfdaa2316ac28a5a65274870bfe66a33ea0c4613de260405190565b610276613df2565b613e76611ffe565b611535613e8233613cff565b825260049082905afa801561094e57610cc4613d6191613ea994600091613d6f57506102d7565b610276613ed5565b9061ff009060081b6116f8565b90613ece6102e361171992151590565b8254613eb1565b613ee0600180613ebe565b7f60b78ed2d882d2d2387ad2b7119495f7c99dd9a9c191d3d02c35982a0750bcc6613de260405190565b610276613e6e565b613f1a611ffe565b611535613f2633613cff565b825260049082905afa801561094e57610cc4613d6191613f4d94600091613d6f57506102d7565b610276613f5c60006001613ebe565b7f687bf6e69dbabcc95e11041b4816a83f36dcf6ef647f6acf63e7469d28f5ea73613de260405190565b610276613f12565b613f96611ffe565b611535613fa233613cff565b825260049082905afa801561094e57610cc4613d6191613fc994600091613d6f57506102d7565b610276613ff6565b9062ff00009060101b6116f8565b90613fef6102e361171992151590565b8254613fd1565b614001600180613fdf565b7fff1961bacbc4ad36bbb3affa41b9ca1167f9f3e8b2fa05b3a3d87546424c72f8613de260405190565b610276613f8e565b61403b611ffe565b61153561404733613cff565b825260049082905afa801561094e57610cc4613d619161406e94600091613d6f57506102d7565b61027661407d60006001613fdf565b7fe2a0c3d430f5c761f9440a5c7c1a9c27524338eb75537ec0ffa23744248e89de613de260405190565b610276614033565b611535906140bb611ffe565b33906140eb60206108f37f0000000000000000000000000000000000000000000000000000000000000000610420565b825260049082905afa92831561094e57613d61610cc46102769561411694600091613d6f57506102d7565b614185565b1561412257565b60405162461bcd60e51b815260206004820152601560248201527416995c9bc81859191c995cdcc819195d1958dd1959605a1b6044820152606490fd5b906001600160a01b03906116f8565b9061417e6102e361171992610420565b825461415f565b6141ac6102769161140361419c6109986000610a6d565b6141a5836102d7565b141561411b565b600661416e565b610276906140af565b156141c357565b60405162461bcd60e51b81526020600482015260186024820152774e6f7420656e6f7567682061737365742062616c616e636560401b6044820152606490fd5b9081526060810193926102769290916040916107bd906020830152565b929061422c8185612063565b906142567f0000000000000000000000000000000000000000000000000000000000000000610420565b63e3d670d77f00000000000000000000000000000000000000000000000000000000000000009361428961319660405190565b82526020828061429c88600483016102ef565b0381865afa801561094e57610d326142bd916142c49460009161134d575090565b11156141bc565b6000956142d087610b10565b81116145ae575b506142e186610b10565b82116144c5575b5050506142f483610b10565b81116143ec575b5061430582610b10565b831161431057505050565b61433c6114037f0000000000000000000000000000000000000000000000000000000000000000610420565b91639dc29fac3393803b1561026d5761435a91839161090260405190565b825281838161436d8b8b60048401610e42565b03925af1801561094e576143cf575b505061438e6040611eec602084015190565b92611f306143bc7f3b931001c0728420650d0922e385dcd2dbcf634aee98dc541642fe27358da45894610420565b946143c660405190565b93849384614203565b816143e592903d10612315576123078183610871565b388061437c565b6144186114037f0000000000000000000000000000000000000000000000000000000000000000610420565b6144286020639dc29fac33612907565b825281888161443b898960048401610e42565b03925af190811561094e576000916144a7575b50614460611ed5846136246002611288565b60208401519261449e614474604087015190565b6122e37f8331e6d9453e2cdb4da24bdc7337453d7324ddf71d1cb7949834baea5de4ba4395610420565b0390a2386142fb565b6144bf915060203d811161136e576113668183610871565b3861444e565b6145119063d9caed1260206144f97f0000000000000000000000000000000000000000000000000000000000000000610420565b6361d027b39061450860405190565b95869260e01b90565b825260049082905afa92831561094e5760009361458e575b50813b1561026d57876145519161455c829661454460405190565b9889978896879560e01b90565b855260048501610ea5565b03925af1801561094e57614572575b80806142e8565b61458890843d8611612315576123078183610871565b3861456b565b6145a791935060203d81116109475761093f8183610871565b9138614529565b63d9caed123391833b1561026d5788916145da61455192886145cf60405190565b968795869560e01b90565b038183865af1801561094e57156142d75761460190873d8911612315576123078183610871565b386142d7565b604d811161205e57600a0a90565b61466161464e61469b92614649614636426146306003611288565b906137d2565b614643605960f81b611471565b90614841565b614841565b61465b6301e13380610b10565b90614870565b602061468c7f0000000000000000000000000000000000000000000000000000000000000000610420565b63313ce5679061191e60405190565b825260049082905afa91821561094e576146c19261465b91600091614810575b50614607565b60006146cc81610b10565b82116146d6575050565b6101606146e230610420565b73cff94c34175a57086d48e54cf3367f5fee9a2f42611d7d632bb4c93261471861470b60405190565b9788958694859460e01b90565b03915af491821561094e576000926147ef575b506147586114037f0000000000000000000000000000000000000000000000000000000000000000610420565b63bc4f2d6d90803b1561026d5761477491839161090260405190565b825260048201869052602490829084905af1801561094e576147d2575b50506147a4611ed582611ed06002611288565b613de57ff1bbb98ed8a759d6a70a94f35aa8e98b8cea8b6173370a12de519df22047ccb4916102ca60405190565b816147e892903d10612315576123078183610871565b3880614791565b6148099192506101603d8111611f9857611f878183610871565b919061472b565b614828915060203d811161136e576113668183610871565b386146bb565b8181029291811591840414171561205e57565b6102e3919061482e565b634e487b7160e01b600052601260045260246000fd5b811561486b570490565b61484b565b6102e39190614861565b9061488b634141525360e01b611471565b9182811015806148d9575b156148a957505050610276426005611702565b821191826148ce575b50506148ba57565b6102766148c76000610b10565b6005611702565b9150101538806148b2565b50828210614896565b6102e3906102d7565b6102e390546148e2565b6102e36102e36102e39260ff1690565b61492790602061491861140360066148eb565b63a3e6ba949061191e60405190565b825260049082905afa801561094e57614961926000916149a8575b50602061495261140360066148eb565b63313ce5679061450860405190565b825260049082905afa92831561094e57600093614984575b506102e390926148f5565b6102e39193506149a19060203d81116114535761144b8183610871565b9290614979565b6149c0915060203d811161136e576113668183610871565b3861494256fe000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee79d2400774c9ceba50645590d91414af42f277c27641bd9cba2f5b92db83ad5a26469706673582212206a2f19b43db9da5a33dbe74858fd0307fcc3270bb6604755dc33fdf67ed0541864736f6c6343000812003360e0604052346200006f576200001f6200001862000123565b90620001de565b6040516115eb620002a782396080518181816102530152610bba015260a051818181610188015261047a015260c051818181610109015281816104ee0152818161079d0152610ad301526115eb90f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b03821117620000ac57604052565b62000074565b90620000c9620000c160405190565b92836200008a565b565b6001600160a01b031690565b90565b6001600160a01b038116036200006f57565b90505190620000c982620000da565b91906040838203126200006f57620000d790620001198185620000ec565b93602001620000ec565b6200014662001892803803806200013a81620000b2565b928339810190620000fb565b9091565b620000cb620000d7620000d79290565b620000d7906200014a565b156200016d57565b60405162461bcd60e51b815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606490fd5b620000d790620000cb906001600160a01b031682565b620000d790620001b2565b620000d790620001c8565b620002306200023992620001f162000290565b620002266200020160006200015a565b6001600160a01b0381166001600160a01b038616141590816200023e575b5062000165565b3360a052620001d3565b608052620001d3565b60c052565b6001600160a01b031690506001600160a01b0383161415386200021f565b620000d7620000d7620000d79290565b620000d760016200025c565b90620000d7620000d76200028c926200025c565b9055565b620000c96200029e6200026c565b60006200027856fe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c80633fef6dc11461008b5780634e29a333146100865780638da5cb5b14610081578063d9caed121461007c578063ddef195314610077578063e06174e4146100725763e3d670d70361000e5761028b565b61023e565b610226565b61020d565b61016f565b610139565b6100f4565b600091031261009b57565b600080fd5b6100b4906100b7906001600160a01b031682565b90565b6001600160a01b031690565b6100b4906100a0565b6100b4906100c3565b6100de906100cc565b9052565b6020810192916100f291906100d5565b565b3461009b57610104366004610090565b6101357f00000000000000000000000000000000000000000000000000000000000000005b604051918291826100e2565b0390f35b3461009b57610149366004610090565b61015161069f565b604051005b6100de906100b7565b6020810192916100f29190610156565b3461009b5761017f366004610090565b604051806101357f00000000000000000000000000000000000000000000000000000000000000008261015f565b6101b6816100b7565b0361009b57565b905035906100f2826101ad565b806101b6565b905035906100f2826101ca565b909160608284031261009b576100b46101f684846101bd565b9361020481602086016101bd565b936040016101d0565b3461009b576101516102203660046101dd565b91610d31565b3461009b57610236366004610090565b6101516108ed565b3461009b5761024e366004610090565b6101357f0000000000000000000000000000000000000000000000000000000000000000610129565b9060208282031261009b576100b4916101bd565b3461009b576101356102a66102a1366004610277565b610321565b6040515b9182918290815260200190565b634e487b7160e01b600052604160045260246000fd5b90601f01601f1916810190811067ffffffffffffffff8211176102ef57604052565b6102b7565b905051906100f2826101ca565b9060208282031261009b576100b4916102f4565b6040513d6000823e3d90fd5b61034373eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6100b7565b6100b7565b61034c826100b7565b0361035f575061035b306100cc565b3190565b60206103756103706103a9936100cc565b6100cc565b6370a082319061039e610387306100cc565b9261039160405190565b9586948593849360e01b90565b83526004830161015f565b03915afa9081156103e7576000916103bf575090565b6100b4915060203d81116103e0575b6103d881836102cd565b810190610301565b503d6103ce565b610315565b6103f461073a565b6103fc61046d565b6100f2610776565b0190565b60208082526021908201527f546f6b656e506f743a2063616c6c6572206973206e6f7420746865206f776e656040820152603960f91b606082015260800190565b1561045057565b60405162461bcd60e51b81528061046960048201610408565b0390fd5b6104aa335b6104a461049e7f00000000000000000000000000000000000000000000000000000000000000006100b7565b916100b7565b14610449565b6100f26104e9565b905051906100f2826101ad565b9060208282031261009b576100b4916104b2565b6100b76100b46100b49290565b6100b4906104d3565b6105127f00000000000000000000000000000000000000000000000000000000000000006100cc565b6349d3d5e161052060405190565b9161052b8260e01b90565b8352602083600481845afa9283156103e75760009361067f575b5060009261055861049e61033e866104e0565b0361056257505050565b61057b9160209161057260405190565b93849260e01b90565b825260049082905afa9081156103e7576105a19161037091600091610651575b506100cc565b637114177a813b1561009b576105c06105b960405190565b9160e01b90565b8152828160048183865af180156103e757610635575b50634e606c4790803b1561009b576105f391839161057260405190565b8252818381600481015b03925af180156103e75761060f575050565b816100f292903d1061062e575b61062681836102cd565b810190610090565b503d61061c565b61064b90833d851161062e5761062681836102cd565b386105d6565b610672915060203d8111610678575b61066a81836102cd565b8101906104bf565b3861059b565b503d610660565b61069891935060203d81116106785761066a81836102cd565b9138610545565b6100f26103ec565b6100b49081565b6100b490546106a7565b6100b46100b46100b49290565b6100b460026106b8565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b1561070d57565b60405162461bcd60e51b815280610469600482016106cf565b906100b46100b4610736926106b8565b9055565b6100f261074760006106ae565b6107656107526106c5565b91829061075e565b9190565b1415610706565b6000610726565b6100b460016106b8565b6100f261076561076c565b61078961073a565b6103fc61079533610472565b6100f26107c17f00000000000000000000000000000000000000000000000000000000000000006100cc565b63095f363c906107da6107d360405190565b9260e01b90565b8252602082600481845afa9182156103e7576000926108c7575b50602061080a916340ae3e149061057260405190565b825260049082905afa9081156103e7576000916108a9575b5060009161082f836104e0565b610838816100b7565b610841836100b7565b1415908161088e575b5061085457505050565b610370610860916100cc565b906336b91f2b90823b1561009b576105fd9261039e85809461088160405190565b9687958694859360e01b90565b61089891506100b7565b6108a1836100b7565b14153861084a565b6108c1915060203d81116106785761066a81836102cd565b38610822565b61080a9192506108e5602091823d81116106785761066a81836102cd565b9291506107f4565b6100f2610781565b906103fc929161090361073a565b6100f292919061091233610472565b610a23565b60208082526015908201527416995c9bc81859191c995cdcc819195d1958dd1959605a1b604082015260600190565b1561094d57565b60405162461bcd60e51b81528061046960048201610917565b6020808252600e908201526d125b9d985b1a5908185b5bdd5b9d60921b604082015260600190565b1561099557565b60405162461bcd60e51b81528061046960048201610966565b6002111561009b57565b905051906100f2826109ae565b60808183031261009b576109d982826102f4565b926100b46109ea84602085016102f4565b936109f881604086016102f4565b936060016109b8565b9160206100f2929493610a1c60408201966000830190610156565b0190610156565b90610b0f90600093610a34856104e0565b91610a3e836100b7565b610a47866100b7565b141580610d12575b610a5890610946565b610a61866106b8565b821180610cf8575b610a729061098e565b610a7b306100cc565b94610a8883828885610d3c565b7fa4195c37c2947bbe89165f03e320b6903116f0b10d8cfdb522330f7ce6f9fa24610ac9610abf610ab980336100cc565b946100cc565b946102aa60405190565b0390a46020610af77f00000000000000000000000000000000000000000000000000000000000000006100cc565b6349d3d5e190610b0660405190565b94859260e01b90565b825260049082905afa9182156103e757600092610cd4575b50610b31906100b7565b610b3a826100b7565b03610b4457505050565b610370610b50916100cc565b9063dde798a4610b626105b960405190565b815260808180610b75856004830161015f565b0381865afa80156103e7576000918291610ca1575b50610b9761075a866106b8565b119081610c8c575b50610ba957505050565b610bf69163954fa5ee936020610bde7f00000000000000000000000000000000000000000000000000000000000000006100cc565b6361d027b390610bed60405190565b96879260e01b90565b825260049082905afa9384156103e757600094610c66575b50610c309060209495610c3b610c2360405190565b9788968795869460e01b90565b845260048401610a01565b03925af180156103e757610c4c5750565b610c639060203d81116103e0576103d881836102cd565b50565b6020945090610c84610c3092863d81116106785761066a81836102cd565b945090610c0e565b9050610c9a61075a856106b8565b1138610b9f565b9050610cc4915060803d8111610ccd575b610cbc81836102cd565b8101906109c5565b50919091610b8a565b503d610cb2565b610b31919250610cf19060203d81116106785761066a81836102cd565b9190610b27565b50610a72610d086100b483610321565b8311159050610a69565b50610a58610d1f846100b7565b610d28836100b7565b14159050610a4f565b906100f292916108f5565b929190610d5c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6100b7565b610d65856100b7565b03610d74576100f29350610fd5565b6100f2936110ea565b6020808252600c908201526b53616d65206164647265737360a01b604082015260600190565b15610daa57565b60405162461bcd60e51b81528061046960048201610d7d565b6020808252600c908201526b5a65726f206164647265737360a01b604082015260600190565b15610df057565b60405162461bcd60e51b81528061046960048201610dc3565b6020808252602a908201527f4f6e65206f662074686520616464726573736573206d757374206265207468696040820152691cc818dbdb9d1c9858dd60b21b606082015260800190565b15610e5a57565b60405162461bcd60e51b81528061046960048201610e09565b6020808252601d908201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604082015260600190565b15610eb157565b60405162461bcd60e51b81528061046960048201610e73565b602080825260139082015272496e636f7272656374206d73672e76616c756560681b604082015260600190565b15610efe57565b60405162461bcd60e51b81528061046960048201610eca565b906100f2610f2460405190565b92836102cd565b67ffffffffffffffff81116102ef57602090601f01601f19160190565b90610f5a610f5583610f2b565b610f17565b918252565b3d15610f7957610f6e3d610f48565b903d6000602084013e565b606090565b6020808252601c908201527f4e617469766520746f6b656e207472616e73666572206661696c656400000000604082015260600190565b15610fbc57565b60405162461bcd60e51b81528061046960048201610f7e565b90610ff2610fe2826100b7565b610feb846100b7565b1415610da3565b611060600092611025611004856104e0565b61100d816100b7565b611016846100b7565b141590816110cf575b50610de9565b61102e306100cc565b9061103b61049e836100b7565b1480156110b1575b61104c90610e53565b61033e611058856106b8565b865b11610eaa565b611069826100b7565b1461109a5781906100f29361107d60405190565b9081611088816100b4565b03925af1611094610f5f565b50610fb5565b50506100f2906110ab61075a349290565b14610ef7565b5061104c6110be826100b7565b6110c7856100b7565b149050611043565b6110d991506100b7565b6110e2856100b7565b14153861101f565b9291906111026110f9836100b7565b610feb836100b7565b61114161113b6000611136611116826104e0565b61111f816100b7565b611128876100b7565b1415908161117e5750610de9565b6106b8565b8461105a565b61114d61033e306100cc565b611156826100b7565b0361116d57506111686100f2936100cc565b6111d6565b6111796100f2946100cc565b611248565b61118891506100b7565b6110e2876100b7565b6111aa6111a46100b49263ffffffff1690565b60e01b90565b6001600160e01b03191690565b9160206100f29294936111d260408201966000830190610156565b0152565b61121960049261120a6100f2956111f063a9059cbb611191565b926111fa60405190565b96879460208601908152016111b7565b602082018103825203836102cd565b61134c565b6040906111d26100f2949695939661123e60608401986000850190610156565b6020830190610156565b906112199061120a6100f2956004956112646323b872dd611191565b9361126e60405190565b978895602087019081520161121e565b6112886020610f48565b7f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602082015290565b6100b461127e565b8015156101b6565b905051906100f2826112b9565b9060208282031261009b576100b4916112c1565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b1561133357565b60405162461bcd60e51b815280610469600482016112e2565b6100f29161135c61136b926100cc565b906113656112b1565b916113a9565b805161137a61075a60006106b8565b14908115611389575b5061132c565b6113a391506020611398825190565b8183010191016112ce565b38611383565b6100b492916113b860006106b8565b91611424565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b1561140b57565b60405162461bcd60e51b815280610469600482016113be565b9060006100b494938192611436606090565b5061144d611443306100cc565b8390311015611404565b60208101905191855af161145f610f5f565b916114bc565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b156114a357565b60405162461bcd60e51b81528061046960048201611465565b919290156114ee575081516114d461075a60006106b8565b146114dd575090565b6114e96100b4916114f4565b61149c565b8261156e565b3b61150261075a60006106b8565b1190565b60005b8381106115195750506000910152565b8181015183820152602001611509565b61154a6115536020936104049361153e815190565b80835293849260200190565b95869101611506565b601f01601f191690565b60208082526100b492910190611529565b90611577825190565b61158461075a60006106b8565b11156115935750805190602001fd5b610469906115a060405190565b62461bcd60e51b81529182916004830161155d56fea26469706673582212201e7c7c7bc36c12b89caf700f5cdfb9fb8166a9843a51e36321d55a3a82c5e7bc64736f6c6343000812003300000000000000000000000031e9026bf3a20fa3250a94cad5e6bfbe203b001b0000000000000000000000007449dc43a03e70050c4acd3f8a6acab9a7f879330000000000000000000000004300000000000000000000000000000000000003000000000000000000000000836aed3b0e0ee44c77e0b6db34d170abcce9baac000000000000000000000000b4bb26cc7d36d6045432d89fc525b8adee269ad8
Deployed Bytecode
0x60806040526004361015610023575b361561001957600080fd5b61002161095a565b005b60003560e01c8062b190d91461025d57806302b0dbd7146102585780631083f761146102535780631a8bd2da1461024e5780632db574a1146102495780632e2071211461024457806332ec84d21461023f5780633a006cda1461023a5780633fef6dc1146102355780634ac032be146102305780634e29a3331461022b57806350eb741c1461022657806351dddf4f146102215780635c975abb1461021c5780635cd480b4146102175780636685ed87146102125780636a8f6ebb1461020d578063741bef1a146102085780637b4a7cea146102035780638d93fb21146101c75780638da5cb5b146101fe57806395877f78146101f95780639e3141d3146101f4578063a098ba73146101ef578063af3345d1146101ea578063b85fc766146101e5578063c66f2455146101e0578063cd85cdb5146101db578063d5ba6809146101d6578063ddef1953146101d1578063e06174e4146101cc578063e0851a88146101c7578063e13a4fe9146101c2578063ea00162c146101bd578063eaee8425146101b85763f7a17d930361000e57610822565b610807565b6107ef565b6107c1565b610639565b610771565b610759565b610741565b610729565b61070e565b6106f3565b6106db565b6106c3565b6106ab565b610693565b61064e565b610626565b61060b565b6105cc565b610593565b61057b565b610551565b61051e565b61050b565b6104f3565b6104d4565b610442565b6103eb565b6103d3565b61039a565b610387565b610340565b6102ff565b6102ab565b610278565b600091031261026d57565b600080fd5b9052565b565b3461026d57610288366004610262565b6102a76102936113ac565b6040519182918260ff909116815260200190565b0390f35b3461026d576102bb366004610262565b6102a76102c661151a565b6040515b9182918290815260200190565b6001600160a01b031690565b90565b610272906102d7565b60208101929161027691906102e6565b3461026d5761030f366004610262565b6102a77f00000000000000000000000043000000000000000000000000000000000000035b604051918291826102ef565b3461026d57610350366004610262565b610358613e66565b604051005b805b0361026d57565b905035906102768261035d565b9060208282031261026d576102e391610366565b610358610395366004610373565b611f9f565b3461026d576103aa366004610262565b6102a77f000000000000000000000000d86b2b6f1169e4304be700d6522c3ff79ff8fb77610334565b3461026d576103e3366004610262565b610358613f0a565b3461026d576103586103fe366004610373565b612ce5565b6102e3906102d7906001600160a01b031682565b6102e390610403565b6102e390610417565b61027290610420565b6020810192916102769190610429565b3461026d57610452366004610262565b6102a77f00000000000000000000000031e9026bf3a20fa3250a94cad5e6bfbe203b001b5b60405191829182610432565b634e487b7160e01b600052602160045260246000fd5b600211156104a357565b610483565b9061027682610499565b6102e3906104a8565b610272906104b2565b60208101929161027691906104bb565b3461026d576104e4366004610262565b604051806102a76001826104c4565b3461026d57610503366004610262565b610358613b25565b610358610519366004610373565b61272d565b3461026d5761052e366004610262565b6103586140a7565b90151581529015156020820152901515604082015260600190565b3461026d57610561366004610262565b6102a761056c61125c565b60405191939193849384610536565b3461026d5761035861058e366004610373565b6137bc565b3461026d576105a3366004610262565b6102a77f000000000000000000000000836aed3b0e0ee44c77e0b6db34d170abcce9baac610334565b3461026d576105dc366004610262565b6102a76102c6611512565b6102e3916008021c6102d7565b906102e391546105e7565b6102e3600060066105f4565b3461026d5761061b366004610262565b6102a76104776105ff565b610358610634366004610373565b612350565b3461026d57610649366004610262565b6114d3565b3461026d5761065e366004610262565b6102a76103346108c5565b61035f816102d7565b9050359061027682610669565b9060208282031261026d576102e391610672565b3461026d576103586106a636600461067f565b6141b3565b3461026d576103586106be366004610373565b61324e565b3461026d576103586106d6366004610373565b612a65565b3461026d576106eb366004610262565b610358613f86565b3461026d57610703366004610262565b6102a76102c6611292565b3461026d5761071e366004610262565b6102a76102c66112bd565b3461026d57610739366004610262565b610358613dea565b3461026d57610358610754366004610373565b613037565b3461026d57610769366004610262565b610358613c92565b3461026d57610781366004610262565b6102a77f0000000000000000000000007449dc43a03e70050c4acd3f8a6acab9a7f87933610477565b9081526040810192916102769160200152565b0152565b3461026d576107d1366004610262565b6107d9611465565b906102a76107e660405190565b928392836107aa565b3461026d576107ff366004610262565b61035861402b565b3461026d576102a76102c661081d366004610373565b611471565b3461026d57610832366004610262565b6102a77f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610477565b634e487b7160e01b600052604160045260246000fd5b90601f01601f1916810190811067ffffffffffffffff82111761089357604052565b61085b565b9050519061027682610669565b9060208282031261026d576102e391610898565b6040513d6000823e3d90fd5b61090b60206108f37f00000000000000000000000031e9026bf3a20fa3250a94cad5e6bfbe203b001b610420565b63c1d6ba699061090260405190565b93849260e01b90565b825260049082905afa90811561094e57600091610926575090565b6102e3915060203d8111610947575b61093f8183610871565b8101906108a5565b503d610935565b6108b9565b1561026d57565b6102767f00000000000000000000000043000000000000000000000000000000000000036109ac61099d6000805160206149c78339815191526102d7565b6102d7565b6109a6836102d7565b14610953565b6109b530610420565b6109de7f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b9034925b9291906109fc6000805160206149c78339815191526102d7565b610a05856102d7565b03610a14576102769350610c5e565b61027693610d75565b0190565b15610a2857565b60405162461bcd60e51b815260206004820152600c60248201526b53616d65206164647265737360a01b6044820152606490fd5b0390fd5b6102d76102e36102e39290565b6102e390610a60565b15610a7d57565b60405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606490fd5b15610ab857565b60405162461bcd60e51b815260206004820152602a60248201527f4f6e65206f662074686520616464726573736573206d757374206265207468696044820152691cc818dbdb9d1c9858dd60b21b6064820152608490fd5b6102e36102e36102e39290565b15610b2457565b60405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606490fd5b15610b7057565b60405162461bcd60e51b8152602060048201526013602482015272496e636f7272656374206d73672e76616c756560681b6044820152606490fd5b90610276610bb860405190565b9283610871565b67ffffffffffffffff811161089357602090601f01601f19160190565b90610bee610be983610bbf565b610bab565b918252565b3d15610c0d57610c023d610bdc565b903d6000602084013e565b606090565b15610c1957565b60405162461bcd60e51b815260206004820152601c60248201527f4e617469766520746f6b656e207472616e73666572206661696c6564000000006044820152606490fd5b90610c7b610c6b826102d7565b610c74846102d7565b1415610a21565b610cef600092610cae610c8d85610a6d565b610c96816102d7565b610c9f846102d7565b14159081610d5a575b50610a76565b610cb730610420565b90610cca610cc4836102d7565b916102d7565b148015610d3c575b610cdb90610ab1565b610998610ce785610b10565b865b11610b1d565b610cf8826102d7565b14610d2157819061027693610d0c60405190565b90818003925af1610d1b610bf3565b50610c12565b505061027690610d36610d32349290565b9190565b14610b69565b50610cdb610d49826102d7565b610d52856102d7565b149050610cd2565b610d6491506102d7565b610d6d856102d7565b141538610ca8565b929190610d8d610d84836102d7565b610c74836102d7565b610dcc610dc66000610dc1610da182610a6d565b610daa816102d7565b610db3876102d7565b14159081610e095750610a76565b610b10565b84610ce9565b610dd861099830610420565b610de1826102d7565b03610df85750610df361027693610420565b610e5d565b610e0461027694610420565b610ecf565b610e1391506102d7565b610d6d876102d7565b610e35610e2f6102e39263ffffffff1690565b60e01b90565b6001600160e01b03191690565b9160206102769294936107bd604082019660008301906102e6565b610ea0600492610e9161027695610e7763a9059cbb610e1c565b92610e8160405190565b9687946020860190815201610e42565b60208201810382520383610871565b610fc8565b6040906107bd6102769496959396610ec5606084019860008501906102e6565b60208301906102e6565b90610ea090610e9161027695600495610eeb6323b872dd610e1c565b93610ef560405190565b9788956020870190815201610ea5565b610f0f6020610bdc565b7f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602082015290565b6102e3610f05565b80151561035f565b9050519061027682610f40565b9060208282031261026d576102e391610f48565b15610f7057565b60405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b61027691610fd8610fe792610420565b90610fe1610f38565b91611025565b8051610ff6610d326000610b10565b14908115611005575b50610f69565b61101f91506020611014825190565b818301019101610f55565b38610fff565b6102e392916110346000610b10565b91611095565b1561104157565b60405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608490fd5b9060006102e3949381926110a7606090565b506110be6110b430610420565b839031101561103a565b60208101905191855af16110d0610bf3565b91611122565b156110dd57565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b919290156111545750815161113a610d326000610b10565b14611143575090565b61114f6102e39161115a565b6110d6565b826111d4565b3b611168610d326000610b10565b1190565b60005b83811061117f5750506000910152565b818101518382015260200161116f565b6111b06111b9602093610a1d936111a4815190565b80835293849260200190565b9586910161116c565b601f01601f191690565b60208082526102e39291019061118f565b906111dd825190565b6111ea610d326000610b10565b11156111f95750805190602001fd5b610a5c9061120660405190565b62461bcd60e51b8152918291600483016111c3565b6102e3905b60ff1690565b6102e3905461121b565b6102e39060081c611220565b6102e39054611230565b6102e39060101c611220565b6102e39054611246565b6112666001611226565b611270600161123c565b9161127b6001611252565b91929190565b6102e39081565b6102e39054611281565b6102e36002611288565b905051906102768261035d565b9060208282031261026d576102e39161129c565b61133760206112eb7f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b63e3d670d79061132c7f00000000000000000000000043000000000000000000000000000000000000039261131f60405190565b9586948593849360e01b90565b8352600483016102ef565b03915afa90811561094e5760009161134d575090565b6102e3915060203d811161136e575b6113668183610871565b8101906112a9565b503d61135c565b6112206102e36102e39290565b60ff811661035f565b9050519061027682611382565b9060208282031261026d576102e39161138b565b7f00000000000000000000000043000000000000000000000000000000000000036113e46000805160206149c78339815191526102d7565b6113ed826102d7565b1461145a57602061140861140361141793610420565b610420565b63313ce5679061090260405190565b825260049082905afa90811561094e57600091611432575090565b6102e3915060203d8111611453575b61144b8183610871565b810190611398565b503d611441565b506102e36012611375565b61146d614905565b9091565b602061149c7f0000000000000000000000007449dc43a03e70050c4acd3f8a6acab9a7f87933610420565b635bec50be906114c86114ae30610420565b926113376114bb60405190565b9687958694859460e01b90565b845260048401610e42565b60405162461bcd60e51b815260206004820152600d60248201526c139bdd081cdd5c1c1bdc9d1959609a1b6044820152606490fd5b6102e3600a610b10565b6102e3611508565b6102e36005611288565b61153590611530611ffe565b611577565b610276612030565b1561154457565b60405162461bcd60e51b815260206004820152600b60248201526a135a5b9d081c185d5cd95960aa1b6044820152606490fd5b6102769061159461158f61158b6001611226565b1590565b61153d565b6115e5565b156115a057565b60405162461bcd60e51b815260206004820152601c60248201527f56616c7565206d7573742062652067726561746572207468616e2030000000006044820152606490fd5b610276906115fd6115f66000610b10565b8211611599565b611686565b1561160957565b60405162461bcd60e51b815260206004820152601560248201527406d73672e76616c75652073686f756c64206265203605c1b6044820152606490fd5b1561164d57565b60405162461bcd60e51b8152602060048201526011602482015270496e76616c6964206d73672076616c756560781b6044820152606490fd5b610276907f00000000000000000000000043000000000000000000000000000000000000036116c5610cc46000805160206149c78339815191526102d7565b036116db576116d681345b14611646565b611792565b6116d6346116ec610d326000610b10565b14611602565b90600019905b9181191691161790565b906117126102e361171992610b10565b82546116f2565b9055565b6002111561026d57565b905051906102768261171d565b60808183031261026d57611748828261129c565b926102e3611759846020850161129c565b93611767816040860161129c565b93606001611727565b91602061027692949361178b604082019660008301906102e6565b01906102e6565b6118059060019060206117c47f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b63e3d670d79061132c7f0000000000000000000000004300000000000000000000000000000000000003926117f860405190565b9788948593849360e01b90565b03915afa92831561094e57600093611b9c575b5061182290611d45565b611b5e575b503061183281610420565b9073cff94c34175a57086d48e54cf3367f5fee9a2f42630b7c48059261185760405190565b916118628560e01b90565b8352602083806118758560048301610432565b0381845af4801561094e576118c1956118a66118b692602096600091611b41575b506118a16004611288565b61487a565b6040519687948593849360e01b90565b835260048301610432565b03915af491821561094e57611927926118e491600091611b23575b506004611702565b602061190f7f00000000000000000000000031e9026bf3a20fa3250a94cad5e6bfbe203b001b610420565b6349d3d5e19061191e60405190565b94859260e01b90565b825260049082905afa91821561094e57600092611b03575b5060009161194f61099884610a6d565b611958826102d7565b0361196257505050565b61140361196e91610420565b9061197d63dde798a491610420565b9061199161198a60405190565b9160e01b90565b8152608081806119a485600483016102ef565b0381865afa801561094e576000918291611ad0575b506119c6610d3286610b10565b119081611abb575b506119d857505050565b611a259163954fa5ee936020611a0d7f0000000000000000000000007449dc43a03e70050c4acd3f8a6acab9a7f87933610420565b6361d027b390611a1c60405190565b96879260e01b90565b825260049082905afa93841561094e57600094611a95575b50611a5f9060209495611a6a611a5260405190565b9788968795869460e01b90565b845260048401611770565b03925af1801561094e57611a7b5750565b611a929060203d811161136e576113668183610871565b50565b6020945090611ab3611a5f92863d81116109475761093f8183610871565b945090611a3d565b9050611ac9610d3285610b10565b11386119ce565b9050611af3915060803d8111611afc575b611aeb8183610871565b810190611734565b509190916119b9565b503d611ae1565b611b1c91925060203d81116109475761093f8183610871565b903861193f565b611b3b915060203d811161136e576113668183610871565b386118dc565b611b589150873d811161136e576113668183610871565b38611896565b611b686003611288565b611b75610d326000610b10565b03611b8d575b50611b87426003611702565b38611827565b611b9690614615565b38611b7b565b611822919350611bb99060203d811161136e576113668183610871565b9290611818565b9190916101408184031261026d57611c89611bdc610140610bab565b936000611be9828561129c565b908601526020611bfb8282860161129c565b908601526040611c0d8282860161129c565b908601526060611c1f8282860161129c565b908601526080611c318282860161129c565b9086015260a0611c438282860161129c565b9086015260c0611c558282860161129c565b9086015260e0611c678282860161129c565b90860152610100611c7a8282860161129c565b9086015261012080930161129c565b90830152565b91906101608382031261026d576102e390611caa8185611bc0565b936101400161129c565b9160206102769294936107bd60408201966000830190610429565b15611cd657565b60405162461bcd60e51b815260206004820152600e60248201526d4141522042656c6f77204141525360901b6044820152606490fd5b9095949261027694611d3e6107bd92611d37608096611d3060a088019c6000890152565b6020870152565b6040850152565b6060830152565b309080610160611d5484610420565b73cff94c34175a57086d48e54cf3367f5fee9a2f42611d7d632bb4c932611d886114bb60405190565b845260048401611cb4565b03915af491821561094e57611e9393600080939094611f69575b50611dc9611db160a086015190565b611dc2610d326102e360c089015190565b1015611ccf565b817f0000000000000000000000004300000000000000000000000000000000000003611e026000805160206149c78339815191526102d7565b611e0b826102d7565b03611f5957611e1c611e4b93610420565b611e457f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b916109e2565b611e776114037f000000000000000000000000d86b2b6f1169e4304be700d6522c3ff79ff8fb77610420565b9260206340c10f193395611e8a60405190565b97889260e01b90565b825281600081611ea7898b60048401610e42565b03925af194851561094e57600095611f35575b50611f3090611edc611ed585611ed06002611288565b612063565b6002611702565b611ef26040611eec602084015190565b92015190565b90611f1d7f63c3f185975ecdfdf59dfa778ff2ddbfe5a3f930ccc104a7b4f6d9f882fde93c96610420565b96611f2760405190565b95869586611d0c565b0390a2565b611f30919550611f529060203d811161136e576113668183610871565b9490611eba565b611f64925033611e1c565b611e4b565b909350611f8f9192506101603d8111611f98575b611f878183610871565b810190611c8f565b91909238611da2565b503d611f7d565b61027690611524565b6102e36002610b10565b15611fb957565b60405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606490fd5b61027661200b6000611288565b61201f612016611fa8565b91821415611fb2565b6000611702565b6102e36001610b10565b61027661201f612026565b634e487b7160e01b600052601160045260246000fd5b9190820180921161205e57565b61203b565b6102e39190612051565b61153590612079611ffe565b6102769061208d61158f61158b6001611226565b6102769061209e6115f66000610b10565b610276907f00000000000000000000000043000000000000000000000000000000000000036120dd610cc46000805160206149c78339815191526102d7565b036120f1576120ec81346116d0565b612102565b612102346116ec610d326000610b10565b6121349060019060206117c47f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b03915afa92831561094e57600093612151575b50611822906121a2565b61182291935061216e9060203d811161136e576113668183610871565b9290612147565b6107bd6102769461219b606094989795612194608086019a6000870152565b6020850152565b6040830152565b3090806101606121b184610420565b73cff94c34175a57086d48e54cf3367f5fee9a2f42611d7d63cd6c29b56121da6114bb60405190565b03915af492831561094e5760008092909461232c575b50827f000000000000000000000000430000000000000000000000000000000000000361222a6000805160206149c78339815191526102d7565b612233826102d7565b0361231c57611e1c61224493610420565b6122706114037f000000000000000000000000836aed3b0e0ee44c77e0b6db34d170abcce9baac610420565b916340c10f193393803b1561026d5761228f9160009161090260405190565b82528183816122a2898b60048401610e42565b03925af1801561094e576122f6575b50611f306122cb60406122c5602088015190565b96015190565b6122e36000805160206149e783398151915295610420565b956122ed60405190565b94859485612175565b61230f9060005b6123078183610871565b810190610262565b386122b1565b503d6122fd565b612327925033611e1c565b612244565b90935061234891506101603d8111611f9857611f878183610871565b9092386121f0565b6102769061206d565b61153590612365611ffe565b6102769061237961158f61158b6001611226565b6102769061238a6115f66000610b10565b610276907f00000000000000000000000043000000000000000000000000000000000000036123c9610cc46000805160206149c78339815191526102d7565b036123dd576123d881346116d0565b6123ee565b6123ee346116ec610d326000610b10565b6124209060019060206117c47f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b03915afa92831561094e5760009361243d575b5061182290612494565b61182291935061245a9060203d811161136e576113668183610871565b9290612433565b90916101808284031261026d576102e361247b8484611bc0565b9361248a81610140860161129c565b936101600161129c565b80306101806124a282610420565b73cff94c34175a57086d48e54cf3367f5fee9a2f42611d7d63b7aa264c6124d86124cb60405190565b9889958694859460e01b90565b03915af491821561094e576000808093919590946126f5575b50817f000000000000000000000000430000000000000000000000000000000000000361252b6000805160206149c78339815191526102d7565b612534826102d7565b036126e557611e1c61254593610420565b6125716114037f000000000000000000000000d86b2b6f1169e4304be700d6522c3ff79ff8fb77610420565b936340c10f193390602061258460405190565b80986125908460e01b90565b8252816000816125a48c8960048401610e42565b03925af196871561094e576000976126c5575b506125c9611ed587611ed06002611288565b602083019260406125d8855190565b9101966125e3885190565b987f63c3f185975ecdfdf59dfa778ff2ddbfe5a3f930ccc104a7b4f6d9f882fde93c9161262861261287610420565b9b8c9561261e60405190565b9485948c86611d0c565b0390a26126576114037f000000000000000000000000836aed3b0e0ee44c77e0b6db34d170abcce9baac610420565b91823b1561026d5785926114c860008094612674611a5260405190565b03925af1801561094e57611f309261269892612693926126b157505190565b945190565b6000805160206149e7833981519152946122ed60405190565b6126c19060006123078183610871565b5190565b6126de91975060203d811161136e576113668183610871565b95386125b7565b6126f0925033611e1c565b612545565b919450925061271c91506101803d8111612726575b6127148183610871565b810190612461565b91939092386124f1565b503d61270a565b61027690612359565b61153590612742611ffe565b612783565b1561274e57565b60405162461bcd60e51b815260206004820152600d60248201526c14995919595b481c185d5cd959609a1b6044820152606490fd5b6102769061279c61279761158b600161123c565b612747565b610276906127ad6115f66000610b10565b6127df9060019060206117c47f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b03915afa92831561094e576000936127fc575b50611822906128cf565b6118229193506128199060203d811161136e576113668183610871565b92906127f2565b1561282757565b60405162461bcd60e51b81526020600482015260166024820152754e6f7420656e6f756768205553422062616c616e636560501b6044820152606490fd5b6101a08183031261026d5761287a8282611bc0565b926102e361288c84610140850161129c565b9361289b81610160860161129c565b936101800161129c565b6040906107bd61027694969593966128c560608401986000850190610429565b6020830190610429565b6128fb6114037f000000000000000000000000d86b2b6f1169e4304be700d6522c3ff79ff8fb77610420565b61291160206370a08231335b9361090260405190565b8252818061292287600483016102ef565b03915afa90811561094e57612949916129409160009161134d575090565b835b1115612820565b61295230610420565b916101a073cff94c34175a57086d48e54cf3367f5fee9a2f429363b6f25c87946129b17f0000000000000000000000007449dc43a03e70050c4acd3f8a6acab9a7f87933966129bc866129a460405190565b998a968795869560e01b90565b8552600485016128a5565b03915af490811561094e576000938492839190612a2a575b50611f30906129ef6129e66000610b10565b84838988614220565b6129ff6040611eec602084015190565b90611f1d7f83e33350dd7d2770e5ef41f54623d7ab48e7ed10992b6fcacd403ec7433b4aa096610420565b9050612a54919450611f3092506101a03d8111612a5e575b612a4c8183610871565b810190612865565b95929150926129d4565b503d612a42565b61027690612736565b61153590612a7a611ffe565b61027690612a8e61279761158b600161123c565b61027690612a9f6115f66000610b10565b612ad19060019060206117c47f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b03915afa92831561094e57600093612aee575b5061182290612b5e565b611822919350612b0b9060203d811161136e576113668183610871565b9290612ae4565b15612b1957565b60405162461bcd60e51b815260206004820152601f60248201527f4e6f7420656e6f756768206d617267696e20746f6b656e2062616c616e6365006044820152606490fd5b612b8a6114037f000000000000000000000000836aed3b0e0ee44c77e0b6db34d170abcce9baac610420565b612b9a60206370a0823133612907565b82528180612bab87600483016102ef565b03915afa90811561094e57612bd291612bc99160009161134d575090565b835b1115612b12565b612bdb30610420565b916101a073cff94c34175a57086d48e54cf3367f5fee9a2f429363be008d49946129b17f0000000000000000000000007449dc43a03e70050c4acd3f8a6acab9a7f8793396612c2d866129a460405190565b03915af490811561094e576000938492839190612cba575b5080612c69612c5860a0611f3094015190565b611dc2610d326102e360c086015190565b612c7f83612c776000610b10565b838988614220565b612c8f6040611eec602084015190565b90611f1d7fe695803557243d1db69c47b18a9d48a4cda9a440d066d05610a559766e52690c96610420565b9050612cdb919450611f3092506101a03d8111612a5e57612a4c8183610871565b9592915092612c45565b61027690612a6e565b61153590612cfa611ffe565b61027690612d0e61279761158b600161123c565b61027690612d1f6115f66000610b10565b612d519060019060206117c47f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b03915afa92831561094e57600093612d6e575b5061182290612dd6565b611822919350612d8b9060203d811161136e576113668183610871565b9290612d64565b9194612dcf6107bd92989795612dc860a096612dc16102769a612dba60c08a019e60008b0152565b6020890152565b6040870152565b6060850152565b6080830152565b612e026114037f000000000000000000000000d86b2b6f1169e4304be700d6522c3ff79ff8fb77610420565b6370a0823133916020612e1460405190565b8092612e208560e01b90565b82528180612e3188600483016102ef565b03915afa90811561094e57612e5591612e4f9160009161134d575090565b84612942565b612e5e30610420565b9273cff94c34175a57086d48e54cf3367f5fee9a2f429363c9e5cf2592612e8e612e8760405190565b9460e01b90565b845260208480612ea2868660048401611cb4565b0381895af493841561094e5760009461300f575b50906020612ef292612eea6114037f000000000000000000000000836aed3b0e0ee44c77e0b6db34d170abcce9baac610420565b60405161191e565b82528180612f038a600483016102ef565b03915afa801561094e57612f23612f29916101a09460009161134d575090565b85612bcb565b6394764610956129b17f0000000000000000000000007449dc43a03e70050c4acd3f8a6acab9a7f8793397612f6e87612f6160405190565b9a8b968795869560e01b90565b03915af493841561094e5760009485918291612fe6575b509081612f988585611f3095858b614220565b612fa86040611eec602084015190565b91612fd37f349a548d6a4fdc89e9f4cee7a49220b59a0cda0e7062c7ba8e406c4b5137b0c497610420565b97612fdd60405190565b96879687612d92565b9050611f30955061300691506101a03d8111612a5e57612a4c8183610871565b92915095612f85565b612ef29291945061302e602091823d811161136e576113668183610871565b94919250612eb6565b61027690612cee565b6115359061304c611ffe565b6102769061306061279761158b600161123c565b610276906130716115f66000610b10565b6130a39060019060206117c47f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b03915afa92831561094e576000936130c0575b50611822906130e4565b6118229193506130dd9060203d811161136e576113668183610871565b92906130b6565b6131106114037f000000000000000000000000836aed3b0e0ee44c77e0b6db34d170abcce9baac610420565b6370a08231913391602061312360405190565b809261312f8760e01b90565b8252818061314088600483016102ef565b03915afa90811561094e576131649161315e9160009161134d575090565b82612bcb565b61316d30610420565b9273cff94c34175a57086d48e54cf3367f5fee9a2f429363fc6e90e09061319d61319660405190565b9260e01b90565b8252602082806131b1878560048401611cb4565b0381895af491821561094e5760009261322a575b5060206131f99293612eea6114037f000000000000000000000000d86b2b6f1169e4304be700d6522c3ff79ff8fb77610420565b8252818061320a8a600483016102ef565b03915afa801561094e57612e4f612f29916101a09460009161134d575090565b6131f99250613247602091823d811161136e576113668183610871565b92506131c5565b61027690613040565b61153590613263611ffe565b6132b4565b1561326f57565b60405162461bcd60e51b815260206004820152601b60248201527f55534220746f204d617267696e20546f6b656e732070617573656400000000006044820152606490fd5b610276906132cd6132c861158b6001611252565b613268565b610276906132de6115f66000610b10565b60009061330f60206112eb7f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b03915afa91821561094e57839160009361348d575b5061332e906134dc565b613450575b503061333e81610420565b73cff94c34175a57086d48e54cf3367f5fee9a2f42630b7c48059161336260405190565b9161336d8460e01b90565b8352602083806133808560048301610432565b0381845af4801561094e576133b3946133ab6118b692602096600091611b4157506118a16004611288565b60405161131f565b03915af4801561094e576133d091600091611b2357506004611702565b61340d60206133fe7f00000000000000000000000031e9026bf3a20fa3250a94cad5e6bfbe203b001b610420565b6349d3d5e19061090260405190565b825260049082905afa90811561094e57600091613432575b5061194f61099884610a6d565b61344a915060203d81116109475761093f8183610871565b38613425565b61345a6003611288565b613466610d3284610b10565b0361347e575b50613478426003611702565b38613333565b61348790614615565b3861346c565b61332e9193506134aa9060203d811161136e576113668183610871565b9290613324565b61027290610b10565b6107bd6102769461219b606094989795612194608086019a60008701906134b1565b6135086114037f000000000000000000000000d86b2b6f1169e4304be700d6522c3ff79ff8fb77610420565b906370a0823190339161351d61198a60405190565b81526020818061353086600483016102ef565b0381875afa90811561094e576135559161354f9160009161134d575090565b82612942565b61355e30610420565b9061016073cff94c34175a57086d48e54cf3367f5fee9a2f429263e80eba32936129b17f0000000000000000000000007449dc43a03e70050c4acd3f8a6acab9a7f87933956135bd866135b060405190565b9889968795869560e01b90565b03915af4801561094e576135e7946000938492613795575b50604051602091639dc29fac91611e8a565b8252816000816135fb888b60048401610e42565b03925af193841561094e5761368595600095613775575b50613629611ed5846136246002611288565b6137d2565b60208201916040613638845190565b910195613643875190565b917f8331e6d9453e2cdb4da24bdc7337453d7324ddf71d1cb7949834baea5de4ba439161366f85610420565b998a9461367b60405190565b9384938a85612175565b0390a26136b46114037f000000000000000000000000836aed3b0e0ee44c77e0b6db34d170abcce9baac610420565b906340c10f1990823b1561026d5785926114c8600080946136d7611a5260405190565b03925af1801561094e57611f3092613734926126939261375f575b50876000876136ff845190565b9161372d61370b8c5190565b6000805160206149e78339815191529461372460405190565b948594856134ba565b0390a25190565b7f52d7aa340d530e823911f14778f0f82b34460971ef6af5c237d103ebeae637bc946122ed60405190565b61376f9060006123078183610871565b386136f2565b61378e91955060203d811161136e576113668183610871565b9338613612565b602094506137b39192506101603d8111611f9857611f878183610871565b939190916135d5565b61027690613257565b9190820391821161205e57565b6102e391906137c5565b613825335b61380d6109987f00000000000000000000000031e9026bf3a20fa3250a94cad5e6bfbe203b001b610420565b613816826102d7565b1490811561382d575b50610953565b610276613844565b905061383d610cc46109986108c5565b143861381f565b61384c611ffe565b6115356138787f00000000000000000000000031e9026bf3a20fa3250a94cad5e6bfbe203b001b610420565b6349d3d5e161388660405190565b916138918260e01b90565b8352602083600481845afa92831561094e57600093613b05575b506000926138be610cc461099886610a6d565b036138c857505050565b6138d89160209161090260405190565b825260049082905afa801561094e576138f991600091613ae7575b50610420565b7f0000000000000000000000004300000000000000000000000000000000000003613934610cc46000805160206149c78339815191526102d7565b14613a82575b61394390610420565b634e606c4790803b1561026d5761395f91839161090260405190565b8252600490829084905af1801561094e57613a66575b5061399f7f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b634e29a33390803b1561026d57826139b660405190565b80926139c28560e01b90565b8252600490829084905af1801561094e57613a4a575b50613a056114037f000000000000000000000000836aed3b0e0ee44c77e0b6db34d170abcce9baac610420565b803b1561026d57613a1b91839161090260405190565b8252600490829084905af1801561094e57613a34575050565b8161027692903d10612315576123078183610871565b613a6090833d8511612315576123078183610871565b386139d8565b613a7c90823d8411612315576123078183610871565b38613975565b613a8b81610420565b90637114177a91803b1561026d57613aa892849161191e60405190565b8252600490829084905af191821561094e5761394392613acb575b50905061393a565b613ae190843d8611612315576123078183610871565b38613ac3565b613aff915060203d81116109475761093f8183610871565b386138f3565b613b1e91935060203d81116109475761093f8183610871565b91386138ab565b6102766137dc565b613b36336137e1565b610276613b41611ffe565b611535613b6d7f00000000000000000000000031e9026bf3a20fa3250a94cad5e6bfbe203b001b610420565b63095f363c90613b7f61319660405190565b8252602082600481845afa90811561094e57613baf92600092613c70575b506040516020916340ae3e149161191e565b825260049082905afa91821561094e57600092613c50575b50600091613bd483610a6d565b91613be1610cc4846102d7565b14159182613c38575b5050613bf35750565b613c1c7f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b63ddef195390803b1561026d57613a1b91839161090260405190565b613c47919250610cc4906102d7565b14153880613bea565b613c6991925060203d81116109475761093f8183610871565b9038613bc7565b6020919250613c8b90823d81116109475761093f8183610871565b9190613b9d565b610276613b2d565b613ca2611ffe565b611535613cfa565b15613cb157565b60405162461bcd60e51b815280610a5c600482016020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b613d39335b6020613d2a7f00000000000000000000000031e9026bf3a20fa3250a94cad5e6bfbe203b001b610420565b63c1d6ba699061191e60405190565b825260049082905afa801561094e57610cc4613d6191613d6794600091613d6f575b506102d7565b14613caa565b610276613dad565b613d87915060203d81116109475761093f8183610871565b38613d5b565b9060ff906116f8565b90613da66102e361171992151590565b8254613d8d565b613db8600180613d96565b7fd7d248ba47bac931be252275aff92303dd610ca36c92c05dbac783fde1662a0e613de260405190565b80805b0390a1565b610276613c9a565b613dfa611ffe565b611535613e0633613cff565b825260049082905afa801561094e57610cc4613d6191613e2d94600091613d6f57506102d7565b610276613e3c60006001613d96565b7fd76d4045ba8d223490b9c6a5657cfdaa2316ac28a5a65274870bfe66a33ea0c4613de260405190565b610276613df2565b613e76611ffe565b611535613e8233613cff565b825260049082905afa801561094e57610cc4613d6191613ea994600091613d6f57506102d7565b610276613ed5565b9061ff009060081b6116f8565b90613ece6102e361171992151590565b8254613eb1565b613ee0600180613ebe565b7f60b78ed2d882d2d2387ad2b7119495f7c99dd9a9c191d3d02c35982a0750bcc6613de260405190565b610276613e6e565b613f1a611ffe565b611535613f2633613cff565b825260049082905afa801561094e57610cc4613d6191613f4d94600091613d6f57506102d7565b610276613f5c60006001613ebe565b7f687bf6e69dbabcc95e11041b4816a83f36dcf6ef647f6acf63e7469d28f5ea73613de260405190565b610276613f12565b613f96611ffe565b611535613fa233613cff565b825260049082905afa801561094e57610cc4613d6191613fc994600091613d6f57506102d7565b610276613ff6565b9062ff00009060101b6116f8565b90613fef6102e361171992151590565b8254613fd1565b614001600180613fdf565b7fff1961bacbc4ad36bbb3affa41b9ca1167f9f3e8b2fa05b3a3d87546424c72f8613de260405190565b610276613f8e565b61403b611ffe565b61153561404733613cff565b825260049082905afa801561094e57610cc4613d619161406e94600091613d6f57506102d7565b61027661407d60006001613fdf565b7fe2a0c3d430f5c761f9440a5c7c1a9c27524338eb75537ec0ffa23744248e89de613de260405190565b610276614033565b611535906140bb611ffe565b33906140eb60206108f37f00000000000000000000000031e9026bf3a20fa3250a94cad5e6bfbe203b001b610420565b825260049082905afa92831561094e57613d61610cc46102769561411694600091613d6f57506102d7565b614185565b1561412257565b60405162461bcd60e51b815260206004820152601560248201527416995c9bc81859191c995cdcc819195d1958dd1959605a1b6044820152606490fd5b906001600160a01b03906116f8565b9061417e6102e361171992610420565b825461415f565b6141ac6102769161140361419c6109986000610a6d565b6141a5836102d7565b141561411b565b600661416e565b610276906140af565b156141c357565b60405162461bcd60e51b81526020600482015260186024820152774e6f7420656e6f7567682061737365742062616c616e636560401b6044820152606490fd5b9081526060810193926102769290916040916107bd906020830152565b929061422c8185612063565b906142567f000000000000000000000000565e325b7197d6105b0ee74563ea211cc838e2c3610420565b63e3d670d77f00000000000000000000000043000000000000000000000000000000000000039361428961319660405190565b82526020828061429c88600483016102ef565b0381865afa801561094e57610d326142bd916142c49460009161134d575090565b11156141bc565b6000956142d087610b10565b81116145ae575b506142e186610b10565b82116144c5575b5050506142f483610b10565b81116143ec575b5061430582610b10565b831161431057505050565b61433c6114037f000000000000000000000000836aed3b0e0ee44c77e0b6db34d170abcce9baac610420565b91639dc29fac3393803b1561026d5761435a91839161090260405190565b825281838161436d8b8b60048401610e42565b03925af1801561094e576143cf575b505061438e6040611eec602084015190565b92611f306143bc7f3b931001c0728420650d0922e385dcd2dbcf634aee98dc541642fe27358da45894610420565b946143c660405190565b93849384614203565b816143e592903d10612315576123078183610871565b388061437c565b6144186114037f000000000000000000000000d86b2b6f1169e4304be700d6522c3ff79ff8fb77610420565b6144286020639dc29fac33612907565b825281888161443b898960048401610e42565b03925af190811561094e576000916144a7575b50614460611ed5846136246002611288565b60208401519261449e614474604087015190565b6122e37f8331e6d9453e2cdb4da24bdc7337453d7324ddf71d1cb7949834baea5de4ba4395610420565b0390a2386142fb565b6144bf915060203d811161136e576113668183610871565b3861444e565b6145119063d9caed1260206144f97f0000000000000000000000007449dc43a03e70050c4acd3f8a6acab9a7f87933610420565b6361d027b39061450860405190565b95869260e01b90565b825260049082905afa92831561094e5760009361458e575b50813b1561026d57876145519161455c829661454460405190565b9889978896879560e01b90565b855260048501610ea5565b03925af1801561094e57614572575b80806142e8565b61458890843d8611612315576123078183610871565b3861456b565b6145a791935060203d81116109475761093f8183610871565b9138614529565b63d9caed123391833b1561026d5788916145da61455192886145cf60405190565b968795869560e01b90565b038183865af1801561094e57156142d75761460190873d8911612315576123078183610871565b386142d7565b604d811161205e57600a0a90565b61466161464e61469b92614649614636426146306003611288565b906137d2565b614643605960f81b611471565b90614841565b614841565b61465b6301e13380610b10565b90614870565b602061468c7f0000000000000000000000007449dc43a03e70050c4acd3f8a6acab9a7f87933610420565b63313ce5679061191e60405190565b825260049082905afa91821561094e576146c19261465b91600091614810575b50614607565b60006146cc81610b10565b82116146d6575050565b6101606146e230610420565b73cff94c34175a57086d48e54cf3367f5fee9a2f42611d7d632bb4c93261471861470b60405190565b9788958694859460e01b90565b03915af491821561094e576000926147ef575b506147586114037f000000000000000000000000d86b2b6f1169e4304be700d6522c3ff79ff8fb77610420565b63bc4f2d6d90803b1561026d5761477491839161090260405190565b825260048201869052602490829084905af1801561094e576147d2575b50506147a4611ed582611ed06002611288565b613de57ff1bbb98ed8a759d6a70a94f35aa8e98b8cea8b6173370a12de519df22047ccb4916102ca60405190565b816147e892903d10612315576123078183610871565b3880614791565b6148099192506101603d8111611f9857611f878183610871565b919061472b565b614828915060203d811161136e576113668183610871565b386146bb565b8181029291811591840414171561205e57565b6102e3919061482e565b634e487b7160e01b600052601260045260246000fd5b811561486b570490565b61484b565b6102e39190614861565b9061488b634141525360e01b611471565b9182811015806148d9575b156148a957505050610276426005611702565b821191826148ce575b50506148ba57565b6102766148c76000610b10565b6005611702565b9150101538806148b2565b50828210614896565b6102e3906102d7565b6102e390546148e2565b6102e36102e36102e39260ff1690565b61492790602061491861140360066148eb565b63a3e6ba949061191e60405190565b825260049082905afa801561094e57614961926000916149a8575b50602061495261140360066148eb565b63313ce5679061450860405190565b825260049082905afa92831561094e57600093614984575b506102e390926148f5565b6102e39193506149a19060203d81116114535761144b8183610871565b9290614979565b6149c0915060203d811161136e576113668183610871565b3861494256fe000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee79d2400774c9ceba50645590d91414af42f277c27641bd9cba2f5b92db83ad5a26469706673582212206a2f19b43db9da5a33dbe74858fd0307fcc3270bb6604755dc33fdf67ed0541864736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000031e9026bf3a20fa3250a94cad5e6bfbe203b001b0000000000000000000000007449dc43a03e70050c4acd3f8a6acab9a7f879330000000000000000000000004300000000000000000000000000000000000003000000000000000000000000836aed3b0e0ee44c77e0b6db34d170abcce9baac000000000000000000000000b4bb26cc7d36d6045432d89fc525b8adee269ad8
-----Decoded View---------------
Arg [0] : _wandProtocol (address): 0x31e9026bf3A20FA3250a94caD5E6BFbE203B001B
Arg [1] : _settings (address): 0x7449dc43a03e70050c4AcD3F8A6acab9A7F87933
Arg [2] : _assetToken_ (address): 0x4300000000000000000000000000000000000003
Arg [3] : _marginToken_ (address): 0x836aED3b0E0ee44C77e0b6Db34D170AbCCe9BaAC
Arg [4] : _assetTokenPriceFeed_ (address): 0xb4bB26cc7D36d6045432d89FC525b8adEe269ad8
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 00000000000000000000000031e9026bf3a20fa3250a94cad5e6bfbe203b001b
Arg [1] : 0000000000000000000000007449dc43a03e70050c4acd3f8a6acab9a7f87933
Arg [2] : 0000000000000000000000004300000000000000000000000000000000000003
Arg [3] : 000000000000000000000000836aed3b0e0ee44c77e0b6db34d170abcce9baac
Arg [4] : 000000000000000000000000b4bb26cc7d36d6045432d89fc525b8adee269ad8
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.