Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 56 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Approve | 53054022 | 85 days ago | IN | 0 S | 0.0013169 | ||||
| Approve | 48531965 | 120 days ago | IN | 0 S | 0.0014064 | ||||
| Approve | 48200590 | 122 days ago | IN | 0 S | 0.00167596 | ||||
| Approve | 41680710 | 174 days ago | IN | 0 S | 0.00140594 | ||||
| Approve | 32318295 | 233 days ago | IN | 0 S | 0.00140594 | ||||
| Reallocate | 29824764 | 244 days ago | IN | 0 S | 0.1269567 | ||||
| Reallocate | 29571134 | 245 days ago | IN | 0 S | 0.1251128 | ||||
| Reallocate | 29185167 | 247 days ago | IN | 0 S | 0.1127247 | ||||
| Reallocate | 29184934 | 247 days ago | IN | 0 S | 0.1190829 | ||||
| Reallocate | 29184805 | 247 days ago | IN | 0 S | 0.1190829 | ||||
| Reallocate | 29125033 | 247 days ago | IN | 0 S | 0.1122916 | ||||
| Reallocate | 29109135 | 247 days ago | IN | 0 S | 0.1145744 | ||||
| Reallocate | 29108966 | 247 days ago | IN | 0 S | 0.1204017 | ||||
| Reallocate | 29094182 | 247 days ago | IN | 0 S | 0.1015986 | ||||
| Reallocate | 29081842 | 247 days ago | IN | 0 S | 0.1017026 | ||||
| Reallocate | 29081663 | 247 days ago | IN | 0 S | 0.1078088 | ||||
| Reallocate | 29070566 | 247 days ago | IN | 0 S | 0.1042458 | ||||
| Reallocate | 29056037 | 247 days ago | IN | 0 S | 0.0938732 | ||||
| Reallocate | 29027735 | 248 days ago | IN | 0 S | 0.0933412 | ||||
| Approve | 22639569 | 274 days ago | IN | 0 S | 0.00140569 | ||||
| Reallocate | 22456283 | 275 days ago | IN | 0 S | 0.0941786 | ||||
| Reallocate | 22456054 | 275 days ago | IN | 0 S | 0.0999888 | ||||
| Reallocate | 22037048 | 276 days ago | IN | 0 S | 0.0943305 | ||||
| Approve | 18917285 | 293 days ago | IN | 0 S | 0.00247038 | ||||
| Approve | 16666007 | 303 days ago | IN | 0 S | 0.00120565 |
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 3079760 | 382 days ago | Contract Creation | 0 S |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
LendingVaultV1
Compiler Version
v0.5.16+commit.9c3226ce
Optimization Enabled:
Yes with 999999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity =0.5.16;
import "./LVSetterV1.sol";
import "./interfaces/ILendingVaultV1Factory.sol";
contract LendingVaultV1 is LVSetterV1 {
function _getTotalSupplied() internal returns (uint totalSupplied) {
for (uint i = 0; i < borrowables.length; i++) {
address borrowable = borrowables[i];
totalSupplied = totalSupplied.add(borrowable.myUnderlyingBalance());
}
}
function _mintReserves(uint _exchangeRate, uint _totalSupply) internal returns (uint) {
uint _exchangeRateLast = exchangeRateLast;
if (_exchangeRate > _exchangeRateLast) {
uint _exchangeRateNew = _exchangeRate.sub( _exchangeRate.sub(_exchangeRateLast).mul(reserveFactor).div(1e18) );
uint liquidity = _totalSupply.mul(_exchangeRate).div(_exchangeRateNew).sub(_totalSupply);
if (liquidity > 0) {
address reservesManager = ILendingVaultV1Factory(factory).reservesManager();
_mint(reservesManager, liquidity);
}
exchangeRateLast = _exchangeRateNew;
return _exchangeRateNew;
}
else return _exchangeRate;
}
function exchangeRate() public returns (uint) {
uint _totalSupply = totalSupply;
uint _actualBalance = totalBalance.add(_getTotalSupplied());
if (_totalSupply == 0 || _actualBalance == 0) return initialExchangeRate;
uint _exchangeRate = _actualBalance.mul(1e18).div(_totalSupply);
return _mintReserves(_exchangeRate, _totalSupply);
}
// this low-level function should be called from another contract
function mint(address minter) external nonReentrant update returns (uint mintTokens) {
uint balance = underlying.myBalance();
uint mintAmount = balance.sub(totalBalance);
mintTokens = mintAmount.mul(1e18).div(exchangeRate());
if(totalSupply == 0) {
// permanently lock the first MINIMUM_LIQUIDITY tokens
mintTokens = mintTokens.sub(MINIMUM_LIQUIDITY);
_mint(address(0), MINIMUM_LIQUIDITY);
}
require(mintTokens > 0, "LendingVaultV1: MINT_AMOUNT_ZERO");
_mint(minter, mintTokens);
_withdrawAndReallocate(0);
emit Mint(msg.sender, minter, mintAmount, mintTokens);
}
// this low-level function should be called from another contract
function redeem(address redeemer) external nonReentrant update returns (uint redeemAmount) {
uint redeemTokens = balanceOf[address(this)];
redeemAmount = redeemTokens.mul(exchangeRate()).div(1e18);
require(redeemAmount > 0, "LendingVaultV1: REDEEM_AMOUNT_ZERO");
_burn(address(this), redeemTokens);
_withdrawAndReallocate(redeemAmount);
underlying.safeTransfer(redeemer, redeemAmount);
emit Redeem(msg.sender, redeemer, redeemAmount, redeemTokens);
}
function reallocate() external nonReentrant update {
_withdrawAndReallocate(0);
}
}pragma solidity =0.5.16;
import "./libraries/SafeMath.sol";
// This contract is basically UniswapV2ERC20 with small modifications
// src: https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol
contract ImpermaxERC20 {
using SafeMath for uint;
string public name;
string public symbol;
uint8 public decimals = 18;
uint public totalSupply;
mapping(address => uint) public balanceOf;
mapping(address => mapping(address => uint)) public allowance;
bytes32 public DOMAIN_SEPARATOR;
mapping(address => uint) public nonces;
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
constructor() public {}
function _setName(string memory _name, string memory _symbol) internal {
name = _name;
symbol = _symbol;
uint chainId;
assembly {
chainId := chainid
}
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(_name)),
keccak256(bytes("1")),
chainId,
address(this)
)
);
}
function _mint(address to, uint value) internal {
totalSupply = totalSupply.add(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(address(0), to, value);
}
function _burn(address from, uint value) internal {
balanceOf[from] = balanceOf[from].sub(value);
totalSupply = totalSupply.sub(value);
emit Transfer(from, address(0), value);
}
function _approve(address owner, address spender, uint value) private {
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
function _transfer(address from, address to, uint value) internal {
balanceOf[from] = balanceOf[from].sub(value, "Impermax: TRANSFER_TOO_HIGH");
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(from, to, value);
}
function approve(address spender, uint value) external returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transfer(address to, uint value) external returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
function transferFrom(address from, address to, uint value) external returns (bool) {
if (allowance[from][msg.sender] != uint(-1)) {
allowance[from][msg.sender] = allowance[from][msg.sender].sub(value, "Impermax: TRANSFER_NOT_ALLOWED");
}
_transfer(from, to, value);
return true;
}
function _checkSignature(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s, bytes32 typehash) internal {
require(deadline >= block.timestamp, "Impermax: EXPIRED");
bytes32 digest = keccak256(
abi.encodePacked(
'\x19\x01',
DOMAIN_SEPARATOR,
keccak256(abi.encode(typehash, owner, spender, value, nonces[owner]++, deadline))
)
);
address recoveredAddress = ecrecover(digest, v, r, s);
require(recoveredAddress != address(0) && recoveredAddress == owner, "Impermax: INVALID_SIGNATURE");
}
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
_checkSignature(owner, spender, value, deadline, v, r, s, PERMIT_TYPEHASH);
_approve(owner, spender, value);
}
}pragma solidity >=0.5.0;
interface IBorrowable {
/*** Impermax ERC20 ***/
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
/*** Pool Token ***/
event Mint(address indexed sender, address indexed minter, uint mintAmount, uint mintTokens);
event Redeem(address indexed sender, address indexed redeemer, uint redeemAmount, uint redeemTokens);
event Sync(uint totalBalance);
function underlying() external view returns (address);
function factory() external view returns (address);
function totalBalance() external view returns (uint);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function exchangeRate() external returns (uint);
function mint(address minter) external returns (uint mintTokens);
function redeem(address redeemer) external returns (uint redeemAmount);
function skim(address to) external;
function sync() external;
function _setFactory() external;
/*** Borrowable ***/
event BorrowApproval(address indexed owner, address indexed spender, uint value);
event Borrow(address indexed sender, address indexed borrower, address indexed receiver, uint borrowAmount, uint repayAmount, uint accountBorrowsPrior, uint accountBorrows, uint totalBorrows);
event Liquidate(address indexed sender, address indexed borrower, address indexed liquidator, uint seizeTokens, uint repayAmount, uint accountBorrowsPrior, uint accountBorrows, uint totalBorrows);
function BORROW_FEE() external pure returns (uint);
function collateral() external view returns (address);
function reserveFactor() external view returns (uint);
function exchangeRateLast() external view returns (uint);
function borrowIndex() external view returns (uint);
function totalBorrows() external view returns (uint);
function borrowAllowance(address owner, address spender) external view returns (uint);
function borrowBalance(address borrower) external view returns (uint);
function borrowTracker() external view returns (address);
function BORROW_PERMIT_TYPEHASH() external pure returns (bytes32);
function borrowApprove(address spender, uint256 value) external returns (bool);
function borrowPermit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
function borrow(address borrower, address receiver, uint borrowAmount, bytes calldata data) external;
function liquidate(address borrower, address liquidator) external returns (uint seizeTokens);
function trackBorrow(address borrower) external;
/*** Borrowable Interest Rate Model ***/
event AccrueInterest(uint interestAccumulated, uint borrowIndex, uint totalBorrows);
event CalculateKink(uint kinkRate);
event CalculateBorrowRate(uint borrowRate);
function KINK_BORROW_RATE_MAX() external pure returns (uint);
function KINK_BORROW_RATE_MIN() external pure returns (uint);
function KINK_MULTIPLIER() external pure returns (uint);
function borrowRate() external view returns (uint);
function kinkBorrowRate() external view returns (uint);
function kinkUtilizationRate() external view returns (uint);
function adjustSpeed() external view returns (uint);
function rateUpdateTimestamp() external view returns (uint32);
function accrualTimestamp() external view returns (uint32);
function accrueInterest() external;
/*** Borrowable Setter ***/
event NewReserveFactor(uint newReserveFactor);
event NewKinkUtilizationRate(uint newKinkUtilizationRate);
event NewAdjustSpeed(uint newAdjustSpeed);
event NewBorrowTracker(address newBorrowTracker);
function RESERVE_FACTOR_MAX() external pure returns (uint);
function KINK_UR_MIN() external pure returns (uint);
function KINK_UR_MAX() external pure returns (uint);
function ADJUST_SPEED_MIN() external pure returns (uint);
function ADJUST_SPEED_MAX() external pure returns (uint);
function _initialize (
string calldata _name,
string calldata _symbol,
address _underlying,
address _collateral
) external;
function _setReserveFactor(uint newReserveFactor) external;
function _setKinkUtilizationRate(uint newKinkUtilizationRate) external;
function _setAdjustSpeed(uint newAdjustSpeed) external;
function _setBorrowTracker(address newBorrowTracker) external;
}pragma solidity >=0.5.0;
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
}pragma solidity >=0.5.0;
interface ILendingVaultV1 {
/*** Impermax ERC20 ***/
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
/*** Pool Token ***/
event Mint(address indexed sender, address indexed minter, uint mintAmount, uint mintTokens);
event Redeem(address indexed sender, address indexed redeemer, uint redeemAmount, uint redeemTokens);
event Sync(uint totalBalance);
function underlying() external view returns (address);
function factory() external view returns (address);
function totalBalance() external view returns (uint);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function exchangeRate() external returns (uint);
function mint(address minter) external returns (uint mintTokens);
function redeem(address redeemer) external returns (uint redeemAmount);
function skim(address to) external;
function sync() external;
function _setFactory() external;
/*** Lending Vault V1 ***/
event AddBorrowable(address indexed borrowable);
event RemoveBorrowable(address indexed borrowable);
event EnableBorrowable(address indexed borrowable);
event DisableBorrowable(address indexed borrowable);
event UnwindBorrowable(address indexed borrowable, uint256 underlyingBalance, uint256 actualRedeemAmount);
event AllocateIntoBorrowable(address indexed borrowable, uint256 mintAmount, uint256 mintTokens);
event DeallocateFromBorrowable(address indexed borrowable, uint256 redeemAmount, uint256 redeemTokens);
function borrowables(uint) external view returns (address borrowable);
function borrowableInfo(address borrowable) external view returns (
bool enabled,
bool exists
);
function getBorrowablesLength() external view returns (uint);
function indexOfBorrowable(address borrowable) external view returns (uint);
function reserveFactor() external view returns (uint);
function exchangeRateLast() external view returns (uint);
function addBorrowable(address borrowable) external;
function removeBorrowable(address borrowable) external;
function disableBorrowable(address borrowable) external;
function enableBorrowable(address borrowable) external;
function unwindBorrowable(address borrowable) external;
function reallocate() external;
/*** Lending Vault Setter ***/
event NewReserveFactor(uint newReserveFactor);
function RESERVE_FACTOR_MAX() external pure returns (uint);
function _initialize (
address _underlying,
string calldata _name,
string calldata _symbol
) external;
function _setReserveFactor(uint newReserveFactor) external;
}pragma solidity >=0.5.0;
interface ILendingVaultV1Factory {
event VaultCreated(address indexed underlying, address vault, uint);
event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
event NewAdmin(address oldAdmin, address newAdmin);
event NewReservesPendingAdmin(address oldReservesPendingAdmin, address newReservesPendingAdmin);
event NewReservesAdmin(address oldReservesAdmin, address newReservesAdmin);
event NewReservesManager(address oldReservesManager, address newReservesManager);
function admin() external view returns (address);
function pendingAdmin() external view returns (address);
function reservesAdmin() external view returns (address);
function reservesPendingAdmin() external view returns (address);
function reservesManager() external view returns (address);
function allVaults(uint) external view returns (address);
function allVaultsLength() external view returns (uint);
function createVault(address underlying, string calldata _name, string calldata _symbol) external returns (address vault);
function _setPendingAdmin(address newPendingAdmin) external;
function _acceptAdmin() external;
function _setReservesPendingAdmin(address newPendingAdmin) external;
function _acceptReservesAdmin() external;
function _setReservesManager(address newReservesManager) external;
}pragma solidity >=0.5.0;
interface IPoolToken {
/*** Impermax ERC20 ***/
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
/*** Pool Token ***/
event Mint(address indexed sender, address indexed minter, uint mintAmount, uint mintTokens);
event Redeem(address indexed sender, address indexed redeemer, uint redeemAmount, uint redeemTokens);
event Sync(uint totalBalance);
function underlying() external view returns (address);
function factory() external view returns (address);
function totalBalance() external view returns (uint);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function exchangeRate() external returns (uint);
function mint(address minter) external returns (uint mintTokens);
function redeem(address redeemer) external returns (uint redeemAmount);
function skim(address to) external;
function sync() external;
function _setFactory() external;
}pragma solidity =0.5.16;
import "./SafeMath.sol";
import "../interfaces/IBorrowable.sol";
import "../interfaces/IERC20.sol";
library BorrowableHelpers {
using SafeMath for uint256;
function underlyingValueOf(address borrowable, uint256 borrowableAmount) internal returns (uint256) {
uint256 exchangeRate = IBorrowable(borrowable).exchangeRate();
return borrowableAmount.mul(exchangeRate).div(1e18);
}
function underlyingBalanceOf(address borrowable, address account) internal returns (uint256) {
return underlyingValueOf(borrowable, IBorrowable(borrowable).balanceOf(account));
}
function myUnderlyingBalance(address borrowable) internal returns (uint256) {
return underlyingValueOf(borrowable, IBorrowable(borrowable).balanceOf(address(this)));
}
/*** AMOUNT TO TOKENS CONVERSION ***/
function tokensFor(uint redeemAmount, uint exchangeRate, bool atMost) internal pure returns (uint redeemTokens) {
uint redeemTokensLow = redeemAmount.mul(1e18).div(exchangeRate);
uint redeemTokensHigh = redeemTokensLow.add(1);
if (atMost) {
uint actualRedeemAmountHigh = redeemTokensHigh.mul(exchangeRate).div(1e18);
return actualRedeemAmountHigh <= redeemAmount ? redeemTokensHigh : redeemTokensLow;
} else {
uint actualRedeemAmountLow = redeemTokensLow.mul(exchangeRate).div(1e18);
return actualRedeemAmountLow >= redeemAmount ? redeemTokensLow : redeemTokensHigh;
}
}
function tokensForAtMost(uint redeemAmount, uint exchangeRate) internal pure returns (uint redeemTokens) {
return tokensFor(redeemAmount, exchangeRate, true);
}
function tokensForAtLeast(uint redeemAmount, uint exchangeRate) internal pure returns (uint redeemTokens) {
return tokensFor(redeemAmount, exchangeRate, false);
}
}pragma solidity =0.5.16;
pragma experimental ABIEncoderV2;
import "./SafeMath.sol";
import "./Math.sol";
import "../interfaces/IBorrowable.sol";
library BorrowableObject {
using SafeMath for uint;
using BorrowableObject for Borrowable;
struct Borrowable {
IBorrowable borrowableContract;
uint exchangeRate;
uint totalBorrows; // in underlyings
uint externalSupply; // in underlyings
uint initialOwnedSupply; // in underlyings
uint ownedSupply; // in underlyings
uint kinkBorrowRate;
uint kinkUtilizationRate;
uint reserveFactor;
uint kinkMultiplier;
uint cachedSupplyRate;
}
function newBorrowable(IBorrowable borrowableContract, address lendingVault) internal returns (Borrowable memory borrowable) {
borrowableContract.sync();
uint exchangeRate = borrowableContract.exchangeRate();
uint totalSupplyInTokens = borrowableContract.totalSupply();
uint ownedSupplyInTokens = borrowableContract.balanceOf(lendingVault);
uint externalSupplyInTokens = totalSupplyInTokens.sub(ownedSupplyInTokens);
borrowable = Borrowable({
borrowableContract: borrowableContract,
exchangeRate: exchangeRate,
totalBorrows: borrowableContract.totalBorrows(),
externalSupply: externalSupplyInTokens.mul(exchangeRate).div(1e18),
initialOwnedSupply: ownedSupplyInTokens.mul(exchangeRate).div(1e18),
ownedSupply: ownedSupplyInTokens.mul(exchangeRate).div(1e18),
kinkBorrowRate: borrowableContract.kinkBorrowRate(),
kinkUtilizationRate: borrowableContract.kinkUtilizationRate(),
reserveFactor: borrowableContract.reserveFactor(),
kinkMultiplier: borrowableContract.KINK_MULTIPLIER(),
cachedSupplyRate: 0
});
borrowable.cachedSupplyRate = supplyRate(borrowable);
return borrowable;
}
function totalSupply(Borrowable memory borrowable) internal pure returns (uint) {
return borrowable.externalSupply.add(borrowable.ownedSupply);
}
function utilizationRate(Borrowable memory borrowable) internal pure returns (uint) {
uint _totalSupply = totalSupply(borrowable);
if (_totalSupply == 0) return 0;
return borrowable.totalBorrows.mul(1e18).div(_totalSupply);
}
function kinkRate(Borrowable memory borrowable) internal pure returns (uint) {
return borrowable.kinkUtilizationRate
.mul(borrowable.kinkBorrowRate).div(1e18)
.mul(uint(1e18).sub(borrowable.reserveFactor)).div(1e18);
}
function supplyRate(Borrowable memory borrowable) internal pure returns (uint rate) {
uint utilizationRate_ = utilizationRate(borrowable);
uint ratio = utilizationRate_.mul(1e18).div(borrowable.kinkUtilizationRate);
uint borrowFactor; //borrowRate to kinkBorrowRate ratio
if (utilizationRate_ < borrowable.kinkUtilizationRate) {
borrowFactor = ratio;
} else {
uint excessRatio = utilizationRate_.sub(borrowable.kinkUtilizationRate)
.mul(1e18).div(uint(1e18).sub(borrowable.kinkUtilizationRate));
borrowFactor = excessRatio.mul(borrowable.kinkMultiplier.sub(1)).add(1e18);
}
rate = borrowFactor.mul(kinkRate(borrowable)).div(1e18).mul(ratio).div(1e18);
}
function allocate(Borrowable memory borrowable, uint amount) internal pure returns (Borrowable memory) {
borrowable.ownedSupply = borrowable.ownedSupply.add(amount);
borrowable.cachedSupplyRate = supplyRate(borrowable);
return borrowable;
}
function deallocate(Borrowable memory borrowable, uint amount) internal pure returns (Borrowable memory) {
uint availableLiquidity = totalSupply(borrowable).sub(borrowable.totalBorrows, "ERROR: NEGATIVE AVAILABLE LIQUIDITY");
require(amount <= availableLiquidity, "ERROR: DEALLOCATE AMOUNT > AVAILABLE LIQUIDITY");
borrowable.ownedSupply = borrowable.ownedSupply.sub(amount);
borrowable.cachedSupplyRate = supplyRate(borrowable);
return borrowable;
}
function deallocateMax(Borrowable memory borrowable) internal pure returns (Borrowable memory, uint) {
if (totalSupply(borrowable) < borrowable.totalBorrows) return (borrowable, 0);
uint availableLiquidity = totalSupply(borrowable).sub(borrowable.totalBorrows);
uint amount = Math.min(borrowable.ownedSupply, availableLiquidity);
return (deallocate(borrowable, amount), amount);
}
function calculateUtilizationForRate(Borrowable memory borrowable, uint rate) internal pure returns (uint targetUtilizationRate) {
if (rate <= kinkRate(borrowable)) {
targetUtilizationRate = Math.sqrt(
rate.mul(1e18).div(kinkRate(borrowable)).mul(1e18)
).mul(borrowable.kinkUtilizationRate).div(1e18);
} else {
uint a = borrowable.kinkMultiplier.sub(1);
uint b = borrowable.kinkUtilizationRate.mul(borrowable.kinkMultiplier).sub(1e18);
uint c = rate.mul(borrowable.kinkUtilizationRate).div(1e18)
.mul(uint(1e18).sub(borrowable.kinkUtilizationRate)).div(kinkRate(borrowable));
uint tmp = Math.sqrt(
b.mul(b).div(1e18).add(a.mul(c).mul(4)).mul(1e18)
);
targetUtilizationRate = tmp.add(b).div(a).div(2);
}
require(targetUtilizationRate <= 1e18, "ERROR: TARGET UTILIZATION > 100%");
}
function calculateAmountForRate(Borrowable memory borrowable, uint rate) internal pure returns (uint) {
require(rate > 0, "ERROR: rate = 0");
require(rate <= borrowable.cachedSupplyRate, "ERROR: TARGET RATE > CACHED RATE");
uint targetUtilizationRate = calculateUtilizationForRate(borrowable, rate);
require(targetUtilizationRate <= utilizationRate(borrowable), "ERROR: TARGET UTILIZATION > CURRENT UTILIZATION");
uint targetSupply = borrowable.totalBorrows.mul(1e18).div(targetUtilizationRate);
return targetSupply.sub(totalSupply(borrowable), "ERROR: TARGET SUPPLY > TOTAL SUPPLY");
}
function compare(Borrowable memory borrowableA, Borrowable memory borrowableB) internal pure returns (bool) {
return borrowableA.cachedSupplyRate > borrowableB.cachedSupplyRate;
}
}pragma solidity =0.5.16;
// a library for performing various math operations
// forked from: https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/libraries/Math.sol
library Math {
function min(uint x, uint y) internal pure returns (uint z) {
z = x < y ? x : y;
}
// babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
function sqrt(uint y) internal pure returns (uint z) {
if (y > 3) {
z = y;
uint x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}pragma solidity =0.5.16;
// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol
// Subject to the MIT license.
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the addition of two unsigned integers, reverting with custom message on overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, errorMessage);
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot underflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction underflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot underflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @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) {
// 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 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @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, string memory errorMessage) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, errorMessage);
return c;
}
/**
* @dev Returns the integer division of two unsigned integers.
* Reverts on division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers.
* Reverts 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) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts 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 mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}pragma solidity =0.5.16;
interface ERC20Interface {
function balanceOf(address user) external view returns (uint256);
}
library SafeToken {
function myBalance(address token) internal view returns (uint256) {
return ERC20Interface(token).balanceOf(address(this));
}
function balanceOf(address token, address user) internal view returns (uint256) {
return ERC20Interface(token).balanceOf(user);
}
function safeApprove(address token, address to, uint256 value) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), "!safeApprove");
}
function safeTransfer(address token, address to, uint256 value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), "!safeTransfer");
}
function safeTransferFrom(address token, address from, address to, uint256 value) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), "!safeTransferFrom");
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call.value(value)(new bytes(0));
require(success, "!safeTransferETH");
}
}pragma solidity =0.5.16;
import "./PoolToken.sol";
import "./LVStorageV1.sol";
import "./interfaces/ILendingVaultV1.sol";
import "./libraries/BorrowableHelpers.sol";
import "./libraries/BorrowableObject.sol";
contract LVAllocatorV1 is ILendingVaultV1, PoolToken, LVStorageV1 {
using BorrowableHelpers for address;
using BorrowableObject for BorrowableObject.Borrowable;
function _allocate(IBorrowable borrowable, uint mintAmount, uint _exchangeRate) internal returns (uint mintTokens) {
mintTokens = mintAmount.mul(1e18).div(_exchangeRate);
if (mintTokens == 0) return 0;
underlying.safeTransfer(address(borrowable), mintAmount);
mintTokens = borrowable.mint(address(this));
emit AllocateIntoBorrowable(address(borrowable), mintAmount, mintTokens);
}
function _allocate(IBorrowable borrowable, uint mintAmount) internal returns (uint mintTokens) {
mintTokens = _allocate(borrowable, mintAmount, borrowable.exchangeRate());
}
function _deallocate(IBorrowable borrowable, uint redeemTokens, uint _exchangeRate) internal returns (uint redeemAmount) {
redeemAmount = redeemTokens.mul(_exchangeRate).div(1e18);
if (redeemAmount == 0) return 0;
uint totalBalance = borrowable.totalBalance();
if (redeemAmount > totalBalance) {
redeemTokens = totalBalance.mul(1e18).div(_exchangeRate);
}
address(borrowable).safeTransfer(address(borrowable), redeemTokens);
redeemAmount = borrowable.redeem(address(this));
emit DeallocateFromBorrowable(address(borrowable), redeemAmount, redeemTokens);
}
function _deallocate(IBorrowable borrowable, uint redeemTokens) internal returns (uint redeemAmount) {
redeemAmount = _deallocate(borrowable, redeemTokens, borrowable.exchangeRate());
}
function _deallocateAtLeastOrMax(IBorrowable borrowable, uint redeemAmount, uint _exchangeRate) internal returns (uint actualRedeemAmount) {
actualRedeemAmount = _deallocate(IBorrowable(borrowable), BorrowableHelpers.tokensForAtLeast(redeemAmount, _exchangeRate), _exchangeRate);
}
function _deallocateAtLeastOrMax(IBorrowable borrowable, uint redeemAmount) internal returns (uint actualRedeemAmount) {
actualRedeemAmount = _deallocateAtLeastOrMax(borrowable, redeemAmount, borrowable.exchangeRate());
}
function _withdrawAndReallocate(uint withdrawAmount) internal {
// initialize borrowablesObj
BorrowableObject.Borrowable[] memory borrowablesObj = new BorrowableObject.Borrowable[](borrowables.length);
uint borrowablesLength = borrowables.length;
for(uint i = 0; i < borrowables.length; i++) {
if (!borrowableInfo[borrowables[i]].enabled) {
borrowablesLength--;
continue;
}
uint delta = uint(borrowables.length).sub(borrowablesLength);
borrowablesObj[i - delta] = BorrowableObject.newBorrowable(IBorrowable(borrowables[i]), address(this));
}
// deallocate everything
uint amountToAllocate = underlying.myBalance();
for(uint i = 0; i < borrowablesLength; i++) {
uint amount;
(borrowablesObj[i], amount) = borrowablesObj[i].deallocateMax();
amountToAllocate = amountToAllocate.add(amount);
}
amountToAllocate = amountToAllocate.sub(withdrawAmount, "LendingVaultV1: INSUFFICIENT_LIQUIDITY");
// bubblesort borrowablesObj
for (uint i = 0; i < borrowablesLength - 1; i++) {
for (uint j = 0; j < borrowablesLength - 1 - i; j++) {
if (!borrowablesObj[j].compare(borrowablesObj[j+1])) {
BorrowableObject.Borrowable memory tmp = borrowablesObj[j];
borrowablesObj[j] = borrowablesObj[j+1];
borrowablesObj[j+1] = tmp;
}
}
}
// Allocate in the pool with the highest APR an amount such that the next APR matches the one
// of the pool with the second highest APR.
// Repeat until all the pools with the highest APR have the same APR.
uint lastCycle = borrowablesLength;
for(uint i = 1; i < borrowablesLength; i++) {
uint targetRate = borrowablesObj[i].cachedSupplyRate;
uint amountThisCycle = 0;
uint[] memory amounts = new uint[](i);
if (targetRate == 0) {
// Unachievable APR
lastCycle = i;
break;
}
for (uint j = 0; j < i; j++) {
if (borrowablesObj[j].cachedSupplyRate <= targetRate) break;
amounts[j] = borrowablesObj[j].calculateAmountForRate(targetRate);
amountThisCycle = amountThisCycle.add(amounts[j]);
}
if (amountThisCycle > amountToAllocate) {
// We can't afford to complete this cycle
lastCycle = i;
break;
}
for (uint j = 0; j < i; j++) {
if (amounts[j] == 0) continue;
borrowablesObj[j] = borrowablesObj[j].allocate(amounts[j]);
amountToAllocate = amountToAllocate.sub(amounts[j]);
}
}
// distribute the amount left equally among pools with highest APR proportionally to their total supply
uint globalTotalSupply = 0;
uint totalAmountToAllocate = amountToAllocate;
for (uint i = 0; i < lastCycle; i++) {
globalTotalSupply = globalTotalSupply.add(borrowablesObj[i].totalSupply());
}
for (uint i = 0; i < lastCycle; i++) {
uint amount = globalTotalSupply > 0
? borrowablesObj[i].totalSupply().mul(totalAmountToAllocate).div(globalTotalSupply)
: amountToAllocate;
if (amount > amountToAllocate) amount = amountToAllocate;
borrowablesObj[i] = borrowablesObj[i].allocate(amount);
amountToAllocate = amountToAllocate.sub(amount);
}
// redeem
for(uint i = 0; i < borrowablesLength; i++) {
if (borrowablesObj[i].ownedSupply < borrowablesObj[i].initialOwnedSupply) {
uint redeemAmount = borrowablesObj[i].initialOwnedSupply.sub(borrowablesObj[i].ownedSupply);
_deallocateAtLeastOrMax(borrowablesObj[i].borrowableContract, redeemAmount, borrowablesObj[i].exchangeRate);
}
}
// mint
amountToAllocate = underlying.myBalance().sub(withdrawAmount, "LendingVaultV1: NEGATIVE AMOUNT TO ALLOCATE");
for(uint i = 0; i < borrowablesLength; i++) {
if (borrowablesObj[i].ownedSupply > borrowablesObj[i].initialOwnedSupply) {
uint mintAmount = borrowablesObj[i].ownedSupply.sub(borrowablesObj[i].initialOwnedSupply);
if (mintAmount > amountToAllocate) mintAmount = amountToAllocate;
amountToAllocate = amountToAllocate.sub(mintAmount);
_allocate(borrowablesObj[i].borrowableContract, mintAmount, borrowablesObj[i].exchangeRate);
}
}
}
}pragma solidity =0.5.16;
import "./LVAllocatorV1.sol";
import "./interfaces/ILendingVaultV1Factory.sol";
contract LVSetterV1 is LVAllocatorV1 {
uint public constant RESERVE_FACTOR_MAX = 0.90e18; //90%
uint private constant MAX_BORROWABLES_LENGTH = 10;
function _initialize(
address _underlying,
string calldata _name,
string calldata _symbol
) external {
require(msg.sender == factory, "LendingVaultV1: UNAUTHORIZED"); // sufficient check
_setName(_name, _symbol);
underlying = _underlying;
exchangeRateLast = initialExchangeRate;
}
function _setReserveFactor(uint newReserveFactor) external onlyAdmin nonReentrant {
require(newReserveFactor <= RESERVE_FACTOR_MAX, "LendingVaultV1: INVALID_SETTING");
reserveFactor = newReserveFactor;
emit NewReserveFactor(newReserveFactor);
}
/*** Borrowables management ***/
function addBorrowable(address borrowable) external onlyAdmin nonReentrant {
require(IBorrowable(borrowable).underlying() == underlying, "LendingVaultV1: INVALID_UNDERLYING");
require(!borrowableInfo[borrowable].exists, "LendingVaultV1: BORROWABLE_EXISTS");
require(borrowables.length < MAX_BORROWABLES_LENGTH, "LendingVaultV1: MAX_BORROWABLES_LENGTH");
borrowableInfo[borrowable].exists = true;
borrowableInfo[borrowable].enabled = true;
borrowables.push(borrowable);
emit AddBorrowable(address(borrowable));
}
function removeBorrowable(address borrowable) external onlyAdmin nonReentrant {
require(borrowableInfo[borrowable].exists, "LendingVaultV1: BORROWABLE_DOESNT_EXISTS");
require(!borrowableInfo[borrowable].enabled, "LendingVaultV1: BORROWABLE_ENABLED");
require(borrowable.balanceOf(address(this)) == 0, "LendingVaultV1: NOT_EMPTY");
uint lastIndex = borrowables.length - 1;
uint index = indexOfBorrowable(borrowable);
borrowables[index] = borrowables[lastIndex];
borrowables.pop();
delete borrowableInfo[borrowable];
emit RemoveBorrowable(address(borrowable));
}
function disableBorrowable(address borrowable) external onlyAdmin nonReentrant {
require(borrowableInfo[borrowable].exists, "LendingVaultV1: BORROWABLE_DOESNT_EXISTS");
require(borrowableInfo[borrowable].enabled, "LendingVaultV1: BORROWABLE_DISABLED");
borrowableInfo[borrowable].enabled = false;
emit DisableBorrowable(address(borrowable));
}
function enableBorrowable(address borrowable) external onlyAdmin nonReentrant {
require(borrowableInfo[borrowable].exists, "LendingVaultV1: BORROWABLE_DOESNT_EXISTS");
require(!borrowableInfo[borrowable].enabled, "LendingVaultV1: BORROWABLE_ENABLED");
borrowableInfo[borrowable].enabled = true;
emit EnableBorrowable(address(borrowable));
}
function unwindBorrowable(address borrowable) external onlyAdmin nonReentrant update {
require(borrowableInfo[borrowable].exists, "LendingVaultV1: BORROWABLE_DOESNT_EXISTS");
require(!borrowableInfo[borrowable].enabled, "LendingVaultV1: BORROWABLE_ENABLED");
uint underlyingBalance = borrowable.myUnderlyingBalance();
require(underlyingBalance > 0, "LendingVaultV1: ZERO_AMOUNT");
uint actualRedeemAmount = _deallocateAtLeastOrMax(IBorrowable(borrowable), underlyingBalance);
emit UnwindBorrowable(address(borrowable), underlyingBalance, actualRedeemAmount);
}
modifier onlyAdmin() {
require(msg.sender == ILendingVaultV1Factory(factory).admin(), "LendingVaultV1: UNAUTHORIZED");
_;
}
}pragma solidity =0.5.16;
contract LVStorageV1 {
address[] public borrowables;
struct BorrowableInfo {
bool enabled;
bool exists;
}
mapping(address => BorrowableInfo) public borrowableInfo;
function getBorrowablesLength() external view returns (uint) {
return borrowables.length;
}
function indexOfBorrowable(address borrowable) public view returns (uint) {
for (uint i = 0; i < borrowables.length; i++) {
if (borrowables[i] == borrowable) {
return i;
}
}
require(false, "LendingVaultV1: BORROWABLE_NOT_FOUND");
}
uint public exchangeRateLast;
uint public reserveFactor = 0.10e18; //10%
}pragma solidity =0.5.16;
import "./ImpermaxERC20.sol";
import "./interfaces/IPoolToken.sol";
import "./libraries/SafeToken.sol";
contract PoolToken is IPoolToken, ImpermaxERC20 {
using SafeToken for address;
uint internal constant initialExchangeRate = 1e18;
address public underlying;
address public factory;
uint public totalBalance;
uint public constant MINIMUM_LIQUIDITY = 1000;
event Mint(address indexed sender, address indexed minter, uint mintAmount, uint mintTokens);
event Redeem(address indexed sender, address indexed redeemer, uint redeemAmount, uint redeemTokens);
event Sync(uint totalBalance);
/*** Initialize ***/
// called once by the factory
function _setFactory() external {
require(factory == address(0), "Impermax: FACTORY_ALREADY_SET");
factory = msg.sender;
}
/*** PoolToken ***/
function _update() internal {
totalBalance = underlying.myBalance();
emit Sync(totalBalance);
}
function exchangeRate() public returns (uint)
{
uint _totalSupply = totalSupply; // gas savings
uint _totalBalance = totalBalance; // gas savings
if (_totalSupply == 0 || _totalBalance == 0) return initialExchangeRate;
return _totalBalance.mul(1e18).div(_totalSupply);
}
// this low-level function should be called from another contract
function mint(address minter) external nonReentrant update returns (uint mintTokens) {
uint balance = underlying.myBalance();
uint mintAmount = balance.sub(totalBalance);
mintTokens = mintAmount.mul(1e18).div(exchangeRate());
if(totalSupply == 0) {
// permanently lock the first MINIMUM_LIQUIDITY tokens
mintTokens = mintTokens.sub(MINIMUM_LIQUIDITY);
_mint(address(0), MINIMUM_LIQUIDITY);
}
require(mintTokens > 0, "Impermax: MINT_AMOUNT_ZERO");
_mint(minter, mintTokens);
emit Mint(msg.sender, minter, mintAmount, mintTokens);
}
// this low-level function should be called from another contract
function redeem(address redeemer) external nonReentrant update returns (uint redeemAmount) {
uint redeemTokens = balanceOf[address(this)];
redeemAmount = redeemTokens.mul(exchangeRate()).div(1e18);
require(redeemAmount > 0, "Impermax: REDEEM_AMOUNT_ZERO");
require(redeemAmount <= totalBalance, "Impermax: INSUFFICIENT_CASH");
_burn(address(this), redeemTokens);
underlying.safeTransfer(redeemer, redeemAmount);
emit Redeem(msg.sender, redeemer, redeemAmount, redeemTokens);
}
// force real balance to match totalBalance
function skim(address to) external nonReentrant {
underlying.safeTransfer(to, underlying.myBalance().sub(totalBalance));
}
// force totalBalance to match real balance
function sync() external nonReentrant update {}
/*** Utilities ***/
// prevents a contract from calling itself, directly or indirectly.
bool internal _notEntered = true;
modifier nonReentrant() {
require(_notEntered, "Impermax: REENTERED");
_notEntered = false;
_;
_notEntered = true;
}
// update totalBalance with current balance
modifier update() {
_;
_update();
}
}{
"optimizer": {
"enabled": true,
"runs": 999999
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrowable","type":"address"}],"name":"AddBorrowable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrowable","type":"address"},{"indexed":false,"internalType":"uint256","name":"mintAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintTokens","type":"uint256"}],"name":"AllocateIntoBorrowable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrowable","type":"address"},{"indexed":false,"internalType":"uint256","name":"redeemAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redeemTokens","type":"uint256"}],"name":"DeallocateFromBorrowable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrowable","type":"address"}],"name":"DisableBorrowable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrowable","type":"address"}],"name":"EnableBorrowable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"mintAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintTokens","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newReserveFactor","type":"uint256"}],"name":"NewReserveFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"redeemer","type":"address"},{"indexed":false,"internalType":"uint256","name":"redeemAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redeemTokens","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrowable","type":"address"}],"name":"RemoveBorrowable","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalBalance","type":"uint256"}],"name":"Sync","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrowable","type":"address"},{"indexed":false,"internalType":"uint256","name":"underlyingBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"actualRedeemAmount","type":"uint256"}],"name":"UnwindBorrowable","type":"event"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MINIMUM_LIQUIDITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"RESERVE_FACTOR_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_underlying","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"name":"_initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"_setFactory","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newReserveFactor","type":"uint256"}],"name":"_setReserveFactor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"borrowable","type":"address"}],"name":"addBorrowable","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"borrowableInfo","outputs":[{"internalType":"bool","name":"enabled","type":"bool"},{"internalType":"bool","name":"exists","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"borrowables","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"borrowable","type":"address"}],"name":"disableBorrowable","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"borrowable","type":"address"}],"name":"enableBorrowable","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"exchangeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"exchangeRateLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBorrowablesLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"borrowable","type":"address"}],"name":"indexOfBorrowable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"mintTokens","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"reallocate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"redeemer","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"redeemAmount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"borrowable","type":"address"}],"name":"removeBorrowable","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"reserveFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"skim","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"sync","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"borrowable","type":"address"}],"name":"unwindBorrowable","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040526002805460ff19908116601217909155600b8054909116600117905567016345785d8a0000600f5561592f8061003b6000396000f3fe608060405234801561001057600080fd5b50600436106102925760003560e01c80637ecebe0011610160578063bc25cf77116100d8578063d505accf1161008c578063eb1ea9f411610071578063eb1ea9f414610891578063fca7820b146108c4578063fff6cae9146108e157610292565b8063d505accf146107f8578063dd62ed3e1461085657610292565b8063c45a0155116100bd578063c45a0155146107b5578063c5b7e148146107bd578063c72f3fbb146107f057610292565b8063bc25cf771461077a578063be340e32146107ad57610292565b806398084db71161012f578063ad7a672f11610114578063ad7a672f1461074d578063ade37c1314610755578063ba9a7a561461077257610292565b806398084db71461070c578063a9059cbb1461071457610292565b80637ecebe0014610696578063821beaf5146106c957806395a2251f146106d157806395d89b411461070457610292565b80633ba0b9a91161020e57806352ac4b02116101c25780636a627842116101a75780636a627842146105ff5780636f307dc31461063257806370a082311461066357610292565b806352ac4b021461057e578063579ce367146105b157610292565b80634643ec58116101f35780634643ec58146104645780634a5d316c14610543578063506fb0861461054b57610292565b80633ba0b9a9146104545780634322b7141461045c57610292565b806323b872dd11610265578063313ce5671161024a578063313ce567146103fb57806332fe35fd146104195780633644e5151461044c57610292565b806323b872dd146103b057806330adf81f146103f357610292565b806306fdde0314610297578063095ea7b31461031457806318160ddd14610361578063218b5b811461037b575b600080fd5b61029f6108e9565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102d95781810151838201526020016102c1565b50505050905090810190601f1680156103065780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61034d6004803603604081101561032a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610995565b604080519115158252519081900360200190f35b6103696109ac565b60408051918252519081900360200190f35b6103ae6004803603602081101561039157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166109b2565b005b61034d600480360360608110156103c657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610e68565b610369610f7d565b610403610fa1565b6040805160ff9092168252519081900360200190f35b6103ae6004803603602081101561042f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610faa565b6103696112fe565b610369611304565b610369611388565b6103ae6004803603606081101561047a57600080fd5b73ffffffffffffffffffffffffffffffffffffffff82351691908101906040810160208201356401000000008111156104b257600080fd5b8201836020820111156104c457600080fd5b803590602001918460018302840111640100000000831117156104e657600080fd5b91939092909160208101903564010000000081111561050457600080fd5b82018360208201111561051657600080fd5b8035906020019184600183028401116401000000008311171561053857600080fd5b50909250905061138e565b6103ae6114df565b6103696004803603602081101561056157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611590565b6103ae6004803603602081101561059457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611650565b6105e4600480360360208110156105c757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166119a0565b60408051921515835290151560208301528051918290030190f35b6103696004803603602081101561061557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166119be565b61063a611bfd565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6103696004803603602081101561067957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611c19565b610369600480360360208110156106ac57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611c2b565b610369611c3d565b610369600480360360208110156106e757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611c43565b61029f611e09565b6103ae611e81565b61034d6004803603604081101561072a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611f59565b610369611f66565b61063a6004803603602081101561076b57600080fd5b5035611f6c565b610369611fa0565b6103ae6004803603602081101561079057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611fa6565b6103696120cf565b61063a6120d5565b6103ae600480360360208110156107d357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166120f1565b6103696124a3565b6103ae600480360360e081101561080e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356124af565b6103696004803603604081101561086c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166124f3565b6103ae600480360360208110156108a757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612510565b6103ae600480360360208110156108da57600080fd5b5035612a15565b6103ae612ca2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561098d5780601f106109625761010080835404028352916020019161098d565b820191906000526020600020905b81548152906001019060200180831161097057829003601f168201915b505050505081565b60006109a2338484612d43565b5060015b92915050565b60035481565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015610a1a57600080fd5b505afa158015610a2e573d6000803e3d6000fd5b505050506040513d6020811015610a4457600080fd5b505173ffffffffffffffffffffffffffffffffffffffff163314610ac957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b600b5460ff16610b3a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600854604080517f6f307dc3000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff92831692841691636f307dc3916004808301926020929190829003018186803b158015610bcf57600080fd5b505afa158015610be3573d6000803e3d6000fd5b505050506040513d6020811015610bf957600080fd5b505173ffffffffffffffffffffffffffffffffffffffff1614610c67576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806158186022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d6020526040902054610100900460ff1615610ceb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806156c96021913960400191505060405180910390fd5b600c54600a11610d46576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806158d56026913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152600d602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff90911661010017166001908117909155600c8054918201815583527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180547fffffffffffffffffffffffff00000000000000000000000000000000000000001684179055517f3b94e6c56297c3ab2913d31d1c1adf8279146dbfb5624cc473e7af7a22d9c8469190a250600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b73ffffffffffffffffffffffffffffffffffffffff831660009081526005602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14610f6757604080518082018252601e81527f496d7065726d61783a205452414e534645525f4e4f545f414c4c4f574544000060208083019190915273ffffffffffffffffffffffffffffffffffffffff87166000908152600582528381203382529091529190912054610f3591849063ffffffff612db216565b73ffffffffffffffffffffffffffffffffffffffff851660009081526005602090815260408083203384529091529020555b610f72848484612e63565b5060015b9392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60025460ff1681565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561101257600080fd5b505afa158015611026573d6000803e3d6000fd5b505050506040513d602081101561103c57600080fd5b505173ffffffffffffffffffffffffffffffffffffffff1633146110c157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b600b5460ff1661113257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905573ffffffffffffffffffffffffffffffffffffffff81166000908152600d6020526040902054610100900460ff166111dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018061583a6028913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff161561125c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806156a76022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152600d602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f54ba33e4b0861b4d81b3384c3b5130b25b55df191223d9e48b317dc289fac3a99190a250600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b60065481565b60035460009081611325611316612f7c565b600a549063ffffffff612fe516565b9050811580611332575080155b1561134957670de0b6b3a764000092505050611385565b60006113738361136784670de0b6b3a764000063ffffffff61305916565b9063ffffffff6130cc16565b905061137f818461310e565b93505050505b90565b600f5481565b60095473ffffffffffffffffffffffffffffffffffffffff16331461141457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b61148784848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8801819004810282018101909252868152925086915085908190840183828082843760009201919091525061324092505050565b5050600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff94909416939093179092555050670de0b6b3a7640000600e55565b60095473ffffffffffffffffffffffffffffffffffffffff161561156457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496d7065726d61783a20464143544f52595f414c52454144595f534554000000604482015290519081900360640190fd5b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055565b6000805b600c548110156115f9578273ffffffffffffffffffffffffffffffffffffffff16600c82815481106115c257fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1614156115f157905061164b565b600101611594565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061570d6024913960400191505060405180910390fd5b919050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b1580156116b857600080fd5b505afa1580156116cc573d6000803e3d6000fd5b505050506040513d60208110156116e257600080fd5b505173ffffffffffffffffffffffffffffffffffffffff16331461176757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b600b5460ff166117d857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905573ffffffffffffffffffffffffffffffffffffffff81166000908152600d6020526040902054610100900460ff16611883576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018061583a6028913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16611901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806157316023913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152600d602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f6149acc591caf5f3d506cb615abb39ea3847de4e2aa83f4382531de216bdc6809190a250600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b600d6020526000908152604090205460ff8082169161010090041682565b600b5460009060ff16611a3257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600854600090611a7f9073ffffffffffffffffffffffffffffffffffffffff16613324565b90506000611a98600a54836133c690919063ffffffff16565b9050611abd611aa5611304565b61136783670de0b6b3a764000063ffffffff61305916565b925060035460001415611aeb57611adc836103e863ffffffff6133c616565b9250611aeb60006103e8613408565b60008311611b5a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656e64696e675661756c7456313a204d494e545f414d4f554e545f5a45524f604482015290519081900360640190fd5b611b648484613408565b611b6e60006134b9565b6040805182815260208101859052815173ffffffffffffffffffffffffffffffffffffffff87169233927f2f00e3cdd69a77be7ed215ec7b2a36784dd158f921fca79ac29deffa353fe6ee929081900390910190a35050611bcd613c21565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055919050565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b60046020526000908152604090205481565b60076020526000908152604090205481565b600c5490565b600b5460009060ff16611cb757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905530600090815260046020526040902054611d13670de0b6b3a7640000611367611d06611304565b849063ffffffff61305916565b915060008211611d6e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806158b36022913960400191505060405180910390fd5b611d783082613c7c565b611d81826134b9565b600854611dab9073ffffffffffffffffffffffffffffffffffffffff16848463ffffffff613d4016565b6040805183815260208101839052815173ffffffffffffffffffffffffffffffffffffffff86169233927f3f693fff038bb8a046aa76d9516190ac7444f7d69cf952c4cbdc086fdef2d6fc929081900390910190a350611bcd613c21565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561098d5780601f106109625761010080835404028352916020019161098d565b600b5460ff16611ef257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611f2460006134b9565b611f2c613c21565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b60006109a2338484612e63565b600a5481565b600c8181548110611f7957fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b6103e881565b600b5460ff1661201757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600a546008546120a191839161207b919061206f9073ffffffffffffffffffffffffffffffffffffffff16613324565b9063ffffffff6133c616565b60085473ffffffffffffffffffffffffffffffffffffffff16919063ffffffff613d4016565b50600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b600e5481565b60095473ffffffffffffffffffffffffffffffffffffffff1681565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561215957600080fd5b505afa15801561216d573d6000803e3d6000fd5b505050506040513d602081101561218357600080fd5b505173ffffffffffffffffffffffffffffffffffffffff16331461220857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b600b5460ff1661227957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905573ffffffffffffffffffffffffffffffffffffffff81166000908152600d6020526040902054610100900460ff16612324576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018061583a6028913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16156123a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806156a76022913960400191505060405180910390fd5b60006123c48273ffffffffffffffffffffffffffffffffffffffff16613f1d565b90506000811161243557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4c656e64696e675661756c7456313a205a45524f5f414d4f554e540000000000604482015290519081900360640190fd5b60006124418383613fd1565b90508273ffffffffffffffffffffffffffffffffffffffff167f05750bc9042b6da04fdebec7b024caed5c2e2b35c707bd1fde571f31cdaeb5668383604051808381526020018281526020019250505060405180910390a250506120a1613c21565b670c7d713b49da000081565b6124df878787878787877f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9614051565b6124ea878787612d43565b50505050505050565b600560209081526000928352604080842090915290825290205481565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561257857600080fd5b505afa15801561258c573d6000803e3d6000fd5b505050506040513d60208110156125a257600080fd5b505173ffffffffffffffffffffffffffffffffffffffff16331461262757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b600b5460ff1661269857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905573ffffffffffffffffffffffffffffffffffffffff81166000908152600d6020526040902054610100900460ff16612743576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018061583a6028913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16156127c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806156a76022913960400191505060405180910390fd5b6127e873ffffffffffffffffffffffffffffffffffffffff82163063ffffffff6142f416565b1561285457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4c656e64696e675661756c7456313a204e4f545f454d50545900000000000000604482015290519081900360640190fd5b600c547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600061288483611590565b9050600c828154811061289357fe5b600091825260209091200154600c805473ffffffffffffffffffffffffffffffffffffffff90921691839081106128c657fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600c80548061291957fe5b6000828152602080822083017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905590920190925573ffffffffffffffffffffffffffffffffffffffff8516808352600d909152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690555190917f1f537c1571c0e7fa29083762436cadb3e57564c0f78e857e498cf428124c710e91a25050600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905550565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015612a7d57600080fd5b505afa158015612a91573d6000803e3d6000fd5b505050506040513d6020811015612aa757600080fd5b505173ffffffffffffffffffffffffffffffffffffffff163314612b2c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b600b5460ff16612b9d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055670c7d713b49da0000811115612c3c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4c656e64696e675661756c7456313a20494e56414c49445f53455454494e4700604482015290519081900360640190fd5b600f8190556040805182815290517f9d9cd27245b4e6b06dcf523ac57b6e851b934e199eee376313f906e94bfbfd559181900360200190a150600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b600b5460ff16612d1357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611f2c613c21565b73ffffffffffffffffffffffffffffffffffffffff808416600081815260056020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60008184841115612e5b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612e20578181015183820152602001612e08565b50505050905090810190601f168015612e4d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b604080518082018252601b81527f496d7065726d61783a205452414e534645525f544f4f5f48494748000000000060208083019190915273ffffffffffffffffffffffffffffffffffffffff8616600090815260049091529190912054612ed191839063ffffffff612db216565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600460205260408082209390935590841681522054612f13908263ffffffff612fe516565b73ffffffffffffffffffffffffffffffffffffffff80841660008181526004602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000805b600c54811015612fe1576000600c8281548110612f9957fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050612fd6612fc982613f1d565b849063ffffffff612fe516565b925050600101612f80565b5090565b600082820183811015610f7657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082613068575060006109a6565b8282028284828161307557fe5b0414610f76576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806157d16021913960400191505060405180910390fd5b6000610f7683836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506143a6565b600e546000908084111561323757600061315f613152670de0b6b3a7640000611367600f54613146878b6133c690919063ffffffff16565b9063ffffffff61305916565b869063ffffffff6133c616565b9050600061317b8561206f84611367838b63ffffffff61305916565b9050801561322857600954604080517f345ef941000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163345ef941916004808301926020929190829003018186803b1580156131ee57600080fd5b505afa158015613202573d6000803e3d6000fd5b505050506040513d602081101561321857600080fd5b505190506132268183613408565b505b50600e81905591506109a69050565b839150506109a6565b8151613253906000906020850190615573565b508051613267906001906020840190615573565b50604051469080605261577f82396040805191829003605201822086516020978801208383018352600184527f310000000000000000000000000000000000000000000000000000000000000093880193909352815180880191909152808201929092527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6606083015260808201939093523060a0808301919091528351808303909101815260c090910190925250805192019190912060065550565b604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009173ffffffffffffffffffffffffffffffffffffffff8416916370a0823191602480820192602092909190829003018186803b15801561339457600080fd5b505afa1580156133a8573d6000803e3d6000fd5b505050506040513d60208110156133be57600080fd5b505192915050565b6000610f7683836040518060400160405280601f81526020017f536166654d6174683a207375627472616374696f6e20756e646572666c6f7700815250612db2565b60035461341b908263ffffffff612fe516565b60035573ffffffffffffffffffffffffffffffffffffffff8216600090815260046020526040902054613454908263ffffffff612fe516565b73ffffffffffffffffffffffffffffffffffffffff831660008181526004602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b600c5460408051828152602080840282010190915260609180156134f757816020015b6134e46155ed565b8152602001906001900390816134dc5790505b50600c5490915060005b600c548110156135f257600d6000600c838154811061351c57fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff1661357f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909101906135ea565b600c54600090613595908463ffffffff6133c616565b90506135cf600c83815481106135a757fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1630614425565b84828403815181106135dd57fe5b6020026020010181905250505b600101613501565b506008546000906136189073ffffffffffffffffffffffffffffffffffffffff16613324565b905060005b8281101561367c57600061364385838151811061363657fe5b60200260200101516149b4565b865187908590811061365157fe5b60209081029190910101919091529050613671838263ffffffff612fe516565b92505060010161361d565b506136a8846040518060600160405280602681526020016157f26026913983919063ffffffff612db216565b905060005b600183038110156137825760005b816001850303811015613779576137048582600101815181106136da57fe5b60200260200101518683815181106136ee57fe5b6020026020010151614a1990919063ffffffff16565b613771576137106155ed565b85828151811061371c57fe5b6020026020010151905085826001018151811061373557fe5b602002602001015186838151811061374957fe5b60200260200101819052508086836001018151811061376457fe5b6020026020010181905250505b6001016136bb565b506001016136ad565b508160015b8381101561395e57600085828151811061379d57fe5b60200260200101516101400151905060008090506060836040519080825280602002602001820160405280156137dd578160200160208202803883390190505b509050826137f05783945050505061395e565b60005b8481101561388d578389828151811061380857fe5b602002602001015161014001511161381f5761388d565b613845848a838151811061382f57fe5b6020026020010151614a2790919063ffffffff16565b82828151811061385157fe5b60200260200101818152505061388382828151811061386c57fe5b602002602001015184612fe590919063ffffffff16565b92506001016137f3565b50858211156138a15783945050505061395e565b60005b8481101561394e578181815181106138b857fe5b6020026020010151600014156138cd57613946565b6139068282815181106138dc57fe5b60200260200101518a83815181106138f057fe5b6020026020010151614bdd90919063ffffffff16565b89828151811061391257fe5b602002602001018190525061394382828151811061392c57fe5b6020026020010151886133c690919063ffffffff16565b96505b6001016138a4565b5050600190920191506137879050565b50600082815b838110156139955761398b612fc988838151811061397e57fe5b6020026020010151614c15565b9250600101613964565b5060005b83811015613a165760008084116139b057856139c7565b6139c784611367856131468c878151811061397e57fe5b9050858111156139d45750845b6139e4818984815181106138f057fe5b8883815181106139f057fe5b6020908102919091010152613a0b868263ffffffff6133c616565b955050600101613999565b5060005b85811015613ae157868181518110613a2e57fe5b602002602001015160800151878281518110613a4657fe5b602002602001015160a001511015613ad9576000613a9b888381518110613a6957fe5b602002602001015160a00151898481518110613a8157fe5b6020026020010151608001516133c690919063ffffffff16565b9050613ad6888381518110613aac57fe5b602002602001015160000151828a8581518110613ac557fe5b602002602001015160200151614c32565b50505b600101613a1a565b50613b2e876040518060600160405280602b8152602001615754602b9139600854613b219073ffffffffffffffffffffffffffffffffffffffff16613324565b919063ffffffff612db216565b935060005b85811015613c1757868181518110613b4757fe5b602002602001015160800151878281518110613b5f57fe5b602002602001015160a001511115613c0f576000613bb4888381518110613b8257fe5b602002602001015160800151898481518110613b9a57fe5b602002602001015160a001516133c690919063ffffffff16565b905085811115613bc15750845b613bd1868263ffffffff6133c616565b9550613c0c888381518110613be257fe5b602002602001015160000151828a8581518110613bfb57fe5b602002602001015160200151614c50565b50505b600101613b33565b5050505050505050565b600854613c439073ffffffffffffffffffffffffffffffffffffffff16613324565b600a81905560408051918252517f8a0df8ef054fae2c3d2d19a7b322e864870cc9fd3cb07fb9526309c596244bf49181900360200190a1565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260046020526040902054613cb2908263ffffffff6133c616565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260046020526040902055600354613ceb908263ffffffff6133c616565b60035560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000178152925182516000946060949389169392918291908083835b60208310613e1657805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613dd9565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613e78576040519150601f19603f3d011682016040523d82523d6000602084013e613e7d565b606091505b5091509150818015613eab575080511580613eab5750808060200190516020811015613ea857600080fd5b50515b613f1657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f21736166655472616e7366657200000000000000000000000000000000000000604482015290519081900360640190fd5b5050505050565b60006109a6828373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015613fa057600080fd5b505afa158015613fb4573d6000803e3d6000fd5b505050506040513d6020811015613fca57600080fd5b5051614d9e565b6000610f7683838573ffffffffffffffffffffffffffffffffffffffff16633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561402057600080fd5b505af1158015614034573d6000803e3d6000fd5b505050506040513d602081101561404a57600080fd5b5051614c32565b428510156140c057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496d7065726d61783a2045585049524544000000000000000000000000000000604482015290519081900360640190fd5b60065473ffffffffffffffffffffffffffffffffffffffff808a1660008181526007602090815260408083208054600180820190925582518085018a905280840196909652958e166060860152608085018d905260a085019590955260c08085018c90528151808603909101815260e0850182528051908301207f19010000000000000000000000000000000000000000000000000000000000006101008601526101028501969096526101228085019690965280518085039096018652610142840180825286519683019690962095839052610162840180825286905260ff8a166101828501526101a284018990526101c28401889052519193926101e2808201937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019281900390910190855afa158015614202573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81161580159061427d57508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b6142e857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496d7065726d61783a20494e56414c49445f5349474e41545552450000000000604482015290519081900360640190fd5b50505050505050505050565b60008273ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561437357600080fd5b505afa158015614387573d6000803e3d6000fd5b505050506040513d602081101561439d57600080fd5b50519392505050565b6000818361440f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315612e20578181015183820152602001612e08565b50600083858161441b57fe5b0495945050505050565b61442d6155ed565b8273ffffffffffffffffffffffffffffffffffffffff1663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561447557600080fd5b505af1158015614489573d6000803e3d6000fd5b5050505060008373ffffffffffffffffffffffffffffffffffffffff16633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156144d757600080fd5b505af11580156144eb573d6000803e3d6000fd5b505050506040513d602081101561450157600080fd5b5051604080517f18160ddd000000000000000000000000000000000000000000000000000000008152905191925060009173ffffffffffffffffffffffffffffffffffffffff8716916318160ddd916004808301926020929190829003018186803b15801561456f57600080fd5b505afa158015614583573d6000803e3d6000fd5b505050506040513d602081101561459957600080fd5b5051604080517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301529151929350600092918816916370a0823191602480820192602092909190829003018186803b15801561461157600080fd5b505afa158015614625573d6000803e3d6000fd5b505050506040513d602081101561463b57600080fd5b505190506000614651838363ffffffff6133c616565b90506040518061016001604052808873ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018873ffffffffffffffffffffffffffffffffffffffff166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b1580156146c757600080fd5b505afa1580156146db573d6000803e3d6000fd5b505050506040513d60208110156146f157600080fd5b50518152602001614714670de0b6b3a7640000611367858963ffffffff61305916565b8152602001614735670de0b6b3a7640000611367868963ffffffff61305916565b8152602001614756670de0b6b3a7640000611367868963ffffffff61305916565b81526020018873ffffffffffffffffffffffffffffffffffffffff166391b427456040518163ffffffff1660e01b815260040160206040518083038186803b1580156147a157600080fd5b505afa1580156147b5573d6000803e3d6000fd5b505050506040513d60208110156147cb57600080fd5b50518152604080517f1aebf12f000000000000000000000000000000000000000000000000000000008152905160209283019273ffffffffffffffffffffffffffffffffffffffff8c1692631aebf12f9260048083019392829003018186803b15801561483757600080fd5b505afa15801561484b573d6000803e3d6000fd5b505050506040513d602081101561486157600080fd5b50518152604080517f4322b714000000000000000000000000000000000000000000000000000000008152905160209283019273ffffffffffffffffffffffffffffffffffffffff8c1692634322b7149260048083019392829003018186803b1580156148cd57600080fd5b505afa1580156148e1573d6000803e3d6000fd5b505050506040513d60208110156148f757600080fd5b50518152604080517f5b2b9d1a000000000000000000000000000000000000000000000000000000008152905160209283019273ffffffffffffffffffffffffffffffffffffffff8c1692635b2b9d1a9260048083019392829003018186803b15801561496357600080fd5b505afa158015614977573d6000803e3d6000fd5b505050506040513d602081101561498d57600080fd5b50518152600060209091015294506149a485614e33565b6101408601525050505092915050565b6149bc6155ed565b600082604001516149cc84614c15565b10156149dd57508190506000614a14565b60006149f0846040015161206f86614c15565b90506000614a028560a0015183614f33565b9050614a0e8582614f49565b93509150505b915091565b610140908101519101511190565b6000808211614a9757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4552524f523a2072617465203d20300000000000000000000000000000000000604482015290519081900360640190fd5b826101400151821115614b0b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4552524f523a205441524745542052415445203e204341434845442052415445604482015290519081900360640190fd5b6000614b178484615009565b9050614b22846151e4565b811115614b7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615678602f913960400191505060405180910390fd5b6000614b9f82611367670de0b6b3a7640000886040015161305990919063ffffffff16565b9050614bd4614bad86614c15565b6040518060600160405280602381526020016158906023913983919063ffffffff612db216565b95945050505050565b614be56155ed565b60a0830151614bfa908363ffffffff612fe516565b60a0840152614c0883614e33565b6101408401525090919050565b60006109a68260a001518360600151612fe590919063ffffffff16565b6000614c4884614c428585615224565b84615232565b949350505050565b6000614c6e8261136785670de0b6b3a764000063ffffffff61305916565b905080614c7d57506000610f76565b600854614ca79073ffffffffffffffffffffffffffffffffffffffff16858563ffffffff613d4016565b604080517f6a627842000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff861691636a6278429160248083019260209291908290030181600087803b158015614d1557600080fd5b505af1158015614d29573d6000803e3d6000fd5b505050506040513d6020811015614d3f57600080fd5b50516040805185815260208101839052815192935073ffffffffffffffffffffffffffffffffffffffff8716927f20541ba081e1e2ed9b41701070442c1fe618b0fec04825ba790aea8373f4e237929181900390910190a29392505050565b6000808373ffffffffffffffffffffffffffffffffffffffff16633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614de957600080fd5b505af1158015614dfd573d6000803e3d6000fd5b505050506040513d6020811015614e1357600080fd5b50519050614c48670de0b6b3a7640000611367858463ffffffff61305916565b600080614e3f836151e4565b90506000614e668460e00151611367670de0b6b3a76400008561305990919063ffffffff16565b905060008460e00151831015614e7d575080614efe565b6000614ec4614ea18760e00151670de0b6b3a76400006133c690919063ffffffff16565b611367670de0b6b3a76400006131468a60e00151896133c690919063ffffffff16565b9050614efa670de0b6b3a7640000614eee611d0660018a61012001516133c690919063ffffffff16565b9063ffffffff612fe516565b9150505b614bd4670de0b6b3a764000061136784613146670de0b6b3a7640000611367614f268c61541b565b889063ffffffff61305916565b6000818310614f425781610f76565b5090919050565b614f516155ed565b6000614f7d84604001516040518060600160405280602381526020016156ea60239139613b2187614c15565b905080831115614fd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615862602e913960400191505060405180910390fd5b60a0840151614fed908463ffffffff6133c616565b60a0850152614ffb84614e33565b610140850152509192915050565b60006150148361541b565b821161506d57615066670de0b6b3a76400006113678560e00151613146615061670de0b6b3a76400006131466150498b61541b565b6113678b670de0b6b3a764000063ffffffff61305916565b615473565b905061516d565b61012083015160009061508790600163ffffffff6133c616565b905060006150b3670de0b6b3a764000061206f8761012001518860e0015161305990919063ffffffff16565b905060006151086150c38761541b565b6113676150e58960e00151670de0b6b3a76400006133c690919063ffffffff16565b613146670de0b6b3a76400006113678c60e001518c61305990919063ffffffff16565b9050600061514d615061670de0b6b3a76400006131466151316004828a8963ffffffff61305916565b614eee670de0b6b3a76400006113678a8063ffffffff61305916565b905061516660026113678681858863ffffffff612fe516565b9450505050505b670de0b6b3a76400008111156109a657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4552524f523a20544152474554205554494c495a4154494f4e203e2031303025604482015290519081900360640190fd5b6000806151f083614c15565b90508061520157600091505061164b565b610f7681611367670de0b6b3a7640000866040015161305990919063ffffffff16565b6000610f76838360006154c4565b6000615250670de0b6b3a7640000611367858563ffffffff61305916565b90508061525f57506000610f76565b60008473ffffffffffffffffffffffffffffffffffffffff1663ad7a672f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156152a757600080fd5b505afa1580156152bb573d6000803e3d6000fd5b505050506040513d60208110156152d157600080fd5b50519050808211156152fc576152f98361136783670de0b6b3a764000063ffffffff61305916565b93505b61532373ffffffffffffffffffffffffffffffffffffffff8616868663ffffffff613d4016565b604080517f95a2251f000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff8716916395a2251f9160248083019260209291908290030181600087803b15801561539157600080fd5b505af11580156153a5573d6000803e3d6000fd5b505050506040513d60208110156153bb57600080fd5b50516040805182815260208101879052815192945073ffffffffffffffffffffffffffffffffffffffff8816927f8d69ef09150dd510133bc8e54e6ca115e8cf3370ea49a4a5ae56a1cdefc835e9929181900390910190a2509392505050565b60006109a6670de0b6b3a764000061136761544c856101000151670de0b6b3a76400006133c690919063ffffffff16565b613146670de0b6b3a76400006113678860c001518960e0015161305990919063ffffffff16565b600060038211156154b6575080600160028204015b818110156154b05780915060028182858161549f57fe5b0401816154a857fe5b049050615488565b5061164b565b811561164b57506001919050565b6000806154e38461136787670de0b6b3a764000063ffffffff61305916565b905060006154f882600163ffffffff612fe516565b9050831561553a57600061551e670de0b6b3a7640000611367848963ffffffff61305916565b90508681111561552e5782615530565b815b9350505050610f76565b6000615558670de0b6b3a7640000611367858963ffffffff61305916565b9050868110156155685781615530565b829350505050610f76565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106155b457805160ff19168380011785556155e1565b828001600101855582156155e1579182015b828111156155e15782518255916020019190600101906155c6565b50612fe192915061565d565b604051806101600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61138591905b80821115612fe1576000815560010161566356fe4552524f523a20544152474554205554494c495a4154494f4e203e2043555252454e54205554494c495a4154494f4e4c656e64696e675661756c7456313a20424f52524f5741424c455f454e41424c45444c656e64696e675661756c7456313a20424f52524f5741424c455f4558495354534552524f523a204e4547415449564520415641494c41424c45204c49515549444954594c656e64696e675661756c7456313a20424f52524f5741424c455f4e4f545f464f554e444c656e64696e675661756c7456313a20424f52524f5741424c455f44495341424c45444c656e64696e675661756c7456313a204e4547415449564520414d4f554e5420544f20414c4c4f43415445454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774c656e64696e675661756c7456313a20494e53554646494349454e545f4c49515549444954594c656e64696e675661756c7456313a20494e56414c49445f554e4445524c59494e474c656e64696e675661756c7456313a20424f52524f5741424c455f444f45534e545f4558495354534552524f523a204445414c4c4f4341544520414d4f554e54203e20415641494c41424c45204c49515549444954594552524f523a2054415247455420535550504c59203e20544f54414c20535550504c594c656e64696e675661756c7456313a2052454445454d5f414d4f554e545f5a45524f4c656e64696e675661756c7456313a204d41585f424f52524f5741424c45535f4c454e475448a265627a7a72315820272b1ff2f5bdfb5ffe4ff85e7b931a1776d5924d30728d423cc60a2c786295d764736f6c63430005100032
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102925760003560e01c80637ecebe0011610160578063bc25cf77116100d8578063d505accf1161008c578063eb1ea9f411610071578063eb1ea9f414610891578063fca7820b146108c4578063fff6cae9146108e157610292565b8063d505accf146107f8578063dd62ed3e1461085657610292565b8063c45a0155116100bd578063c45a0155146107b5578063c5b7e148146107bd578063c72f3fbb146107f057610292565b8063bc25cf771461077a578063be340e32146107ad57610292565b806398084db71161012f578063ad7a672f11610114578063ad7a672f1461074d578063ade37c1314610755578063ba9a7a561461077257610292565b806398084db71461070c578063a9059cbb1461071457610292565b80637ecebe0014610696578063821beaf5146106c957806395a2251f146106d157806395d89b411461070457610292565b80633ba0b9a91161020e57806352ac4b02116101c25780636a627842116101a75780636a627842146105ff5780636f307dc31461063257806370a082311461066357610292565b806352ac4b021461057e578063579ce367146105b157610292565b80634643ec58116101f35780634643ec58146104645780634a5d316c14610543578063506fb0861461054b57610292565b80633ba0b9a9146104545780634322b7141461045c57610292565b806323b872dd11610265578063313ce5671161024a578063313ce567146103fb57806332fe35fd146104195780633644e5151461044c57610292565b806323b872dd146103b057806330adf81f146103f357610292565b806306fdde0314610297578063095ea7b31461031457806318160ddd14610361578063218b5b811461037b575b600080fd5b61029f6108e9565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102d95781810151838201526020016102c1565b50505050905090810190601f1680156103065780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61034d6004803603604081101561032a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610995565b604080519115158252519081900360200190f35b6103696109ac565b60408051918252519081900360200190f35b6103ae6004803603602081101561039157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166109b2565b005b61034d600480360360608110156103c657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610e68565b610369610f7d565b610403610fa1565b6040805160ff9092168252519081900360200190f35b6103ae6004803603602081101561042f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610faa565b6103696112fe565b610369611304565b610369611388565b6103ae6004803603606081101561047a57600080fd5b73ffffffffffffffffffffffffffffffffffffffff82351691908101906040810160208201356401000000008111156104b257600080fd5b8201836020820111156104c457600080fd5b803590602001918460018302840111640100000000831117156104e657600080fd5b91939092909160208101903564010000000081111561050457600080fd5b82018360208201111561051657600080fd5b8035906020019184600183028401116401000000008311171561053857600080fd5b50909250905061138e565b6103ae6114df565b6103696004803603602081101561056157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611590565b6103ae6004803603602081101561059457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611650565b6105e4600480360360208110156105c757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166119a0565b60408051921515835290151560208301528051918290030190f35b6103696004803603602081101561061557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166119be565b61063a611bfd565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6103696004803603602081101561067957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611c19565b610369600480360360208110156106ac57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611c2b565b610369611c3d565b610369600480360360208110156106e757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611c43565b61029f611e09565b6103ae611e81565b61034d6004803603604081101561072a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611f59565b610369611f66565b61063a6004803603602081101561076b57600080fd5b5035611f6c565b610369611fa0565b6103ae6004803603602081101561079057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611fa6565b6103696120cf565b61063a6120d5565b6103ae600480360360208110156107d357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166120f1565b6103696124a3565b6103ae600480360360e081101561080e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356124af565b6103696004803603604081101561086c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166124f3565b6103ae600480360360208110156108a757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612510565b6103ae600480360360208110156108da57600080fd5b5035612a15565b6103ae612ca2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561098d5780601f106109625761010080835404028352916020019161098d565b820191906000526020600020905b81548152906001019060200180831161097057829003601f168201915b505050505081565b60006109a2338484612d43565b5060015b92915050565b60035481565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015610a1a57600080fd5b505afa158015610a2e573d6000803e3d6000fd5b505050506040513d6020811015610a4457600080fd5b505173ffffffffffffffffffffffffffffffffffffffff163314610ac957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b600b5460ff16610b3a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600854604080517f6f307dc3000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff92831692841691636f307dc3916004808301926020929190829003018186803b158015610bcf57600080fd5b505afa158015610be3573d6000803e3d6000fd5b505050506040513d6020811015610bf957600080fd5b505173ffffffffffffffffffffffffffffffffffffffff1614610c67576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806158186022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d6020526040902054610100900460ff1615610ceb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806156c96021913960400191505060405180910390fd5b600c54600a11610d46576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806158d56026913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152600d602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff90911661010017166001908117909155600c8054918201815583527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180547fffffffffffffffffffffffff00000000000000000000000000000000000000001684179055517f3b94e6c56297c3ab2913d31d1c1adf8279146dbfb5624cc473e7af7a22d9c8469190a250600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b73ffffffffffffffffffffffffffffffffffffffff831660009081526005602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14610f6757604080518082018252601e81527f496d7065726d61783a205452414e534645525f4e4f545f414c4c4f574544000060208083019190915273ffffffffffffffffffffffffffffffffffffffff87166000908152600582528381203382529091529190912054610f3591849063ffffffff612db216565b73ffffffffffffffffffffffffffffffffffffffff851660009081526005602090815260408083203384529091529020555b610f72848484612e63565b5060015b9392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60025460ff1681565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561101257600080fd5b505afa158015611026573d6000803e3d6000fd5b505050506040513d602081101561103c57600080fd5b505173ffffffffffffffffffffffffffffffffffffffff1633146110c157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b600b5460ff1661113257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905573ffffffffffffffffffffffffffffffffffffffff81166000908152600d6020526040902054610100900460ff166111dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018061583a6028913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff161561125c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806156a76022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152600d602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f54ba33e4b0861b4d81b3384c3b5130b25b55df191223d9e48b317dc289fac3a99190a250600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b60065481565b60035460009081611325611316612f7c565b600a549063ffffffff612fe516565b9050811580611332575080155b1561134957670de0b6b3a764000092505050611385565b60006113738361136784670de0b6b3a764000063ffffffff61305916565b9063ffffffff6130cc16565b905061137f818461310e565b93505050505b90565b600f5481565b60095473ffffffffffffffffffffffffffffffffffffffff16331461141457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b61148784848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8801819004810282018101909252868152925086915085908190840183828082843760009201919091525061324092505050565b5050600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff94909416939093179092555050670de0b6b3a7640000600e55565b60095473ffffffffffffffffffffffffffffffffffffffff161561156457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496d7065726d61783a20464143544f52595f414c52454144595f534554000000604482015290519081900360640190fd5b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055565b6000805b600c548110156115f9578273ffffffffffffffffffffffffffffffffffffffff16600c82815481106115c257fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1614156115f157905061164b565b600101611594565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061570d6024913960400191505060405180910390fd5b919050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b1580156116b857600080fd5b505afa1580156116cc573d6000803e3d6000fd5b505050506040513d60208110156116e257600080fd5b505173ffffffffffffffffffffffffffffffffffffffff16331461176757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b600b5460ff166117d857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905573ffffffffffffffffffffffffffffffffffffffff81166000908152600d6020526040902054610100900460ff16611883576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018061583a6028913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16611901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806157316023913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152600d602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f6149acc591caf5f3d506cb615abb39ea3847de4e2aa83f4382531de216bdc6809190a250600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b600d6020526000908152604090205460ff8082169161010090041682565b600b5460009060ff16611a3257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600854600090611a7f9073ffffffffffffffffffffffffffffffffffffffff16613324565b90506000611a98600a54836133c690919063ffffffff16565b9050611abd611aa5611304565b61136783670de0b6b3a764000063ffffffff61305916565b925060035460001415611aeb57611adc836103e863ffffffff6133c616565b9250611aeb60006103e8613408565b60008311611b5a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656e64696e675661756c7456313a204d494e545f414d4f554e545f5a45524f604482015290519081900360640190fd5b611b648484613408565b611b6e60006134b9565b6040805182815260208101859052815173ffffffffffffffffffffffffffffffffffffffff87169233927f2f00e3cdd69a77be7ed215ec7b2a36784dd158f921fca79ac29deffa353fe6ee929081900390910190a35050611bcd613c21565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055919050565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b60046020526000908152604090205481565b60076020526000908152604090205481565b600c5490565b600b5460009060ff16611cb757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905530600090815260046020526040902054611d13670de0b6b3a7640000611367611d06611304565b849063ffffffff61305916565b915060008211611d6e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806158b36022913960400191505060405180910390fd5b611d783082613c7c565b611d81826134b9565b600854611dab9073ffffffffffffffffffffffffffffffffffffffff16848463ffffffff613d4016565b6040805183815260208101839052815173ffffffffffffffffffffffffffffffffffffffff86169233927f3f693fff038bb8a046aa76d9516190ac7444f7d69cf952c4cbdc086fdef2d6fc929081900390910190a350611bcd613c21565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561098d5780601f106109625761010080835404028352916020019161098d565b600b5460ff16611ef257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611f2460006134b9565b611f2c613c21565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b60006109a2338484612e63565b600a5481565b600c8181548110611f7957fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b6103e881565b600b5460ff1661201757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600a546008546120a191839161207b919061206f9073ffffffffffffffffffffffffffffffffffffffff16613324565b9063ffffffff6133c616565b60085473ffffffffffffffffffffffffffffffffffffffff16919063ffffffff613d4016565b50600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b600e5481565b60095473ffffffffffffffffffffffffffffffffffffffff1681565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561215957600080fd5b505afa15801561216d573d6000803e3d6000fd5b505050506040513d602081101561218357600080fd5b505173ffffffffffffffffffffffffffffffffffffffff16331461220857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b600b5460ff1661227957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905573ffffffffffffffffffffffffffffffffffffffff81166000908152600d6020526040902054610100900460ff16612324576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018061583a6028913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16156123a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806156a76022913960400191505060405180910390fd5b60006123c48273ffffffffffffffffffffffffffffffffffffffff16613f1d565b90506000811161243557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4c656e64696e675661756c7456313a205a45524f5f414d4f554e540000000000604482015290519081900360640190fd5b60006124418383613fd1565b90508273ffffffffffffffffffffffffffffffffffffffff167f05750bc9042b6da04fdebec7b024caed5c2e2b35c707bd1fde571f31cdaeb5668383604051808381526020018281526020019250505060405180910390a250506120a1613c21565b670c7d713b49da000081565b6124df878787878787877f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9614051565b6124ea878787612d43565b50505050505050565b600560209081526000928352604080842090915290825290205481565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561257857600080fd5b505afa15801561258c573d6000803e3d6000fd5b505050506040513d60208110156125a257600080fd5b505173ffffffffffffffffffffffffffffffffffffffff16331461262757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b600b5460ff1661269857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905573ffffffffffffffffffffffffffffffffffffffff81166000908152600d6020526040902054610100900460ff16612743576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018061583a6028913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16156127c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806156a76022913960400191505060405180910390fd5b6127e873ffffffffffffffffffffffffffffffffffffffff82163063ffffffff6142f416565b1561285457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4c656e64696e675661756c7456313a204e4f545f454d50545900000000000000604482015290519081900360640190fd5b600c547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600061288483611590565b9050600c828154811061289357fe5b600091825260209091200154600c805473ffffffffffffffffffffffffffffffffffffffff90921691839081106128c657fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600c80548061291957fe5b6000828152602080822083017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905590920190925573ffffffffffffffffffffffffffffffffffffffff8516808352600d909152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690555190917f1f537c1571c0e7fa29083762436cadb3e57564c0f78e857e498cf428124c710e91a25050600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905550565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015612a7d57600080fd5b505afa158015612a91573d6000803e3d6000fd5b505050506040513d6020811015612aa757600080fd5b505173ffffffffffffffffffffffffffffffffffffffff163314612b2c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4c656e64696e675661756c7456313a20554e415554484f52495a454400000000604482015290519081900360640190fd5b600b5460ff16612b9d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055670c7d713b49da0000811115612c3c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4c656e64696e675661756c7456313a20494e56414c49445f53455454494e4700604482015290519081900360640190fd5b600f8190556040805182815290517f9d9cd27245b4e6b06dcf523ac57b6e851b934e199eee376313f906e94bfbfd559181900360200190a150600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b600b5460ff16612d1357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496d7065726d61783a205245454e544552454400000000000000000000000000604482015290519081900360640190fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611f2c613c21565b73ffffffffffffffffffffffffffffffffffffffff808416600081815260056020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60008184841115612e5b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612e20578181015183820152602001612e08565b50505050905090810190601f168015612e4d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b604080518082018252601b81527f496d7065726d61783a205452414e534645525f544f4f5f48494748000000000060208083019190915273ffffffffffffffffffffffffffffffffffffffff8616600090815260049091529190912054612ed191839063ffffffff612db216565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600460205260408082209390935590841681522054612f13908263ffffffff612fe516565b73ffffffffffffffffffffffffffffffffffffffff80841660008181526004602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000805b600c54811015612fe1576000600c8281548110612f9957fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050612fd6612fc982613f1d565b849063ffffffff612fe516565b925050600101612f80565b5090565b600082820183811015610f7657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082613068575060006109a6565b8282028284828161307557fe5b0414610f76576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806157d16021913960400191505060405180910390fd5b6000610f7683836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506143a6565b600e546000908084111561323757600061315f613152670de0b6b3a7640000611367600f54613146878b6133c690919063ffffffff16565b9063ffffffff61305916565b869063ffffffff6133c616565b9050600061317b8561206f84611367838b63ffffffff61305916565b9050801561322857600954604080517f345ef941000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163345ef941916004808301926020929190829003018186803b1580156131ee57600080fd5b505afa158015613202573d6000803e3d6000fd5b505050506040513d602081101561321857600080fd5b505190506132268183613408565b505b50600e81905591506109a69050565b839150506109a6565b8151613253906000906020850190615573565b508051613267906001906020840190615573565b50604051469080605261577f82396040805191829003605201822086516020978801208383018352600184527f310000000000000000000000000000000000000000000000000000000000000093880193909352815180880191909152808201929092527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6606083015260808201939093523060a0808301919091528351808303909101815260c090910190925250805192019190912060065550565b604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009173ffffffffffffffffffffffffffffffffffffffff8416916370a0823191602480820192602092909190829003018186803b15801561339457600080fd5b505afa1580156133a8573d6000803e3d6000fd5b505050506040513d60208110156133be57600080fd5b505192915050565b6000610f7683836040518060400160405280601f81526020017f536166654d6174683a207375627472616374696f6e20756e646572666c6f7700815250612db2565b60035461341b908263ffffffff612fe516565b60035573ffffffffffffffffffffffffffffffffffffffff8216600090815260046020526040902054613454908263ffffffff612fe516565b73ffffffffffffffffffffffffffffffffffffffff831660008181526004602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b600c5460408051828152602080840282010190915260609180156134f757816020015b6134e46155ed565b8152602001906001900390816134dc5790505b50600c5490915060005b600c548110156135f257600d6000600c838154811061351c57fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff1661357f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909101906135ea565b600c54600090613595908463ffffffff6133c616565b90506135cf600c83815481106135a757fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1630614425565b84828403815181106135dd57fe5b6020026020010181905250505b600101613501565b506008546000906136189073ffffffffffffffffffffffffffffffffffffffff16613324565b905060005b8281101561367c57600061364385838151811061363657fe5b60200260200101516149b4565b865187908590811061365157fe5b60209081029190910101919091529050613671838263ffffffff612fe516565b92505060010161361d565b506136a8846040518060600160405280602681526020016157f26026913983919063ffffffff612db216565b905060005b600183038110156137825760005b816001850303811015613779576137048582600101815181106136da57fe5b60200260200101518683815181106136ee57fe5b6020026020010151614a1990919063ffffffff16565b613771576137106155ed565b85828151811061371c57fe5b6020026020010151905085826001018151811061373557fe5b602002602001015186838151811061374957fe5b60200260200101819052508086836001018151811061376457fe5b6020026020010181905250505b6001016136bb565b506001016136ad565b508160015b8381101561395e57600085828151811061379d57fe5b60200260200101516101400151905060008090506060836040519080825280602002602001820160405280156137dd578160200160208202803883390190505b509050826137f05783945050505061395e565b60005b8481101561388d578389828151811061380857fe5b602002602001015161014001511161381f5761388d565b613845848a838151811061382f57fe5b6020026020010151614a2790919063ffffffff16565b82828151811061385157fe5b60200260200101818152505061388382828151811061386c57fe5b602002602001015184612fe590919063ffffffff16565b92506001016137f3565b50858211156138a15783945050505061395e565b60005b8481101561394e578181815181106138b857fe5b6020026020010151600014156138cd57613946565b6139068282815181106138dc57fe5b60200260200101518a83815181106138f057fe5b6020026020010151614bdd90919063ffffffff16565b89828151811061391257fe5b602002602001018190525061394382828151811061392c57fe5b6020026020010151886133c690919063ffffffff16565b96505b6001016138a4565b5050600190920191506137879050565b50600082815b838110156139955761398b612fc988838151811061397e57fe5b6020026020010151614c15565b9250600101613964565b5060005b83811015613a165760008084116139b057856139c7565b6139c784611367856131468c878151811061397e57fe5b9050858111156139d45750845b6139e4818984815181106138f057fe5b8883815181106139f057fe5b6020908102919091010152613a0b868263ffffffff6133c616565b955050600101613999565b5060005b85811015613ae157868181518110613a2e57fe5b602002602001015160800151878281518110613a4657fe5b602002602001015160a001511015613ad9576000613a9b888381518110613a6957fe5b602002602001015160a00151898481518110613a8157fe5b6020026020010151608001516133c690919063ffffffff16565b9050613ad6888381518110613aac57fe5b602002602001015160000151828a8581518110613ac557fe5b602002602001015160200151614c32565b50505b600101613a1a565b50613b2e876040518060600160405280602b8152602001615754602b9139600854613b219073ffffffffffffffffffffffffffffffffffffffff16613324565b919063ffffffff612db216565b935060005b85811015613c1757868181518110613b4757fe5b602002602001015160800151878281518110613b5f57fe5b602002602001015160a001511115613c0f576000613bb4888381518110613b8257fe5b602002602001015160800151898481518110613b9a57fe5b602002602001015160a001516133c690919063ffffffff16565b905085811115613bc15750845b613bd1868263ffffffff6133c616565b9550613c0c888381518110613be257fe5b602002602001015160000151828a8581518110613bfb57fe5b602002602001015160200151614c50565b50505b600101613b33565b5050505050505050565b600854613c439073ffffffffffffffffffffffffffffffffffffffff16613324565b600a81905560408051918252517f8a0df8ef054fae2c3d2d19a7b322e864870cc9fd3cb07fb9526309c596244bf49181900360200190a1565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260046020526040902054613cb2908263ffffffff6133c616565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260046020526040902055600354613ceb908263ffffffff6133c616565b60035560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000178152925182516000946060949389169392918291908083835b60208310613e1657805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613dd9565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613e78576040519150601f19603f3d011682016040523d82523d6000602084013e613e7d565b606091505b5091509150818015613eab575080511580613eab5750808060200190516020811015613ea857600080fd5b50515b613f1657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f21736166655472616e7366657200000000000000000000000000000000000000604482015290519081900360640190fd5b5050505050565b60006109a6828373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015613fa057600080fd5b505afa158015613fb4573d6000803e3d6000fd5b505050506040513d6020811015613fca57600080fd5b5051614d9e565b6000610f7683838573ffffffffffffffffffffffffffffffffffffffff16633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561402057600080fd5b505af1158015614034573d6000803e3d6000fd5b505050506040513d602081101561404a57600080fd5b5051614c32565b428510156140c057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496d7065726d61783a2045585049524544000000000000000000000000000000604482015290519081900360640190fd5b60065473ffffffffffffffffffffffffffffffffffffffff808a1660008181526007602090815260408083208054600180820190925582518085018a905280840196909652958e166060860152608085018d905260a085019590955260c08085018c90528151808603909101815260e0850182528051908301207f19010000000000000000000000000000000000000000000000000000000000006101008601526101028501969096526101228085019690965280518085039096018652610142840180825286519683019690962095839052610162840180825286905260ff8a166101828501526101a284018990526101c28401889052519193926101e2808201937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019281900390910190855afa158015614202573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81161580159061427d57508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b6142e857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496d7065726d61783a20494e56414c49445f5349474e41545552450000000000604482015290519081900360640190fd5b50505050505050505050565b60008273ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561437357600080fd5b505afa158015614387573d6000803e3d6000fd5b505050506040513d602081101561439d57600080fd5b50519392505050565b6000818361440f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315612e20578181015183820152602001612e08565b50600083858161441b57fe5b0495945050505050565b61442d6155ed565b8273ffffffffffffffffffffffffffffffffffffffff1663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561447557600080fd5b505af1158015614489573d6000803e3d6000fd5b5050505060008373ffffffffffffffffffffffffffffffffffffffff16633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156144d757600080fd5b505af11580156144eb573d6000803e3d6000fd5b505050506040513d602081101561450157600080fd5b5051604080517f18160ddd000000000000000000000000000000000000000000000000000000008152905191925060009173ffffffffffffffffffffffffffffffffffffffff8716916318160ddd916004808301926020929190829003018186803b15801561456f57600080fd5b505afa158015614583573d6000803e3d6000fd5b505050506040513d602081101561459957600080fd5b5051604080517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301529151929350600092918816916370a0823191602480820192602092909190829003018186803b15801561461157600080fd5b505afa158015614625573d6000803e3d6000fd5b505050506040513d602081101561463b57600080fd5b505190506000614651838363ffffffff6133c616565b90506040518061016001604052808873ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018873ffffffffffffffffffffffffffffffffffffffff166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b1580156146c757600080fd5b505afa1580156146db573d6000803e3d6000fd5b505050506040513d60208110156146f157600080fd5b50518152602001614714670de0b6b3a7640000611367858963ffffffff61305916565b8152602001614735670de0b6b3a7640000611367868963ffffffff61305916565b8152602001614756670de0b6b3a7640000611367868963ffffffff61305916565b81526020018873ffffffffffffffffffffffffffffffffffffffff166391b427456040518163ffffffff1660e01b815260040160206040518083038186803b1580156147a157600080fd5b505afa1580156147b5573d6000803e3d6000fd5b505050506040513d60208110156147cb57600080fd5b50518152604080517f1aebf12f000000000000000000000000000000000000000000000000000000008152905160209283019273ffffffffffffffffffffffffffffffffffffffff8c1692631aebf12f9260048083019392829003018186803b15801561483757600080fd5b505afa15801561484b573d6000803e3d6000fd5b505050506040513d602081101561486157600080fd5b50518152604080517f4322b714000000000000000000000000000000000000000000000000000000008152905160209283019273ffffffffffffffffffffffffffffffffffffffff8c1692634322b7149260048083019392829003018186803b1580156148cd57600080fd5b505afa1580156148e1573d6000803e3d6000fd5b505050506040513d60208110156148f757600080fd5b50518152604080517f5b2b9d1a000000000000000000000000000000000000000000000000000000008152905160209283019273ffffffffffffffffffffffffffffffffffffffff8c1692635b2b9d1a9260048083019392829003018186803b15801561496357600080fd5b505afa158015614977573d6000803e3d6000fd5b505050506040513d602081101561498d57600080fd5b50518152600060209091015294506149a485614e33565b6101408601525050505092915050565b6149bc6155ed565b600082604001516149cc84614c15565b10156149dd57508190506000614a14565b60006149f0846040015161206f86614c15565b90506000614a028560a0015183614f33565b9050614a0e8582614f49565b93509150505b915091565b610140908101519101511190565b6000808211614a9757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4552524f523a2072617465203d20300000000000000000000000000000000000604482015290519081900360640190fd5b826101400151821115614b0b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4552524f523a205441524745542052415445203e204341434845442052415445604482015290519081900360640190fd5b6000614b178484615009565b9050614b22846151e4565b811115614b7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615678602f913960400191505060405180910390fd5b6000614b9f82611367670de0b6b3a7640000886040015161305990919063ffffffff16565b9050614bd4614bad86614c15565b6040518060600160405280602381526020016158906023913983919063ffffffff612db216565b95945050505050565b614be56155ed565b60a0830151614bfa908363ffffffff612fe516565b60a0840152614c0883614e33565b6101408401525090919050565b60006109a68260a001518360600151612fe590919063ffffffff16565b6000614c4884614c428585615224565b84615232565b949350505050565b6000614c6e8261136785670de0b6b3a764000063ffffffff61305916565b905080614c7d57506000610f76565b600854614ca79073ffffffffffffffffffffffffffffffffffffffff16858563ffffffff613d4016565b604080517f6a627842000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff861691636a6278429160248083019260209291908290030181600087803b158015614d1557600080fd5b505af1158015614d29573d6000803e3d6000fd5b505050506040513d6020811015614d3f57600080fd5b50516040805185815260208101839052815192935073ffffffffffffffffffffffffffffffffffffffff8716927f20541ba081e1e2ed9b41701070442c1fe618b0fec04825ba790aea8373f4e237929181900390910190a29392505050565b6000808373ffffffffffffffffffffffffffffffffffffffff16633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614de957600080fd5b505af1158015614dfd573d6000803e3d6000fd5b505050506040513d6020811015614e1357600080fd5b50519050614c48670de0b6b3a7640000611367858463ffffffff61305916565b600080614e3f836151e4565b90506000614e668460e00151611367670de0b6b3a76400008561305990919063ffffffff16565b905060008460e00151831015614e7d575080614efe565b6000614ec4614ea18760e00151670de0b6b3a76400006133c690919063ffffffff16565b611367670de0b6b3a76400006131468a60e00151896133c690919063ffffffff16565b9050614efa670de0b6b3a7640000614eee611d0660018a61012001516133c690919063ffffffff16565b9063ffffffff612fe516565b9150505b614bd4670de0b6b3a764000061136784613146670de0b6b3a7640000611367614f268c61541b565b889063ffffffff61305916565b6000818310614f425781610f76565b5090919050565b614f516155ed565b6000614f7d84604001516040518060600160405280602381526020016156ea60239139613b2187614c15565b905080831115614fd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615862602e913960400191505060405180910390fd5b60a0840151614fed908463ffffffff6133c616565b60a0850152614ffb84614e33565b610140850152509192915050565b60006150148361541b565b821161506d57615066670de0b6b3a76400006113678560e00151613146615061670de0b6b3a76400006131466150498b61541b565b6113678b670de0b6b3a764000063ffffffff61305916565b615473565b905061516d565b61012083015160009061508790600163ffffffff6133c616565b905060006150b3670de0b6b3a764000061206f8761012001518860e0015161305990919063ffffffff16565b905060006151086150c38761541b565b6113676150e58960e00151670de0b6b3a76400006133c690919063ffffffff16565b613146670de0b6b3a76400006113678c60e001518c61305990919063ffffffff16565b9050600061514d615061670de0b6b3a76400006131466151316004828a8963ffffffff61305916565b614eee670de0b6b3a76400006113678a8063ffffffff61305916565b905061516660026113678681858863ffffffff612fe516565b9450505050505b670de0b6b3a76400008111156109a657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4552524f523a20544152474554205554494c495a4154494f4e203e2031303025604482015290519081900360640190fd5b6000806151f083614c15565b90508061520157600091505061164b565b610f7681611367670de0b6b3a7640000866040015161305990919063ffffffff16565b6000610f76838360006154c4565b6000615250670de0b6b3a7640000611367858563ffffffff61305916565b90508061525f57506000610f76565b60008473ffffffffffffffffffffffffffffffffffffffff1663ad7a672f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156152a757600080fd5b505afa1580156152bb573d6000803e3d6000fd5b505050506040513d60208110156152d157600080fd5b50519050808211156152fc576152f98361136783670de0b6b3a764000063ffffffff61305916565b93505b61532373ffffffffffffffffffffffffffffffffffffffff8616868663ffffffff613d4016565b604080517f95a2251f000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff8716916395a2251f9160248083019260209291908290030181600087803b15801561539157600080fd5b505af11580156153a5573d6000803e3d6000fd5b505050506040513d60208110156153bb57600080fd5b50516040805182815260208101879052815192945073ffffffffffffffffffffffffffffffffffffffff8816927f8d69ef09150dd510133bc8e54e6ca115e8cf3370ea49a4a5ae56a1cdefc835e9929181900390910190a2509392505050565b60006109a6670de0b6b3a764000061136761544c856101000151670de0b6b3a76400006133c690919063ffffffff16565b613146670de0b6b3a76400006113678860c001518960e0015161305990919063ffffffff16565b600060038211156154b6575080600160028204015b818110156154b05780915060028182858161549f57fe5b0401816154a857fe5b049050615488565b5061164b565b811561164b57506001919050565b6000806154e38461136787670de0b6b3a764000063ffffffff61305916565b905060006154f882600163ffffffff612fe516565b9050831561553a57600061551e670de0b6b3a7640000611367848963ffffffff61305916565b90508681111561552e5782615530565b815b9350505050610f76565b6000615558670de0b6b3a7640000611367858963ffffffff61305916565b9050868110156155685781615530565b829350505050610f76565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106155b457805160ff19168380011785556155e1565b828001600101855582156155e1579182015b828111156155e15782518255916020019190600101906155c6565b50612fe192915061565d565b604051806101600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61138591905b80821115612fe1576000815560010161566356fe4552524f523a20544152474554205554494c495a4154494f4e203e2043555252454e54205554494c495a4154494f4e4c656e64696e675661756c7456313a20424f52524f5741424c455f454e41424c45444c656e64696e675661756c7456313a20424f52524f5741424c455f4558495354534552524f523a204e4547415449564520415641494c41424c45204c49515549444954594c656e64696e675661756c7456313a20424f52524f5741424c455f4e4f545f464f554e444c656e64696e675661756c7456313a20424f52524f5741424c455f44495341424c45444c656e64696e675661756c7456313a204e4547415449564520414d4f554e5420544f20414c4c4f43415445454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774c656e64696e675661756c7456313a20494e53554646494349454e545f4c49515549444954594c656e64696e675661756c7456313a20494e56414c49445f554e4445524c59494e474c656e64696e675661756c7456313a20424f52524f5741424c455f444f45534e545f4558495354534552524f523a204445414c4c4f4341544520414d4f554e54203e20415641494c41424c45204c49515549444954594552524f523a2054415247455420535550504c59203e20544f54414c20535550504c594c656e64696e675661756c7456313a2052454445454d5f414d4f554e545f5a45524f4c656e64696e675661756c7456313a204d41585f424f52524f5741424c45535f4c454e475448a265627a7a72315820272b1ff2f5bdfb5ffe4ff85e7b931a1776d5924d30728d423cc60a2c786295d764736f6c63430005100032
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in S
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.