Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 32 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Init | 19215502 | 408 days ago | IN | 0 ETH | 0.01467054 | ||||
Set Fee To | 19215502 | 408 days ago | IN | 0 ETH | 0.00193383 | ||||
Claim | 19171806 | 414 days ago | IN | 0 ETH | 0.00067332 | ||||
Claim | 19054604 | 431 days ago | IN | 0 ETH | 0.00023725 | ||||
Claim | 18990355 | 440 days ago | IN | 0 ETH | 0.00036015 | ||||
Claim | 18986802 | 440 days ago | IN | 0 ETH | 0.00047328 | ||||
Claim | 18986796 | 440 days ago | IN | 0 ETH | 0.00046341 | ||||
Claim | 18934256 | 447 days ago | IN | 0 ETH | 0.00051663 | ||||
Claim | 18923622 | 449 days ago | IN | 0 ETH | 0.00032976 | ||||
Claim | 18923619 | 449 days ago | IN | 0 ETH | 0.00033301 | ||||
Claim | 18923616 | 449 days ago | IN | 0 ETH | 0.00037195 | ||||
Claim | 18914829 | 450 days ago | IN | 0 ETH | 0.00032978 | ||||
Claim | 18854811 | 459 days ago | IN | 0 ETH | 0.0004558 | ||||
Claim | 18808727 | 465 days ago | IN | 0 ETH | 0.00074663 | ||||
Claim | 18689635 | 482 days ago | IN | 0 ETH | 0.00067872 | ||||
Claim | 18674830 | 484 days ago | IN | 0 ETH | 0.00062746 | ||||
Claim | 18650101 | 487 days ago | IN | 0 ETH | 0.00063106 | ||||
Claim | 18650099 | 487 days ago | IN | 0 ETH | 0.00062417 | ||||
Claim | 18633916 | 490 days ago | IN | 0 ETH | 0.00058118 | ||||
Claim | 18633912 | 490 days ago | IN | 0 ETH | 0.00055891 | ||||
Claim | 18607546 | 493 days ago | IN | 0 ETH | 0.00057528 | ||||
Claim | 18578444 | 497 days ago | IN | 0 ETH | 0.00095794 | ||||
Claim | 18559421 | 500 days ago | IN | 0 ETH | 0.00057529 | ||||
Claim | 18557535 | 500 days ago | IN | 0 ETH | 0.00073059 | ||||
Claim | 18553871 | 501 days ago | IN | 0 ETH | 0.00040997 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
Chamber
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // Chamber pragma solidity >=0.8.0; import "@openzeppelin/contracts/access/Ownable2Step.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "../contracts/interfaces/IMasterContract.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../contracts/libraries/BoringRebase.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/utils/math/SafeCast.sol"; import "../contracts/interfaces/IOracle.sol"; import "../contracts/interfaces/ISwapperV2.sol"; import "../contracts/interfaces/IBentoBoxV1.sol"; import "./Constants.sol"; contract Chamber is Ownable2Step, IMasterContract, Pausable { using SafeMath for uint256; using SafeMath for uint128; using SafeCast for uint256; using SafeCast for uint128; using RebaseLibrary for Rebase; using SafeERC20 for IERC20; event PriceUpdateEvent(uint256 rate); event AccumulateInterestEvent(uint128 accruedAmount); event DepositCollateralEvent(address indexed from, address indexed to, uint256 share); event WithdrawCollateralEvent(address indexed from, address indexed to, uint256 share); event BorrowEvent(address indexed from, address indexed to, uint256 amount, uint256 part); event RepayEvent(address indexed from, address indexed to, uint256 amount, uint256 part); event FeeToEvent(address indexed newFeeTo); event WithdrawFeesEvent(address indexed feeTo, uint256 feesEarnedFraction); event InterestChangeEvent(uint64 oldInterestRate, uint64 newInterestRate); event ChangeBlacklistedEvent(address indexed account, bool blacklisted); event LogChangeBorrowLimit(uint128 newLimit, uint128 perAddressPart); event LogLiquidation( address indexed from, address indexed user, address indexed to, uint256 collateralShare, uint256 borrowAmount, uint256 borrowPart ); // Immutables (for MasterContract and all clones) IBentoBoxV1 public immutable bentoBox; Chamber public immutable masterContract; IERC20 public immutable senUSD; // MasterContract variables address public feeTo; // Per clone variables // Clone init settings IERC20 public collateral; IOracle public oracle; bytes public oracleData; uint256 public COLLATERIZATION_RATE; uint256 public LIQUIDATION_MULTIPLIER; uint256 public BORROW_OPENING_FEE; struct BorrowCap { uint128 total; uint128 borrowPartPerAddress; } BorrowCap public borrowLimit; // Total amounts uint256 public totalCollateralShare; // Total collateral supplied Rebase public totalBorrow; // elastic = Total token amount to be repayed by borrowers, base = Total parts of the debt held by borrowers // User balances mapping(address => uint256) public userCollateralShare; mapping(address => uint256) public userBorrowPart; // Caller restrictions mapping(address => bool) public blacklisted; /// @notice Exchange and interest rate tracking. /// This is 'cached' here because calls to Oracles can be very expensive. uint256 public exchangeRate; struct AccruedInfo { uint64 lastAccrued; uint128 feesEarned; uint64 INTEREST_PER_SECOND; } AccruedInfo public accruedInterest; /// @notice tracks last interest rate uint256 internal lastInterestUpdate; modifier onlyMasterContractOwner() { require(msg.sender == masterContract.owner(), "Caller is not the owner"); _; } /// @notice The constructor is only used for the initial master contract. Subsequent clones are initialised via `init`. constructor(IBentoBoxV1 bentoBox_, IERC20 senUSD_) { bentoBox = bentoBox_; senUSD = senUSD_; masterContract = this; blacklisted[address(bentoBox)] = true; blacklisted[address(this)] = true; blacklisted[Ownable(address(bentoBox)).owner()] = true; } /// @notice Serves as the constructor for clones, as clones can't have a regular constructor /// @dev `data` is abi encoded in the format: (IERC20 collateral, IERC20 asset, IOracle oracle, bytes oracleData) function init(bytes calldata data) public virtual payable override { require(address(collateral) == address(0), "Chamber: already initialized"); (collateral, oracle, oracleData, accruedInterest.INTEREST_PER_SECOND, LIQUIDATION_MULTIPLIER, COLLATERIZATION_RATE, BORROW_OPENING_FEE) = abi.decode(data, (IERC20, IOracle, bytes, uint64, uint256, uint256, uint256)); borrowLimit = BorrowCap(type(uint128).max, type(uint128).max); require(address(collateral) != address(0), "Chamber: bad pair"); blacklisted[address(bentoBox)] = true; blacklisted[address(this)] = true; blacklisted[Ownable(address(bentoBox)).owner()] = true; (, exchangeRate) = oracle.get(oracleData); accumulate(); } /// @notice Accrues the interest on the borrowed tokens and handles the accumulation of fees. function accumulate() whenNotPaused public { AccruedInfo memory _accruedInterest = accruedInterest; // Number of seconds since accrue was called uint256 elapsedTime = block.timestamp - _accruedInterest.lastAccrued; if (elapsedTime == 0) { return; } _accruedInterest.lastAccrued = uint64(block.timestamp); Rebase memory _totalBorrow = totalBorrow; if (_totalBorrow.base == 0) { accruedInterest = _accruedInterest; return; } uint128 extraAmount = uint128(uint256(_totalBorrow.elastic).mul(_accruedInterest.INTEREST_PER_SECOND).mul(elapsedTime) / 1e18); _totalBorrow.elastic = uint128(_totalBorrow.elastic.add(extraAmount)); _accruedInterest.feesEarned = uint128(_accruedInterest.feesEarned.add(extraAmount)); totalBorrow = _totalBorrow; accruedInterest = _accruedInterest; emit AccumulateInterestEvent(extraAmount); } /// @notice Concrete implementation of `isSolvent`. Includes a third parameter to allow caching `exchangeRate`. /// @param _exchangeRate The exchange rate. Used to cache the `exchangeRate` between calls. function _isSolvent(address user, uint256 _exchangeRate) virtual internal view returns (bool) { // accrue must have already been called! uint256 borrowPart = userBorrowPart[user]; if (borrowPart == 0) return true; uint256 collateralShare = userCollateralShare[user]; if (collateralShare == 0) return false; Rebase memory _totalBorrow = totalBorrow; return bentoBox.toAmount( collateral, collateralShare.mul(Constants.EXCHANGE_RATE_PRECISION / Constants.COLLATERIZATION_RATE_PRECISION).mul(COLLATERIZATION_RATE), false ) >= // Moved exchangeRate here instead of dividing the other side to preserve more precision borrowPart.mul(_totalBorrow.elastic).mul(_exchangeRate) / _totalBorrow.base; } function isSolvent(address user) public view returns (bool) { return _isSolvent(user, exchangeRate); } /// @dev Checks if the user is solvent in the closed liquidation case at the end of the function body. modifier solvent() { _; (, uint256 _exchangeRate) = updatePrice(); require(_isSolvent(msg.sender, _exchangeRate), "Chamber: user insolvent"); } /// @notice Gets the exchange rate. I.e how much collateral to buy 1e18 asset. /// This function is supposed to be invoked if needed because Oracle queries can be expensive. /// @return updated True if `exchangeRate` was updated. /// @return rate The new exchange rate. function updatePrice() public returns (bool updated, uint256 rate) { (updated, rate) = oracle.get(oracleData); if (updated) { exchangeRate = rate; emit PriceUpdateEvent(rate); } else { // Return the old rate if fetching wasn't successful rate = exchangeRate; } } /// @dev Helper function to move tokens. /// @param token The ERC-20 token. /// @param share The amount in shares to add. /// @param total Grand total amount to deduct from this contract's balance. Only applicable if `skim` is True. /// Only used for accounting checks. /// @param skim If True, only does a balance check on this contract. /// False if tokens from msg.sender in `bentoBox` should be transferred. function _addTokens( IERC20 token, uint256 share, uint256 total, bool skim ) internal { if (skim) { require(share <= bentoBox.balanceOf(token, address(this)).sub(total), "Chamber: Skim too much"); } else { bentoBox.transfer(token, msg.sender, address(this), share); } } function _afterAddCollateral(address user, uint256 collateralShare) internal virtual {} /// @notice Adds `collateral` from msg.sender to the account `to`. /// @param to The receiver of the tokens. /// @param skim True if the amount should be skimmed from the deposit balance of msg.sender.x /// False if tokens from msg.sender in `bentoBox` should be transferred. /// @param share The amount of shares to add for `to`. function depositCollateral( address to, bool skim, uint256 share ) whenNotPaused public virtual { userCollateralShare[to] = userCollateralShare[to].add(share); uint256 oldTotalCollateralShare = totalCollateralShare; totalCollateralShare = oldTotalCollateralShare.add(share); _addTokens(collateral, share, oldTotalCollateralShare, skim); _afterAddCollateral(to, share); emit DepositCollateralEvent(skim ? address(bentoBox) : msg.sender, to, share); } function _afterWithdrawnCollateral(address from, address to, uint256 collateralShare) internal virtual {} /// @dev Concrete implementation of `withdrawCollateral`. function _withdrawCollateral(address to, uint256 share) whenNotPaused internal virtual { userCollateralShare[msg.sender] = userCollateralShare[msg.sender].sub(share); totalCollateralShare = totalCollateralShare.sub(share); _afterWithdrawnCollateral(msg.sender, to, share); emit WithdrawCollateralEvent(msg.sender, to, share); bentoBox.transfer(collateral, address(this), to, share); } /// @notice Removes `share` amount of collateral and transfers it to `to`. /// @param to The receiver of the shares. /// @param share Amount of shares to remove. function removeCollateral(address to, uint256 share) whenNotPaused public solvent { // accrue must be called because we check solvency accumulate(); _withdrawCollateral(to, share); } function _preBorrowAction(address to, uint256 amount, uint256 newBorrowPart, uint256 part) internal virtual { } /// @dev Concrete implementation of `borrow`. function _borrow(address to, uint256 amount) whenNotPaused internal returns (uint256 part, uint256 share) { uint256 feeAmount = amount.mul(BORROW_OPENING_FEE) / Constants.BORROW_OPENING_FEE_PRECISION; // A flat % fee is charged for any borrow (totalBorrow, part) = totalBorrow.add(amount.add(feeAmount), true); senUSD.safeApprove(address(bentoBox), amount); BorrowCap memory cap = borrowLimit; require(totalBorrow.elastic <= cap.total, "Borrow Limit reached"); accruedInterest.feesEarned = uint128(accruedInterest.feesEarned.add(uint128(feeAmount))); uint256 newBorrowPart = userBorrowPart[msg.sender].add(part); require(newBorrowPart <= cap.borrowPartPerAddress, "Borrow Limit reached"); _preBorrowAction(to, amount, newBorrowPart, part); userBorrowPart[msg.sender] = newBorrowPart; // As long as there are tokens on this contract you can 'mint'... this enables limiting borrows share = bentoBox.toShare(senUSD, amount, false); bentoBox.transfer(senUSD, address(this), to, share); senUSD.approve(address(bentoBox), 0); emit BorrowEvent(msg.sender, to, amount.add(feeAmount), part); } /// @notice Sender borrows `amount` and transfers it to `to`. /// @return part Total part of the debt held by borrowers. /// @return share Total amount in shares borrowed. function borrow(address to, uint256 amount) whenNotPaused public solvent returns (uint256 part, uint256 share) { accumulate(); (part, share) = _borrow(to, amount); } /// @dev Concrete implementation of `repay`. function _repay( address to, bool skim, uint256 part ) whenNotPaused internal returns (uint256 amount) { (totalBorrow, amount) = totalBorrow.sub(part, true); userBorrowPart[to] = userBorrowPart[to].sub(part); uint256 share = bentoBox.toShare(senUSD, amount, true); senUSD.safeApprove(address(bentoBox), amount); bentoBox.transfer(senUSD, skim ? address(bentoBox) : msg.sender, address(this), share); senUSD.approve(address(bentoBox), 0); emit RepayEvent(skim ? address(bentoBox) : msg.sender, to, amount, part); } /// @notice Repays a loan. /// @param to Address of the user this payment should go. /// @param skim True if the amount should be skimmed from the deposit balance of msg.sender. /// False if tokens from msg.sender in `bentoBox` should be transferred. /// @param part The amount to repay. See `userBorrowPart`. /// @return amount The total amount repayed. function repay( address to, bool skim, uint256 part ) whenNotPaused public returns (uint256 amount) { accumulate(); amount = _repay(to, skim, part); } /// @dev Helper function for choosing the correct value (`value1` or `value2`) depending on `inNum`. function _num( int256 inNum, uint256 value1, uint256 value2 ) internal pure returns (uint256 outNum) { outNum = inNum >= 0 ? uint256(inNum) : (inNum == Constants.USE_PARAM1 ? value1 : value2); } /// @dev Helper function for depositing into `bentoBox`. function _bentoDeposit( bytes memory data, uint256 value, uint256 value1, uint256 value2 ) whenNotPaused internal returns (uint256, uint256) { (IERC20 token, address to, int256 amount, int256 share) = abi.decode(data, (IERC20, address, int256, int256)); amount = int256(_num(amount, value1, value2)); // Done this way to avoid stack too deep errors share = int256(_num(share, value1, value2)); return bentoBox.deposit{value: value}(token, msg.sender, to, uint256(amount), uint256(share)); } /// @dev Helper function to withdraw from the `bentoBox`. function _bentoWithdraw( bytes memory data, uint256 value1, uint256 value2 ) whenNotPaused internal returns (uint256, uint256) { (IERC20 token, address to, int256 amount, int256 share) = abi.decode(data, (IERC20, address, int256, int256)); return bentoBox.withdraw(token, msg.sender, to, _num(amount, value1, value2), _num(share, value1, value2)); } /// @dev Helper function to perform a contract call and eventually extracting revert messages on failure. /// Calls to `bentoBox` are not allowed for obvious security reasons. /// This also means that calls made from this contract shall *not* be trusted. function _call( uint256 value, bytes memory data, uint256 value1, uint256 value2 ) whenNotPaused internal returns (bytes memory, uint8) { (address callee, bytes memory callData, bool useValue1, bool useValue2, uint8 returnValues) = abi.decode(data, (address, bytes, bool, bool, uint8)); if (useValue1 && !useValue2) { callData = abi.encodePacked(callData, value1); } else if (!useValue1 && useValue2) { callData = abi.encodePacked(callData, value2); } else if (useValue1 && useValue2) { callData = abi.encodePacked(callData, value1, value2); } require(!blacklisted[callee], "Chamber: can't call"); (bool success, bytes memory returnData) = callee.call{value: value}(callData); require(success, "Chamber: call failed"); return (returnData, returnValues); } struct OperationStatus { bool needsSolvencyCheck; bool hasAccrued; } function _extraOperation(uint8 action, OperationStatus memory, uint256 value, bytes memory data, uint256 value1, uint256 value2) internal virtual returns (bytes memory, uint8, OperationStatus memory) {} /// @notice Executes a set of actions and allows composability (contract calls) to other contracts. /// @param actions An array with a sequence of actions to execute (see OPERATION_ declarations). /// @param values A one-to-one mapped array to `actions`. ETH amounts to send along with the actions. /// Only applicable to `OPERATION`, `OPERATION_BENTO_DEPOSIT`. /// @param datas A one-to-one mapped array to `operations`. Contains abi encoded data of function arguments. /// @return value1 May contain the first positioned return value of the last executed action (if applicable). /// @return value2 May contain the second positioned return value of the last executed action which returns 2 values (if applicable). function performOperations( uint8[] calldata actions, uint256[] calldata values, bytes[] calldata datas ) whenNotPaused external payable returns (uint256 value1, uint256 value2) { OperationStatus memory status; uint256 actionsLength = actions.length; for (uint256 i = 0; i < actionsLength; i++) { uint8 action = actions[i]; if (!status.hasAccrued && action < 10) { accumulate(); status.hasAccrued = true; } if (action == Constants.OPERATION_ADD_COLLATERAL) { (int256 share, address to, bool skim) = abi.decode(datas[i], (int256, address, bool)); depositCollateral(to, skim, _num(share, value1, value2)); } else if (action == Constants.OPERATION_REPAY) { (int256 part, address to, bool skim) = abi.decode(datas[i], (int256, address, bool)); _repay(to, skim, _num(part, value1, value2)); } else if (action == Constants.OPERATION_REMOVE_COLLATERAL) { (int256 share, address to) = abi.decode(datas[i], (int256, address)); _withdrawCollateral(to, _num(share, value1, value2)); status.needsSolvencyCheck = true; } else if (action == Constants.OPERATION_BORROW) { (int256 amount, address to) = abi.decode(datas[i], (int256, address)); (value1, value2) = _borrow(to, _num(amount, value1, value2)); status.needsSolvencyCheck = true; } else if (action == Constants.OPERATION_UPDATE_PRICE) { (bool must_update, uint256 minRate, uint256 maxRate) = abi.decode(datas[i], (bool, uint256, uint256)); (bool updated, uint256 rate) = updatePrice(); require((!must_update || updated) && rate > minRate && (maxRate == 0 || rate < maxRate), "Chamber: rate not ok"); } else if (action == Constants.OPERATION_BENTO_SETAPPROVAL) { (address user, address _masterContract, bool approved, uint8 v, bytes32 r, bytes32 s) = abi.decode(datas[i], (address, address, bool, uint8, bytes32, bytes32)); bentoBox.setMasterContractApproval(user, _masterContract, approved, v, r, s); } else if (action == Constants.OPERATION_BENTO_DEPOSIT) { (value1, value2) = _bentoDeposit(datas[i], values[i], value1, value2); } else if (action == Constants.OPERATION_BENTO_WITHDRAW) { (value1, value2) = _bentoWithdraw(datas[i], value1, value2); } else if (action == Constants.OPERATION_BENTO_TRANSFER) { (IERC20 token, address to, int256 share) = abi.decode(datas[i], (IERC20, address, int256)); bentoBox.transfer(token, msg.sender, to, _num(share, value1, value2)); } else if (action == Constants.OPERATION_BENTO_TRANSFER_MULTIPLE) { (IERC20 token, address[] memory tos, uint256[] memory shares) = abi.decode(datas[i], (IERC20, address[], uint256[])); bentoBox.transferMultiple(token, msg.sender, tos, shares); } else if (action == Constants.OPERATION_CALL) { (bytes memory returnData, uint8 returnValues) = _call(values[i], datas[i], value1, value2); if (returnValues == 1) { (value1) = abi.decode(returnData, (uint256)); } else if (returnValues == 2) { (value1, value2) = abi.decode(returnData, (uint256, uint256)); } } else if (action == Constants.OPERATION_GET_REPAY_SHARE) { int256 part = abi.decode(datas[i], (int256)); value1 = bentoBox.toShare(senUSD, totalBorrow.toElastic(_num(part, value1, value2), true), true); } else if (action == Constants.OPERATION_GET_REPAY_PART) { int256 amount = abi.decode(datas[i], (int256)); value1 = totalBorrow.toBase(_num(amount, value1, value2), false); } else if (action == Constants.OPERATION_LIQUIDATE) { _operationLiquidate(datas[i]); } else { (bytes memory returnData, uint8 returnValues, OperationStatus memory returnStatus) = _extraOperation(action, status, values[i], datas[i], value1, value2); status = returnStatus; if (returnValues == 1) { (value1) = abi.decode(returnData, (uint256)); } else if (returnValues == 2) { (value1, value2) = abi.decode(returnData, (uint256, uint256)); } } } if (status.needsSolvencyCheck) { (, uint256 _exchangeRate) = updatePrice(); require(_isSolvent(msg.sender, _exchangeRate), "Chamber: user insolvent"); } } function _operationLiquidate(bytes calldata data) internal { (address[] memory users, uint256[] memory maxBorrowParts, address to, ISwapperV2 swapper, bytes memory swapperData) = abi.decode(data, (address[], uint256[], address, ISwapperV2, bytes)); liquidate(users, maxBorrowParts, to, swapper, swapperData); } function _beforeUsersLiquidated(address[] memory users, uint256[] memory maxBorrowPart) internal virtual {} function _beforeUserLiquidated(address user, uint256 borrowPart, uint256 borrowAmount, uint256 collateralShare) internal virtual {} function _afterUserLiquidated(address user, uint256 collateralShare) internal virtual {} /// @notice Handles the liquidation of users' balances, once the users' amount of collateral is too low. /// @param users An array of user addresses. /// @param maxBorrowParts A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user. /// @param to Address of the receiver in open liquidations if `swapper` is zero. function liquidate( address[] memory users, uint256[] memory maxBorrowParts, address to, ISwapperV2 swapper, bytes memory swapperData ) whenNotPaused public virtual { // Oracle can fail but we still need to allow liquidations (, uint256 _exchangeRate) = updatePrice(); accumulate(); uint256 allCollateralShare; uint256 allBorrowAmount; uint256 allBorrowPart; Rebase memory bentoBoxTotals = bentoBox.totals(collateral); _beforeUsersLiquidated(users, maxBorrowParts); uint256 usersLength = users.length; for (uint256 i = 0; i < usersLength; i++) { address user = users[i]; if (!_isSolvent(user, _exchangeRate)) { uint256 borrowPart; uint256 availableBorrowPart = userBorrowPart[user]; borrowPart = maxBorrowParts[i] > availableBorrowPart ? availableBorrowPart : maxBorrowParts[i]; uint256 borrowAmount = totalBorrow.toElastic(borrowPart, false); uint256 collateralShare = bentoBoxTotals.toBase( borrowAmount.mul(LIQUIDATION_MULTIPLIER).mul(_exchangeRate) / (Constants.LIQUIDATION_MULTIPLIER_PRECISION * Constants.EXCHANGE_RATE_PRECISION), false ); _beforeUserLiquidated(user, borrowPart, borrowAmount, collateralShare); userBorrowPart[user] = availableBorrowPart.sub(borrowPart); userCollateralShare[user] = userCollateralShare[user].sub(collateralShare); _afterUserLiquidated(user, collateralShare); emit WithdrawCollateralEvent(user, to, collateralShare); emit RepayEvent(msg.sender, user, borrowAmount, borrowPart); emit LogLiquidation(msg.sender, user, to, collateralShare, borrowAmount, borrowPart); // Keep totals allCollateralShare = allCollateralShare.add(collateralShare); allBorrowAmount = allBorrowAmount.add(borrowAmount); allBorrowPart = allBorrowPart.add(borrowPart); } } require(allBorrowAmount != 0, "Chamber: all are solvent"); totalBorrow.elastic = uint128(totalBorrow.elastic.sub(allBorrowAmount)); totalBorrow.base = uint128(totalBorrow.base.sub(allBorrowPart)); totalCollateralShare = totalCollateralShare.sub(allCollateralShare); { uint256 distributionAmount = (allBorrowAmount.mul(LIQUIDATION_MULTIPLIER) / Constants.LIQUIDATION_MULTIPLIER_PRECISION).sub(allBorrowAmount).mul(Constants.DISTRIBUTION_PART) / Constants.DISTRIBUTION_PRECISION; // Distribution Amount allBorrowAmount = allBorrowAmount.add(distributionAmount); accruedInterest.feesEarned = uint128(accruedInterest.feesEarned.add(distributionAmount)); } uint256 allBorrowShare = bentoBox.toShare(senUSD, allBorrowAmount, true); // Swap using a swapper freely chosen by the caller // Open (flash) liquidation: get proceeds first and provide the borrow after bentoBox.transfer(collateral, address(this), to, allCollateralShare); if (swapper != ISwapperV2(address(0))) { swapper.swap(address(collateral), address(senUSD), msg.sender, allBorrowShare, allCollateralShare, swapperData); } allBorrowShare = bentoBox.toShare(senUSD, allBorrowAmount, true); bentoBox.transfer(senUSD, msg.sender, address(this), allBorrowShare); } /// @notice Withdraws the fees accumulated. function withdrawFees() public { accumulate(); address _feeTo = masterContract.feeTo(); uint256 _feesEarned = accruedInterest.feesEarned; uint256 share = bentoBox.toShare(senUSD, _feesEarned, false); bentoBox.transfer(senUSD, address(this), _feeTo, share); accruedInterest.feesEarned = 0; emit WithdrawFeesEvent(_feeTo, _feesEarned); } /// @notice Sets the beneficiary of interest accrued. /// MasterContract Only Admin function. /// @param newFeeTo The address of the receiver. function setFeeTo(address newFeeTo) public onlyOwner { require(newFeeTo != address(0), 'cannot be 0 address'); feeTo = newFeeTo; emit FeeToEvent(newFeeTo); } /// @notice reduces the supply of SENUSD /// @param amount amount to reduce supply by function reduceSupply(uint256 amount) public onlyMasterContractOwner { uint256 maxAmount = bentoBox.toAmount(senUSD, bentoBox.balanceOf(senUSD, address(this)), false); amount = maxAmount > amount ? amount : maxAmount; bentoBox.withdraw(senUSD, address(this), msg.sender, amount, 0); } /// @notice allows to change the interest rate /// @param newInterestRateBps new interest rate in basis points function changeInterestRate(uint16 newInterestRateBps) public onlyMasterContractOwner { uint64 oldInterestRate = accruedInterest.INTEREST_PER_SECOND; uint64 newInterestRate = fromBps(newInterestRateBps); require(newInterestRate < oldInterestRate + oldInterestRate * 3 / 4 || newInterestRate <= ONE_PERCENT_RATE(), "Interest rate increase > 75%"); require(lastInterestUpdate + 3 days < block.timestamp, "Update only every 3 days"); lastInterestUpdate = block.timestamp; accruedInterest.INTEREST_PER_SECOND = newInterestRate; emit InterestChangeEvent(oldInterestRate, newInterestRate); } /// @notice allows to change the borrow limit /// @param newBorrowLimit new borrow limit /// @param perAddressPart new borrow limit per address function changeBorrowLimit(uint128 newBorrowLimit, uint128 perAddressPart) public onlyMasterContractOwner { borrowLimit = BorrowCap(newBorrowLimit, perAddressPart); emit LogChangeBorrowLimit(newBorrowLimit, perAddressPart); } /// @notice allows to change blacklisted callees /// @param callee callee to blacklist or not /// @param _blacklisted true when the callee cannot be used in call cook action function setBlacklistedCaller(address callee, bool _blacklisted) public onlyMasterContractOwner { require(callee != address(0), 'invalid callee'); require(callee != address(bentoBox) && callee != address(this), "invalid callee"); blacklisted[callee] = _blacklisted; emit ChangeBlacklistedEvent(callee, _blacklisted); } function fromBps(uint16 rate) internal pure returns (uint64) { return uint64(rate) * Constants.PERCENT_RATE / Constants.BASIS_POINTS_DENOM; } function ONE_PERCENT_RATE() internal pure returns (uint64) { return Constants.PERCENT_RATE; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such 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. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); require(downcasted == value, "SafeCast: value doesn't fit in 248 bits"); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); require(downcasted == value, "SafeCast: value doesn't fit in 240 bits"); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); require(downcasted == value, "SafeCast: value doesn't fit in 232 bits"); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); require(downcasted == value, "SafeCast: value doesn't fit in 224 bits"); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); require(downcasted == value, "SafeCast: value doesn't fit in 216 bits"); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); require(downcasted == value, "SafeCast: value doesn't fit in 208 bits"); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); require(downcasted == value, "SafeCast: value doesn't fit in 200 bits"); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); require(downcasted == value, "SafeCast: value doesn't fit in 192 bits"); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); require(downcasted == value, "SafeCast: value doesn't fit in 184 bits"); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); require(downcasted == value, "SafeCast: value doesn't fit in 176 bits"); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); require(downcasted == value, "SafeCast: value doesn't fit in 168 bits"); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); require(downcasted == value, "SafeCast: value doesn't fit in 160 bits"); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); require(downcasted == value, "SafeCast: value doesn't fit in 152 bits"); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); require(downcasted == value, "SafeCast: value doesn't fit in 144 bits"); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); require(downcasted == value, "SafeCast: value doesn't fit in 136 bits"); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); require(downcasted == value, "SafeCast: value doesn't fit in 128 bits"); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); require(downcasted == value, "SafeCast: value doesn't fit in 120 bits"); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); require(downcasted == value, "SafeCast: value doesn't fit in 112 bits"); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); require(downcasted == value, "SafeCast: value doesn't fit in 104 bits"); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); require(downcasted == value, "SafeCast: value doesn't fit in 96 bits"); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); require(downcasted == value, "SafeCast: value doesn't fit in 88 bits"); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); require(downcasted == value, "SafeCast: value doesn't fit in 80 bits"); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); require(downcasted == value, "SafeCast: value doesn't fit in 72 bits"); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); require(downcasted == value, "SafeCast: value doesn't fit in 64 bits"); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); require(downcasted == value, "SafeCast: value doesn't fit in 56 bits"); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); require(downcasted == value, "SafeCast: value doesn't fit in 48 bits"); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); require(downcasted == value, "SafeCast: value doesn't fit in 40 bits"); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); require(downcasted == value, "SafeCast: value doesn't fit in 32 bits"); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); require(downcasted == value, "SafeCast: value doesn't fit in 24 bits"); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); require(downcasted == value, "SafeCast: value doesn't fit in 16 bits"); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); require(downcasted == value, "SafeCast: value doesn't fit in 8 bits"); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; library Constants { uint64 public constant PERCENT_RATE = 317097920; // Interest uint16 public constant BASIS_POINTS_DENOM = 1e4; // Core uint256 public constant COLLATERIZATION_RATE_PRECISION = 1e5; // Rates uint256 public constant EXCHANGE_RATE_PRECISION = 1e18; uint256 public constant LIQUIDATION_MULTIPLIER_PRECISION = 1e5; // Fees uint256 public constant BORROW_OPENING_FEE_PRECISION = 1e5; // Distribution uint256 public constant DISTRIBUTION_PART = 10; uint256 public constant DISTRIBUTION_PRECISION = 100; uint8 public constant OPERATION_REPAY = 2; uint8 public constant OPERATION_REMOVE_COLLATERAL = 4; uint8 public constant OPERATION_BORROW = 5; uint8 public constant OPERATION_GET_REPAY_SHARE = 6; uint8 public constant OPERATION_GET_REPAY_PART = 7; uint8 public constant OPERATION_ACCRUE = 8; uint8 public constant OPERATION_ADD_COLLATERAL = 10; uint8 public constant OPERATION_UPDATE_PRICE = 11; uint8 public constant OPERATION_BENTO_DEPOSIT = 20; uint8 public constant OPERATION_BENTO_WITHDRAW = 21; uint8 public constant OPERATION_BENTO_TRANSFER = 22; uint8 public constant OPERATION_BENTO_TRANSFER_MULTIPLE = 23; uint8 public constant OPERATION_BENTO_SETAPPROVAL = 24; uint8 public constant OPERATION_CALL = 30; uint8 public constant OPERATION_LIQUIDATE = 31; uint8 public constant OPERATION_CUSTOM_START_INDEX = 100; int256 public constant USE_PARAM1 = -1; int256 public constant USE_PARAM2 = -2; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../libraries/BoringRebase.sol"; import "./IStrategy.sol"; interface IFlashBorrower { /// @notice The flashloan callback. `amount` + `fee` needs to repayed to msg.sender before this call returns. /// @param sender The address of the invoker of this flashloan. /// @param token The address of the token that is loaned. /// @param amount of the `token` that is loaned. /// @param fee The fee that needs to be paid on top for this loan. Needs to be the same as `token`. /// @param data Additional data that was passed to the flashloan function. function onFlashLoan( address sender, IERC20 token, uint256 amount, uint256 fee, bytes calldata data ) external; } interface IBatchFlashBorrower { /// @notice The callback for batched flashloans. Every amount + fee needs to repayed to msg.sender before this call returns. /// @param sender The address of the invoker of this flashloan. /// @param tokens Array of addresses for ERC-20 tokens that is loaned. /// @param amounts A one-to-one map to `tokens` that is loaned. /// @param fees A one-to-one map to `tokens` that needs to be paid on top for each loan. Needs to be the same token. /// @param data Additional data that was passed to the flashloan function. function onBatchFlashLoan( address sender, IERC20[] calldata tokens, uint256[] calldata amounts, uint256[] calldata fees, bytes calldata data ) external; } interface IBentoBoxV1 { function balanceOf(IERC20, address) external view returns (uint256); function batch(bytes[] calldata calls, bool revertOnFail) external payable returns (bool[] memory successes, bytes[] memory results); function batchFlashLoan( IBatchFlashBorrower borrower, address[] calldata receivers, IERC20[] calldata tokens, uint256[] calldata amounts, bytes calldata data ) external; function claimOwnership() external; function flashLoan( IFlashBorrower borrower, address receiver, IERC20 token, uint256 amount, bytes calldata data ) external; function deploy( address masterContract, bytes calldata data, bool useCreate2 ) external payable returns (address); function deposit( IERC20 token_, address from, address to, uint256 amount, uint256 share ) external payable returns (uint256 amountOut, uint256 shareOut); function harvest( IERC20 token, bool balance, uint256 maxChangeAmount ) external; function masterContractApproved(address, address) external view returns (bool); function masterContractOf(address) external view returns (address); function nonces(address) external view returns (uint256); function owner() external view returns (address); function pendingOwner() external view returns (address); function pendingStrategy(IERC20) external view returns (IStrategy); function permitToken( IERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function registerProtocol() external; function setMasterContractApproval( address user, address masterContract, bool approved, uint8 v, bytes32 r, bytes32 s ) external; function setStrategy(IERC20 token, IStrategy newStrategy) external; function setStrategyTargetPercentage(IERC20 token, uint64 targetPercentage_) external; function strategy(IERC20) external view returns (IStrategy); function strategyData(IERC20) external view returns ( uint64 strategyStartDate, uint64 targetPercentage, uint128 balance ); function toAmount( IERC20 token, uint256 share, bool roundUp ) external view returns (uint256 amount); function toShare( IERC20 token, uint256 amount, bool roundUp ) external view returns (uint256 share); function totals(IERC20) external view returns (Rebase memory totals_); function transfer( IERC20 token, address from, address to, uint256 share ) external; function transferMultiple( IERC20 token, address from, address[] calldata tos, uint256[] calldata shares ) external; function transferOwnership( address newOwner, bool direct, bool renounce ) external; function whitelistMasterContract(address masterContract, bool approved) external; function whitelistedMasterContracts(address) external view returns (bool); function withdraw( IERC20 token_, address from, address to, uint256 amount, uint256 share ) external returns (uint256 amountOut, uint256 shareOut); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IMasterContract { /// @notice Init function that gets called from `BoringFactory.deploy`. /// Also kown as the constructor for cloned contracts. /// Any ETH send to `BoringFactory.deploy` ends up here. /// @param data Can be abi encoded arguments or anything else. function init(bytes calldata data) external payable; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IOracle { /// @notice Get the decimals of the oracle. /// @return decimals The decimals. function decimals() external view returns (uint8); /// @notice Get the latest exchange rate. /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return success if no valid (recent) rate is available, return false else true. /// @return rate The rate of the requested asset / pair / pool. function get(bytes calldata data) external returns (bool success, uint256 rate); /// @notice Check the last exchange rate without any state changes. /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return success if no valid (recent) rate is available, return false else true. /// @return rate The rate of the requested asset / pair / pool. function peek(bytes calldata data) external view returns (bool success, uint256 rate); /// @notice Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek(). /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return rate The rate of the requested asset / pair / pool. function peekSpot(bytes calldata data) external view returns (uint256 rate); /// @notice Returns a human readable (short) name about this oracle. /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return (string) A human readable symbol name about this oracle. function symbol(bytes calldata data) external view returns (string memory); /// @notice Returns a human readable name about this oracle. /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return (string) A human readable name about this oracle. function name(bytes calldata data) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IStrategy { /// @notice Send the assets to the Strategy and call skim to invest them. /// @param amount The amount of tokens to invest. function skim(uint256 amount) external; /// @notice Harvest any profits made converted to the asset and pass them to the caller. /// @param balance The amount of tokens the caller thinks it has invested. /// @param sender The address of the initiator of this transaction. Can be used for reimbursements, etc. /// @return amountAdded The delta (+profit or -loss) that occured in contrast to `balance`. function harvest(uint256 balance, address sender) external returns (int256 amountAdded); /// @notice Withdraw assets. The returned amount can differ from the requested amount due to rounding. /// @dev The `actualAmount` should be very close to the amount. /// The difference should NOT be used to report a loss. That's what harvest is for. /// @param amount The requested amount the caller wants to withdraw. /// @return actualAmount The real amount that is withdrawn. function withdraw(uint256 amount) external returns (uint256 actualAmount); /// @notice Withdraw all assets in the safest way possible. This shouldn't fail. /// @param balance The amount of tokens the caller thinks it has invested. /// @return amountAdded The delta (+profit or -loss) that occured in contrast to `balance`. function exit(uint256 balance) external returns (int256 amountAdded); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface ISwapperV2 { /// @notice Withdraws 'amountFrom' of token 'from' from the BentoBox account for this swapper. /// Swaps it for at least 'amountToMin' of token 'to'. /// Transfers the swapped tokens of 'to' into the BentoBox using a plain IERC20 transfer. /// Returns the amount of tokens 'to' transferred to BentoBox. /// (The BentoBox skim function will be used by the caller to get the swapped funds). function swap( address fromToken, address toToken, address recipient, uint256 shareToMin, uint256 shareFrom, bytes calldata data ) external returns (uint256 extraShare, uint256 shareReturned); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; struct Rebase { uint128 elastic; uint128 base; } /// @notice A rebasing library using overflow-/underflow-safe math. library RebaseLibrary { /// @notice Calculates the base value in relationship to `elastic` and `total`. function toBase( Rebase memory total, uint256 elastic, bool roundUp ) internal pure returns (uint256 base) { if (total.elastic == 0) { base = elastic; } else { base = (elastic * total.base) / total.elastic; if (roundUp && (base * total.elastic) / total.base < elastic) { base++; } } } /// @notice Calculates the elastic value in relationship to `base` and `total`. function toElastic( Rebase memory total, uint256 base, bool roundUp ) internal pure returns (uint256 elastic) { if (total.base == 0) { elastic = base; } else { elastic = (base * total.elastic) / total.base; if (roundUp && (elastic * total.base) / total.elastic < base) { elastic++; } } } /// @notice Add `elastic` to `total` and doubles `total.base`. /// @return (Rebase) The new total. /// @return base in relationship to `elastic`. function add( Rebase memory total, uint256 elastic, bool roundUp ) internal pure returns (Rebase memory, uint256 base) { base = toBase(total, elastic, roundUp); total.elastic += uint128(elastic); total.base += uint128(base); return (total, base); } /// @notice Sub `base` from `total` and update `total.elastic`. /// @return (Rebase) The new total. /// @return elastic in relationship to `base`. function sub( Rebase memory total, uint256 base, bool roundUp ) internal pure returns (Rebase memory, uint256 elastic) { elastic = toElastic(total, base, roundUp); total.elastic -= uint128(elastic); total.base -= uint128(base); return (total, elastic); } /// @notice Add `elastic` and `base` to `total`. function add( Rebase memory total, uint256 elastic, uint256 base ) internal pure returns (Rebase memory) { total.elastic += uint128(elastic); total.base += uint128(base); return total; } /// @notice Subtract `elastic` and `base` to `total`. function sub( Rebase memory total, uint256 elastic, uint256 base ) internal pure returns (Rebase memory) { total.elastic -= uint128(elastic); total.base -= uint128(base); return total; } /// @notice Add `elastic` to `total` and update storage. /// @return newElastic Returns updated `elastic`. function addElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) { newElastic = total.elastic += uint128(elastic); } /// @notice Subtract `elastic` from `total` and update storage. /// @return newElastic Returns updated `elastic`. function subElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) { newElastic = total.elastic -= uint128(elastic); } }
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IBentoBoxV1","name":"bentoBox_","type":"address"},{"internalType":"contract IERC20","name":"senUSD_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"accruedAmount","type":"uint128"}],"name":"AccumulateInterestEvent","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":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"part","type":"uint256"}],"name":"BorrowEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"blacklisted","type":"bool"}],"name":"ChangeBlacklistedEvent","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":"share","type":"uint256"}],"name":"DepositCollateralEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newFeeTo","type":"address"}],"name":"FeeToEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"oldInterestRate","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newInterestRate","type":"uint64"}],"name":"InterestChangeEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"newLimit","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"perAddressPart","type":"uint128"}],"name":"LogChangeBorrowLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateralShare","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowPart","type":"uint256"}],"name":"LogLiquidation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"rate","type":"uint256"}],"name":"PriceUpdateEvent","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":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"part","type":"uint256"}],"name":"RepayEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","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":"share","type":"uint256"}],"name":"WithdrawCollateralEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"feeTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"feesEarnedFraction","type":"uint256"}],"name":"WithdrawFeesEvent","type":"event"},{"inputs":[],"name":"BORROW_OPENING_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COLLATERIZATION_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIQUIDATION_MULTIPLIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"accruedInterest","outputs":[{"internalType":"uint64","name":"lastAccrued","type":"uint64"},{"internalType":"uint128","name":"feesEarned","type":"uint128"},{"internalType":"uint64","name":"INTEREST_PER_SECOND","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accumulate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bentoBox","outputs":[{"internalType":"contract IBentoBoxV1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"blacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"borrow","outputs":[{"internalType":"uint256","name":"part","type":"uint256"},{"internalType":"uint256","name":"share","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"borrowLimit","outputs":[{"internalType":"uint128","name":"total","type":"uint128"},{"internalType":"uint128","name":"borrowPartPerAddress","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"newBorrowLimit","type":"uint128"},{"internalType":"uint128","name":"perAddressPart","type":"uint128"}],"name":"changeBorrowLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"newInterestRateBps","type":"uint16"}],"name":"changeInterestRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateral","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"skim","type":"bool"},{"internalType":"uint256","name":"share","type":"uint256"}],"name":"depositCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exchangeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"init","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"isSolvent","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"uint256[]","name":"maxBorrowParts","type":"uint256[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"contract ISwapperV2","name":"swapper","type":"address"},{"internalType":"bytes","name":"swapperData","type":"bytes"}],"name":"liquidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"masterContract","outputs":[{"internalType":"contract Chamber","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8[]","name":"actions","type":"uint8[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"datas","type":"bytes[]"}],"name":"performOperations","outputs":[{"internalType":"uint256","name":"value1","type":"uint256"},{"internalType":"uint256","name":"value2","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"reduceSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"share","type":"uint256"}],"name":"removeCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"skim","type":"bool"},{"internalType":"uint256","name":"part","type":"uint256"}],"name":"repay","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"senUSD","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"callee","type":"address"},{"internalType":"bool","name":"_blacklisted","type":"bool"}],"name":"setBlacklistedCaller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeTo","type":"address"}],"name":"setFeeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalBorrow","outputs":[{"internalType":"uint128","name":"elastic","type":"uint128"},{"internalType":"uint128","name":"base","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalCollateralShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updatePrice","outputs":[{"internalType":"bool","name":"updated","type":"bool"},{"internalType":"uint256","name":"rate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBorrowPart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userCollateralShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e06040523480156200001157600080fd5b5060405162005cda38038062005cda8339810160408190526200003491620001aa565b6200003f3362000126565b6001805460ff60a01b191681556001600160a01b03808416608081905290831660c0523060a08190526000828152600e60208181526040808420805460ff199081168917909155948452808420805490951687179094558351638da5cb5b60e01b8152935191949293638da5cb5b92600480830193928290030181865afa158015620000cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000f59190620001e9565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905550620002109050565b600180546001600160a01b0319169055620001418162000144565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146200014157600080fd5b60008060408385031215620001be57600080fd5b8251620001cb8162000194565b6020840151909250620001de8162000194565b809150509250929050565b600060208284031215620001fc57600080fd5b8151620002098162000194565b9392505050565b60805160a05160c051615920620003ba6000396000818161070b01528181610cc201528181610d9b01528181611c1f015281816122190152818161237e01528181612eaa0152818161301c015281816130bc01528181613174015281816134e0015281816135920152818161360a0152818161370701528181613a1c01528181613bda01528181613c950152613d770152600081816107550152818161097d01528181610c30015281816111fc0152818161212a01526128510152600081816105810152818161091301528181610d1901528181610ddb0152818161108501528181611334015281816117c40152818161197c01528181611a7a01528181611bf001528181612253015281816123c3015281816129fb01528181612ee301528181612f8a015281816130f2015281816131b2015281816132bc015281816133ad01528181613516015281816135b4015281816135db01528181613636015281816136d80152818161378e015281816138ae01528181613a3e01528181613c1101528181613cd501528181613d4801528181613f1e0152818161401c01526140cc01526159206000f3fe6080604052600436106102bb5760003560e01c806374645ff31161016e578063c7ee2a7b116100cb578063e551d11d1161007f578063f46901ed11610064578063f46901ed14610830578063f7dad43414610850578063ff6ff84b1461087057600080fd5b8063e551d11d146107e5578063f2fde38b1461081057600080fd5b8063d8dfeb45116100b0578063d8dfeb4514610777578063dbac26e914610797578063e30c3978146107c757600080fd5b8063c7ee2a7b1461072d578063cd446e221461074357600080fd5b8063876467f811610122578063a53aeb4e11610107578063a53aeb4e146106ce578063aba024f4146106e3578063b6f173d1146106f957600080fd5b8063876467f8146106905780638da5cb5b146106b057600080fd5b80637dc0d1d0116101535780637dc0d1d01461060557806380623444146106255780638285ef401461064557600080fd5b806374645ff3146105ce57806379ba5097146105f057600080fd5b806348e4163e1161021c5780635c975abb116101d05780636b2ace87116101b55780636b2ace871461056f5780636ec097fb146105a3578063715018a6146105b957600080fd5b80635c975abb14610524578063673a7e281461054357600080fd5b80634ddf47d4116102015780634ddf47d4146104de578063517cf6a3146104f1578063568d8cd91461051157600080fd5b806348e4163e1461047c5780634b8a3529146104a957600080fd5b806338b51ce11161027357806345fe329f1161025857806345fe329f146103e0578063473e3ce714610451578063476343ee1461046757600080fd5b806338b51ce11461039a5780633ba0b9a9146103ca57600080fd5b80630ed6f9be116102a45780630ed6f9be1461031f57806315294c401461033f5780631c9e379b1461036d57600080fd5b8063017e7e58146102c057806302c1a42b146102fd575b600080fd5b3480156102cc57600080fd5b506002546102e0906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561030957600080fd5b5061031d610318366004614a28565b610890565b005b34801561032b57600080fd5b5061031d61033a366004614a69565b61097b565b34801561034b57600080fd5b5061035f61035a366004614a28565b610beb565b6040519081526020016102f4565b34801561037957600080fd5b5061035f610388366004614a8d565b600c6020526000908152604090205481565b3480156103a657600080fd5b506103ba6103b5366004614a8d565b610c10565b60405190151581526020016102f4565b3480156103d657600080fd5b5061035f600f5481565b3480156103ec57600080fd5b5060105461041e9067ffffffffffffffff808216916001600160801b03600160401b82041691600160c01b9091041683565b6040805167ffffffffffffffff94851681526001600160801b0390931660208401529216918101919091526060016102f4565b34801561045d57600080fd5b5061035f600a5481565b34801561047357600080fd5b5061031d610c24565b34801561048857600080fd5b5061035f610497366004614a8d565b600d6020526000908152604090205481565b3480156104b557600080fd5b506104c96104c4366004614aaa565b610e9d565b604080519283526020830191909152016102f4565b61031d6104ec366004614ad6565b610f2a565b3480156104fd57600080fd5b5061031d61050c366004614b48565b6111fa565b6104c961051f366004614bcd565b611428565b34801561053057600080fd5b50600154600160a01b900460ff166103ba565b34801561054f57600080fd5b50610558611f34565b6040805192151583526020830191909152016102f4565b34801561057b57600080fd5b506102e07f000000000000000000000000000000000000000000000000000000000000000081565b3480156105af57600080fd5b5061035f60075481565b3480156105c557600080fd5b5061031d611ff8565b3480156105da57600080fd5b506105e361200c565b6040516102f49190614cb7565b3480156105fc57600080fd5b5061031d61209a565b34801561061157600080fd5b506004546102e0906001600160a01b031681565b34801561063157600080fd5b5061031d610640366004614cca565b612128565b34801561065157600080fd5b50600b54610670906001600160801b0380821691600160801b90041682565b604080516001600160801b039384168152929091166020830152016102f4565b34801561069c57600080fd5b5061031d6106ab366004614aaa565b612437565b3480156106bc57600080fd5b506000546001600160a01b03166102e0565b3480156106da57600080fd5b5061031d6124b9565b3480156106ef57600080fd5b5061035f60085481565b34801561070557600080fd5b506102e07f000000000000000000000000000000000000000000000000000000000000000081565b34801561073957600080fd5b5061035f60065481565b34801561074f57600080fd5b506102e07f000000000000000000000000000000000000000000000000000000000000000081565b34801561078357600080fd5b506003546102e0906001600160a01b031681565b3480156107a357600080fd5b506103ba6107b2366004614a8d565b600e6020526000908152604090205460ff1681565b3480156107d357600080fd5b506001546001600160a01b03166102e0565b3480156107f157600080fd5b50600954610670906001600160801b0380821691600160801b90041682565b34801561081c57600080fd5b5061031d61082b366004614a8d565b61271c565b34801561083c57600080fd5b5061031d61084b366004614a8d565b61279a565b34801561085c57600080fd5b5061031d61086b366004614cf8565b61284f565b34801561087c57600080fd5b5061031d61088b366004614ed9565b61299a565b61089861321e565b6001600160a01b0383166000908152600c60205260409020546108bb9082613278565b6001600160a01b0384166000908152600c6020526040902055600a546108e18183613278565b600a556003546108fc906001600160a01b031683838661328b565b836001600160a01b0316836109115733610933565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03167f6278fc0b0b834dd63a777a95fa7ad401bb418e9abd9e2d2fea56de8d614544c98460405161096d91815260200190565b60405180910390a350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fd9190614f8b565b6001600160a01b0316336001600160a01b031614610a625760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e657200000000000000000060448201526064015b60405180910390fd5b601054600160c01b900467ffffffffffffffff166000610a818361340f565b90506004610a90836003614fbe565b610a9a9190615000565b610aa49083615027565b67ffffffffffffffff168167ffffffffffffffff161080610ad357506312e687c067ffffffffffffffff821611155b610b1f5760405162461bcd60e51b815260206004820152601c60248201527f496e746572657374207261746520696e637265617365203e20373525000000006044820152606401610a59565b426011546203f480610b31919061504f565b10610b7e5760405162461bcd60e51b815260206004820152601860248201527f557064617465206f6e6c792065766572792033206461797300000000000000006044820152606401610a59565b42601155601080546001600160c01b0316600160c01b67ffffffffffffffff8481169182029290921790925560408051918516825260208201929092527fa085058b12d3bd9dd32f87f0105f1996237757c583720c194afdd544ab736baa910160405180910390a1505050565b6000610bf561321e565b610bfd6124b9565b610c08848484613430565b949350505050565b6000610c1e82600f54613801565b92915050565b610c2c6124b9565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663017e7e586040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb09190614f8b565b601054604051636d289ce560e11b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b039081166004830152600160401b9092046001600160801b03166024820181905260006044830181905293945092917f0000000000000000000000000000000000000000000000000000000000000000169063da5139ca90606401602060405180830381865afa158015610d60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d849190615062565b604051633c6340f360e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301523060248301528581166044830152606482018390529192507f00000000000000000000000000000000000000000000000000000000000000009091169063f18d03cc90608401600060405180830381600087803b158015610e2157600080fd5b505af1158015610e35573d6000803e3d6000fd5b50506010805477ffffffffffffffffffffffffffffffff00000000000000001916905550506040518281526001600160a01b038416907f51396202093d5d912cb0ed4b8b0b54a6b6fca25abdb7f87eb8027dd11e8bffa99060200160405180910390a2505050565b600080610ea861321e565b610eb06124b9565b610eba848461397c565b90925090506000610ec9611f34565b915050610ed63382613801565b610f225760405162461bcd60e51b815260206004820152601760248201527f4368616d6265723a207573657220696e736f6c76656e740000000000000000006044820152606401610a59565b509250929050565b6003546001600160a01b031615610f835760405162461bcd60e51b815260206004820152601c60248201527f4368616d6265723a20616c726561647920696e697469616c697a6564000000006044820152606401610a59565b610f8f8183018361507b565b600881905560068290556007839055601080546001600160c01b0316600160c01b67ffffffffffffffff871602179055600360006004816005610fd28a82615193565b50815461010091820a6001600160a01b03818102199092169b8216029a909a17909155825491900a8089021990911698881602979097179096555050604080518082019091526001600160801b0380825260209091015250506000196009556003541690506110835760405162461bcd60e51b815260206004820152601160248201527f4368616d6265723a2062616420706169720000000000000000000000000000006044820152606401610a59565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166000818152600e602081815260408084208054600160ff19918216811790925530865282862080549091168217905581517f8da5cb5b0000000000000000000000000000000000000000000000000000000081529151909593949392638da5cb5b92600480820193918290030181865afa15801561112f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111539190614f8b565b6001600160a01b03908116825260208201929092526040908101600020805460ff19169315159390931790925560048054925163d6d7d52560e01b8152929091169163d6d7d525916111a89160059101615253565b60408051808303816000875af11580156111c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ea91906152ee565b600f55506111f66124b9565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611258573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127c9190614f8b565b6001600160a01b0316336001600160a01b0316146112dc5760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e65720000000000000000006044820152606401610a59565b6001600160a01b0382166113325760405162461bcd60e51b815260206004820152600e60248201527f696e76616c69642063616c6c65650000000000000000000000000000000000006044820152606401610a59565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415801561137d57506001600160a01b0382163014155b6113c95760405162461bcd60e51b815260206004820152600e60248201527f696e76616c69642063616c6c65650000000000000000000000000000000000006044820152606401610a59565b6001600160a01b0382166000818152600e6020908152604091829020805460ff191685151590811790915591519182527f2e07fc793c38fb148513d7ce2598eade436b44d3062703d7380944a8bf6e9d18910160405180910390a25050565b60008061143361321e565b60408051808201909152600080825260208201528760005b81811015611eba5760008b8b838181106114675761146761531c565b905060200201602081019061147c9190615341565b905083602001511580156114935750600a8160ff16105b156114a8576114a06124b9565b600160208501525b60091960ff8216016115085760008060008a8a868181106114cb576114cb61531c565b90506020028101906114dd919061535e565b8101906114ea91906153a5565b9250925092506115008282610318868d8d613e3e565b505050611ea7565b60011960ff82160161156e5760008060008a8a8681811061152b5761152b61531c565b905060200281019061153d919061535e565b81019061154a91906153a5565b9250925092506115658282611560868d8d613e3e565b613430565b50505050611ea7565b60031960ff8216016115d15760008089898581811061158f5761158f61531c565b90506020028101906115a1919061535e565b8101906115ae91906153e7565b915091506115c6816115c1848b8b613e3e565b613e65565b505060018452611ea7565b60041960ff82160161163a576000808989858181106115f2576115f261531c565b9050602002810190611604919061535e565b81019061161191906153e7565b9150915061162981611624848b8b613e3e565b61397c565b600188529098509650611ea7915050565b600a1960ff82160161170f5760008060008a8a8681811061165d5761165d61531c565b905060200281019061166f919061535e565b81019061167c919061540c565b92509250925060008061168d611f34565b9150915084158061169b5750815b80156116a657508381115b80156116b957508215806116b957508281105b6117055760405162461bcd60e51b815260206004820152601460248201527f4368616d6265723a2072617465206e6f74206f6b0000000000000000000000006044820152606401610a59565b5050505050611ea7565b60171960ff82160161182d576000806000806000808d8d898181106117365761173661531c565b9050602002810190611748919061535e565b8101906117559190615441565b6040517fc0a47c930000000000000000000000000000000000000000000000000000000081526001600160a01b0387811660048301528681166024830152851515604483015260ff851660648301526084820184905260a48201839052969c50949a50929850909650945092507f00000000000000000000000000000000000000000000000000000000000000009091169063c0a47c939060c401600060405180830381600087803b15801561180a57600080fd5b505af115801561181e573d6000803e3d6000fd5b50505050505050505050611ea7565b60131960ff8216016118c1576118b788888481811061184e5761184e61531c565b9050602002810190611860919061535e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92508d91508690508181106118a9576118a961531c565b905060200201358888613f80565b9096509450611ea7565b60141960ff821601611932576118b78888848181106118e2576118e261531c565b90506020028101906118f4919061535e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a925089915061409d9050565b60151960ff821601611a305760008060008a8a868181106119555761195561531c565b9050602002810190611967919061535e565b81019061197491906154af565b9250925092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f18d03cc8433856119b7868f8f613e3e565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015292841660248401529216604482015260648101919091526084015b600060405180830381600087803b158015611a1057600080fd5b505af1158015611a24573d6000803e3d6000fd5b50505050505050611ea7565b60161960ff821601611aca5760008060008a8a86818110611a5357611a5361531c565b9050602002810190611a65919061535e565b810190611a7291906154df565b9250925092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630fca8843843385856040518563ffffffff1660e01b81526004016119f69493929190615555565b601d1960ff821601611bad57600080611b578c8c86818110611aee57611aee61531c565b905060200201358b8b87818110611b0757611b0761531c565b9050602002810190611b19919061535e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92508c91506141a99050565b915091508060ff16600103611b815781806020019051810190611b7a9190615062565b9750611ba6565b8060ff16600203611ba65781806020019051810190611ba091906155f1565b90985096505b5050611ea7565b60051960ff821601611cf8576000888884818110611bcd57611bcd61531c565b9050602002810190611bdf919061535e565b810190611bec9190614cca565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663da5139ca7f0000000000000000000000000000000000000000000000000000000000000000611c7c611c4c858c8c613e3e565b60408051808201909152600b546001600160801b038082168352600160801b909104166020820152906001614398565b6040516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482015260016044820152606401602060405180830381865afa158015611ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf09190615062565b965050611ea7565b60061960ff821601611d77576000888884818110611d1857611d1861531c565b9050602002810190611d2a919061535e565b810190611d379190614cca565b9050611cf0611d47828989613e3e565b60408051808201909152600b546001600160801b038082168352600160801b909104166020820152906000614434565b601e1960ff821601611db457611daf888884818110611d9857611d9861531c565b9050602002810190611daa919061535e565b6144a9565b611ea7565b6000806000611e4f84888f8f89818110611dd057611dd061531c565b905060200201358e8e8a818110611de957611de961531c565b9050602002810190611dfb919061535e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060408051808201909152818152602081018290526060999198509650945050505050565b9250925092508096508160ff16600103611e7e5782806020019051810190611e779190615062565b9850611ea3565b8160ff16600203611ea35782806020019051810190611e9d91906155f1565b90995097505b5050505b5080611eb281615615565b91505061144b565b50815115611f27576000611ecc611f34565b915050611ed93382613801565b611f255760405162461bcd60e51b815260206004820152601760248201527f4368616d6265723a207573657220696e736f6c76656e740000000000000000006044820152606401610a59565b505b5050965096945050505050565b6004805460405163d6d7d52560e01b815260009283926001600160a01b03169163d6d7d52591611f679160059101615253565b60408051808303816000875af1158015611f85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa991906152ee565b90925090508115611ff057600f8190556040518181527fa4f3423f4dd10872d278f5fffb845f3639844d295fc8f472ce40b132406d49449060200160405180910390a19091565b50600f549091565b6120006144db565b61200a6000614535565b565b6005805461201990615113565b80601f016020809104026020016040519081016040528092919081815260200182805461204590615113565b80156120925780601f1061206757610100808354040283529160200191612092565b820191906000526020600020905b81548152906001019060200180831161207557829003601f168201915b505050505081565b60015433906001600160a01b0316811461211c5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a59565b61212581614535565b50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612186573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121aa9190614f8b565b6001600160a01b0316336001600160a01b03161461220a5760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e65720000000000000000006044820152606401610a59565b604051633de222bb60e21b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0381811660048401523060248401526000927f00000000000000000000000000000000000000000000000000000000000000009190911691635662311891839063f7888aec90604401602060405180830381865afa1580156122a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c99190615062565b6040516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482015260006044820152606401602060405180830381865afa158015612319573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061233d9190615062565b905081811161234c578061234e565b815b6040517f97da6d300000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015230602483015233604483015260648201839052600060848301529193507f0000000000000000000000000000000000000000000000000000000000000000909116906397da6d309060a40160408051808303816000875af115801561240d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243191906155f1565b50505050565b61243f61321e565b6124476124b9565b6124518282613e65565b600061245b611f34565b9150506124683382613801565b6124b45760405162461bcd60e51b815260206004820152601760248201527f4368616d6265723a207573657220696e736f6c76656e740000000000000000006044820152606401610a59565b505050565b6124c161321e565b6040805160608101825260105467ffffffffffffffff8082168084526001600160801b03600160401b8404166020850152600160c01b909204169282019290925290600090612510904261562e565b90508060000361251e575050565b67ffffffffffffffff4216825260408051808201909152600b546001600160801b038082168352600160801b90910416602082018190526000036125cd575050805160108054602084015160409094015167ffffffffffffffff908116600160c01b026001600160c01b036001600160801b03909616600160401b027fffffffffffffffff00000000000000000000000000000000000000000000000090931691909416171792909216179055565b6000670de0b6b3a76400006126108461260a876040015167ffffffffffffffff1686600001516001600160801b031661455b90919063ffffffff16565b9061455b565b61261a9190615641565b8251909150612636906001600160801b03908116908316613278565b6001600160801b039081168352602085015161265791908116908316613278565b6001600160801b0390811660208681018290528451858201518416600160801b0290841617600b558651601080546040808b015167ffffffffffffffff908116600160c01b026001600160c01b03600160401b9098027fffffffffffffffff00000000000000000000000000000000000000000000000090941691909516179190911794909416919091179055905191831682527f757b29336b38e0454cafcaa1fee2fc9e8677248c1cb1ba37dd3e2c60a87ab3ab910160405180910390a150505050565b6127246144db565b600180546001600160a01b03831673ffffffffffffffffffffffffffffffffffffffff1990911681179091556127626000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6127a26144db565b6001600160a01b0381166127f85760405162461bcd60e51b815260206004820152601360248201527f63616e6e6f7420626520302061646472657373000000000000000000000000006044820152606401610a59565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f8bc25725ca4ea10a36558b30cebb3baa6f7551e3fe58208d839e44189bdbe3e090600090a250565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d19190614f8b565b6001600160a01b0316336001600160a01b0316146129315760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e65720000000000000000006044820152606401610a59565b6040805180820182526001600160801b038481168083529084166020928301819052600160801b810282176009558351918252918101919091527ff1fce436bc22563026222b3b2bdc088cb69d25192974264114df12ab812628f6910160405180910390a15050565b6129a261321e565b60006129ac611f34565b9150506129b76124b9565b6003546040517f4ffe34db0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918291829182917f000000000000000000000000000000000000000000000000000000000000000090911690634ffe34db906024016040805180830381865afa158015612a43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a679190615655565b9050895160005b81811015612d0d5760008c8281518110612a8a57612a8a61531c565b60200260200101519050612a9e8189613801565b612cfa576001600160a01b0381166000908152600d60205260408120548d5181908f9086908110612ad157612ad161531c565b602002602001015111612afd578d8481518110612af057612af061531c565b6020026020010151612aff565b805b60408051808201909152600b546001600160801b038082168352600160801b909104166020820152909250600090612b38908483614398565b90506000612b80612b54670de0b6b3a7640000620186a06156b4565b612b6d8e61260a6007548761455b90919063ffffffff16565b612b779190615641565b89906000614434565b9050612b8c8385614567565b6001600160a01b0386166000908152600d6020908152604080832093909355600c90522054612bbb9082614567565b6001600160a01b0386166000908152600c60205260409020558e6001600160a01b0316856001600160a01b03167f77f19d2489899bac4076fc1c140f57208d84c91aca70c5bfce9460130bcc5c5583604051612c1991815260200190565b60405180910390a360408051838152602081018690526001600160a01b0387169133917fa7489af36ce0dad0b30ae45d2d29c07e996839e7ad59e955a9d33ec30372fdeb910160405180910390a38e6001600160a01b0316856001600160a01b0316336001600160a01b03167f66b108dc29b952efc76dccea9b82dce6b59fab4d9af73d8dcc9789afcad5daf6848689604051612cc9939291909283526020830191909152604082015260600190565b60405180910390a4612cdb8b82613278565b9a50612ce78a83613278565b9950612cf38985613278565b9850505050505b5080612d0581615615565b915050612a6e565b5083600003612d5e5760405162461bcd60e51b815260206004820152601860248201527f4368616d6265723a20616c6c2061726520736f6c76656e7400000000000000006044820152606401610a59565b600b54612d74906001600160801b031685614567565b600b80547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001600160801b039283161790819055612dbd91600160801b9091041684614567565b600b80546001600160801b03928316600160801b029216919091179055600a54612de79086614567565b600a8190555060006064612e23600a61260a88620186a0612e136007548c61455b90919063ffffffff16565b612e1d9190615641565b90614567565b612e2d9190615641565b9050612e398582613278565b601054909550612e5990600160401b90046001600160801b031682613278565b601080546001600160801b0392909216600160401b0277ffffffffffffffffffffffffffffffff00000000000000001990921691909117905550604051636d289ce560e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260248201869052600160448301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063da5139ca90606401602060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f509190615062565b600354604051633c6340f360e21b81526001600160a01b0391821660048201523060248201528c82166044820152606481018990529192507f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612fce57600080fd5b505af1158015612fe2573d6000803e3d6000fd5b505050506001600160a01b038916156130a557886001600160a01b031663a5d4096b600360009054906101000a90046001600160a01b03167f000000000000000000000000000000000000000000000000000000000000000033858b8e6040518763ffffffff1660e01b8152600401613060969594939291906156cb565b60408051808303816000875af115801561307e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a291906155f1565b50505b604051636d289ce560e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260248201879052600160448301527f0000000000000000000000000000000000000000000000000000000000000000169063da5139ca90606401602060405180830381865afa158015613139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061315d9190615062565b604051633c6340f360e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152336024830152306044830152606482018390529192507f00000000000000000000000000000000000000000000000000000000000000009091169063f18d03cc90608401600060405180830381600087803b1580156131f857600080fd5b505af115801561320c573d6000803e3d6000fd5b50505050505050505050505050505050565b600154600160a01b900460ff161561200a5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610a59565b6000613284828461504f565b9392505050565b801561337b57604051633de222bb60e21b81526001600160a01b0385811660048301523060248301526133279184917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015613303573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1d9190615062565b8311156133765760405162461bcd60e51b815260206004820152601660248201527f4368616d6265723a20536b696d20746f6f206d756368000000000000000000006044820152606401610a59565b612431565b604051633c6340f360e21b81526001600160a01b038581166004830152336024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b1580156133f157600080fd5b505af1158015613405573d6000803e3d6000fd5b5050505050505050565b60006127106134266312e687c061ffff8516614fbe565b610c1e9190615000565b600061343a61321e565b60408051808201909152600b546001600160801b038082168352600160801b90910416602082015261346e90836001614573565b81516020928301516001600160801b03908116600160801b02911617600b556001600160a01b0386166000908152600d9092526040909120549091506134b49083614567565b6001600160a01b038581166000908152600d6020526040808220939093559151636d289ce560e11b81527f00000000000000000000000000000000000000000000000000000000000000008216600482015260248101849052600160448201527f00000000000000000000000000000000000000000000000000000000000000009091169063da5139ca90606401602060405180830381865afa15801561355f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135839190615062565b90506135d96001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000846145dc565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f18d03cc7f0000000000000000000000000000000000000000000000000000000000000000866136345733613656565b7f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160e01b031960e085901b1681526001600160a01b0392831660048201529116602482015230604482015260648101849052608401600060405180830381600087803b1580156136ab57600080fd5b505af11580156136bf573d6000803e3d6000fd5b505060405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152600060248301527f000000000000000000000000000000000000000000000000000000000000000016925063095ea7b391506044016020604051808303816000875af1158015613752573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137769190615717565b50846001600160a01b03168461378c57336137ae565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03167fa7489af36ce0dad0b30ae45d2d29c07e996839e7ad59e955a9d33ec30372fdeb84866040516137f1929190918252602082015260400190565b60405180910390a3509392505050565b6001600160a01b0382166000908152600d602052604081205480820361382b576001915050610c1e565b6001600160a01b0384166000908152600c60205260408120549081900361385757600092505050610c1e565b60408051808201909152600b546001600160801b03808216808452600160801b90920416602083018190529061389490879061260a90879061455b565b61389e9190615641565b6003546006546001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116926356623118929116906138fc9061260a6138f5620186a0670de0b6b3a7640000615641565b899061455b565b6040516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482015260006044820152606401602060405180830381865afa15801561394c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139709190615062565b10159695505050505050565b60008061398761321e565b6000620186a06139a26008548661455b90919063ffffffff16565b6139ac9190615641565b90506139eb6139bb8583613278565b60408051808201909152600b546001600160801b038082168352600160801b909104166020820152906001614748565b81516020909201516001600160801b03908116600160801b02921691909117600b559250613a636001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000866145dc565b604080518082019091526009546001600160801b03808216808452600160801b90920481166020840152600b54161115613adf5760405162461bcd60e51b815260206004820152601460248201527f426f72726f77204c696d697420726561636865640000000000000000000000006044820152606401610a59565b601054613b0090600160401b90046001600160801b03908116908416613278565b601080546001600160801b0392909216600160401b0277ffffffffffffffffffffffffffffffff000000000000000019909216919091179055336000908152600d6020526040812054613b539086613278565b905081602001516001600160801b0316811115613bb25760405162461bcd60e51b815260206004820152601460248201527f426f72726f77204c696d697420726561636865640000000000000000000000006044820152606401610a59565b336000908152600d602052604080822083905551636d289ce560e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820189905260448201929092527f00000000000000000000000000000000000000000000000000000000000000009091169063da5139ca90606401602060405180830381865afa158015613c5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c7e9190615062565b604051633c6340f360e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301523060248301528981166044830152606482018390529195507f00000000000000000000000000000000000000000000000000000000000000009091169063f18d03cc90608401600060405180830381600087803b158015613d1b57600080fd5b505af1158015613d2f573d6000803e3d6000fd5b505060405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152600060248301527f000000000000000000000000000000000000000000000000000000000000000016925063095ea7b391506044016020604051808303816000875af1158015613dc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613de69190615717565b506001600160a01b038716337f1298465c3dfc2aaba2a18da010d6b969a7e06f6f9dbcc96798660535389d1e7c613e1d8987613278565b60408051918252602082018a90520160405180910390a35050509250929050565b600080841215613e5d576000198414613e575781610c08565b82610c08565b509192915050565b613e6d61321e565b336000908152600c6020526040902054613e879082614567565b336000908152600c6020526040902055600a54613ea49082614567565b600a556040518181526001600160a01b0383169033907f77f19d2489899bac4076fc1c140f57208d84c91aca70c5bfce9460130bcc5c559060200160405180910390a3600354604051633c6340f360e21b81526001600160a01b0391821660048201523060248201528382166044820152606481018390527f00000000000000000000000000000000000000000000000000000000000000009091169063f18d03cc90608401600060405180830381600087803b158015613f6457600080fd5b505af1158015613f78573d6000803e3d6000fd5b505050505050565b600080613f8b61321e565b60008060008089806020019051810190613fa59190615734565b9350935093509350613fb8828989613e3e565b9150613fc5818989613e3e565b6040517f02b9446c0000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152336024830152858116604483015260648201859052608482018390529192507f0000000000000000000000000000000000000000000000000000000000000000909116906302b9446c908b9060a401604080518083038185885af1158015614067573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061408c91906155f1565b955095505050505094509492505050565b6000806140a861321e565b600080600080888060200190518101906140c29190615734565b93509350935093507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166397da6d30853386614107878e8e613e3e565b614112878f8f613e3e565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015293851660248501529390911660448301526064820152608481019190915260a40160408051808303816000875af1158015614175573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061419991906155f1565b9550955050505050935093915050565b606060006141b561321e565b6000806000806000898060200190518101906141d19190615787565b945094509450945094508280156141e6575081155b156142145783896040516020016141fe929190615845565b604051602081830303815290604052935061426d565b8215801561421f5750815b156142375783886040516020016141fe929190615845565b8280156142415750815b1561426d5783898960405160200161425b93929190615867565b60405160208183030381529060405293505b6001600160a01b0385166000908152600e602052604090205460ff16156142d65760405162461bcd60e51b815260206004820152601360248201527f4368616d6265723a2063616e27742063616c6c000000000000000000000000006044820152606401610a59565b600080866001600160a01b03168d876040516142f2919061588e565b60006040518083038185875af1925050503d806000811461432f576040519150601f19603f3d011682016040523d82523d6000602084013e614334565b606091505b5091509150816143865760405162461bcd60e51b815260206004820152601460248201527f4368616d6265723a2063616c6c206661696c65640000000000000000000000006044820152606401610a59565b9c919b50909950505050505050505050565b600083602001516001600160801b03166000036143b6575081613284565b602084015184516001600160801b03918216916143d49116856156b4565b6143de9190615641565b905081801561441c57508284600001516001600160801b031685602001516001600160801b03168361441091906156b4565b61441a9190615641565b105b15613284578061442b81615615565b95945050505050565b82516000906001600160801b0316810361444f575081613284565b835160208501516001600160801b039182169161446d9116856156b4565b6144779190615641565b905081801561441c57508284602001516001600160801b031685600001516001600160801b03168361441091906156b4565b6000808080806144bb86880188614ed9565b945094509450945094506144d2858585858561299a565b50505050505050565b6000546001600160a01b0316331461200a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a59565b6001805473ffffffffffffffffffffffffffffffffffffffff191690556121258161479d565b600061328482846156b4565b6000613284828461562e565b60408051808201909152600080825260208201526000614594858585614398565b905080856000018181516145a891906158aa565b6001600160801b03169052506020850180518591906145c89083906158aa565b6001600160801b0316905250939492505050565b80158061466f57506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015614649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061466d9190615062565b155b6146e15760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610a59565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663095ea7b360e01b1790526124b49084906147fa565b60408051808201909152600080825260208201526000614769858585614434565b9050838560000181815161477d91906158ca565b6001600160801b03169052506020850180518291906145c89083906158ca565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600061484f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166148e29092919063ffffffff16565b90508051600014806148705750808060200190518101906148709190615717565b6124b45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a59565b6060610c08848460008585600080866001600160a01b03168587604051614909919061588e565b60006040518083038185875af1925050503d8060008114614946576040519150601f19603f3d011682016040523d82523d6000602084013e61494b565b606091505b509150915061495c87838387614967565b979650505050505050565b606083156149d65782516000036149cf576001600160a01b0385163b6149cf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a59565b5081610c08565b610c0883838151156149eb5781518083602001fd5b8060405162461bcd60e51b8152600401610a599190614cb7565b6001600160a01b038116811461212557600080fd5b801515811461212557600080fd5b600080600060608486031215614a3d57600080fd5b8335614a4881614a05565b92506020840135614a5881614a1a565b929592945050506040919091013590565b600060208284031215614a7b57600080fd5b813561ffff8116811461328457600080fd5b600060208284031215614a9f57600080fd5b813561328481614a05565b60008060408385031215614abd57600080fd5b8235614ac881614a05565b946020939093013593505050565b60008060208385031215614ae957600080fd5b823567ffffffffffffffff80821115614b0157600080fd5b818501915085601f830112614b1557600080fd5b813581811115614b2457600080fd5b866020828501011115614b3657600080fd5b60209290920196919550909350505050565b60008060408385031215614b5b57600080fd5b8235614b6681614a05565b91506020830135614b7681614a1a565b809150509250929050565b60008083601f840112614b9357600080fd5b50813567ffffffffffffffff811115614bab57600080fd5b6020830191508360208260051b8501011115614bc657600080fd5b9250929050565b60008060008060008060608789031215614be657600080fd5b863567ffffffffffffffff80821115614bfe57600080fd5b614c0a8a838b01614b81565b90985096506020890135915080821115614c2357600080fd5b614c2f8a838b01614b81565b90965094506040890135915080821115614c4857600080fd5b50614c5589828a01614b81565b979a9699509497509295939492505050565b60005b83811015614c82578181015183820152602001614c6a565b50506000910152565b60008151808452614ca3816020860160208601614c67565b601f01601f19169290920160200192915050565b6020815260006132846020830184614c8b565b600060208284031215614cdc57600080fd5b5035919050565b6001600160801b038116811461212557600080fd5b60008060408385031215614d0b57600080fd5b8235614d1681614ce3565b91506020830135614b7681614ce3565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614d6557614d65614d26565b604052919050565b600067ffffffffffffffff821115614d8757614d87614d26565b5060051b60200190565b600082601f830112614da257600080fd5b81356020614db7614db283614d6d565b614d3c565b82815260059290921b84018101918181019086841115614dd657600080fd5b8286015b84811015614dfa578035614ded81614a05565b8352918301918301614dda565b509695505050505050565b600082601f830112614e1657600080fd5b81356020614e26614db283614d6d565b82815260059290921b84018101918181019086841115614e4557600080fd5b8286015b84811015614dfa5780358352918301918301614e49565b600067ffffffffffffffff821115614e7a57614e7a614d26565b50601f01601f191660200190565b600082601f830112614e9957600080fd5b8135614ea7614db282614e60565b818152846020838601011115614ebc57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a08688031215614ef157600080fd5b853567ffffffffffffffff80821115614f0957600080fd5b614f1589838a01614d91565b96506020880135915080821115614f2b57600080fd5b614f3789838a01614e05565b955060408801359150614f4982614a05565b909350606087013590614f5b82614a05565b90925060808701359080821115614f7157600080fd5b50614f7e88828901614e88565b9150509295509295909350565b600060208284031215614f9d57600080fd5b815161328481614a05565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff818116838216028082169190828114614fe257614fe2614fa8565b505092915050565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061501b5761501b614fea565b92169190910492915050565b67ffffffffffffffff81811683821601908082111561504857615048614fa8565b5092915050565b80820180821115610c1e57610c1e614fa8565b60006020828403121561507457600080fd5b5051919050565b600080600080600080600060e0888a03121561509657600080fd5b87356150a181614a05565b965060208801356150b181614a05565b9550604088013567ffffffffffffffff808211156150ce57600080fd5b6150da8b838c01614e88565b965060608a0135915080821682146150f157600080fd5b509699959850939660808101359560a0820135955060c0909101359350915050565b600181811c9082168061512757607f821691505b60208210810361514757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156124b457600081815260208120601f850160051c810160208610156151745750805b601f850160051c820191505b81811015613f7857828155600101615180565b815167ffffffffffffffff8111156151ad576151ad614d26565b6151c1816151bb8454615113565b8461514d565b602080601f8311600181146151f657600084156151de5750858301515b600019600386901b1c1916600185901b178555613f78565b600085815260208120601f198616915b8281101561522557888601518255948401946001909101908401615206565b50858210156152435787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083526000845461526781615113565b8084870152604060018084166000811461528857600181146152a2576152d0565b60ff1985168984015283151560051b8901830195506152d0565b896000528660002060005b858110156152c85781548b82018601529083019088016152ad565b8a0184019650505b509398975050505050505050565b80516152e981614a1a565b919050565b6000806040838503121561530157600080fd5b825161530c81614a1a565b6020939093015192949293505050565b634e487b7160e01b600052603260045260246000fd5b60ff8116811461212557600080fd5b60006020828403121561535357600080fd5b813561328481615332565b6000808335601e1984360301811261537557600080fd5b83018035915067ffffffffffffffff82111561539057600080fd5b602001915036819003821315614bc657600080fd5b6000806000606084860312156153ba57600080fd5b8335925060208401356153cc81614a05565b915060408401356153dc81614a1a565b809150509250925092565b600080604083850312156153fa57600080fd5b823591506020830135614b7681614a05565b60008060006060848603121561542157600080fd5b833561542c81614a1a565b95602085013595506040909401359392505050565b60008060008060008060c0878903121561545a57600080fd5b863561546581614a05565b9550602087013561547581614a05565b9450604087013561548581614a1a565b9350606087013561549581615332565b9598949750929560808101359460a0909101359350915050565b6000806000606084860312156154c457600080fd5b83356154cf81614a05565b92506020840135614a5881614a05565b6000806000606084860312156154f457600080fd5b83356154ff81614a05565b9250602084013567ffffffffffffffff8082111561551c57600080fd5b61552887838801614d91565b9350604086013591508082111561553e57600080fd5b5061554b86828701614e05565b9150509250925092565b6000608082016001600160a01b0380881684526020818816818601526080604086015282875180855260a087019150828901945060005b818110156155aa57855185168352948301949183019160010161558c565b5050858103606087015286518082529082019350915080860160005b838110156155e2578151855293820193908201906001016155c6565b50929998505050505050505050565b6000806040838503121561560457600080fd5b505080516020909101519092909150565b60006001820161562757615627614fa8565b5060010190565b81810381811115610c1e57610c1e614fa8565b60008261565057615650614fea565b500490565b60006040828403121561566757600080fd5b6040516040810181811067ffffffffffffffff8211171561568a5761568a614d26565b604052825161569881614ce3565b815260208301516156a881614ce3565b60208201529392505050565b8082028115828204841417610c1e57610c1e614fa8565b60006001600160a01b038089168352808816602084015280871660408401525084606083015283608083015260c060a083015261570b60c0830184614c8b565b98975050505050505050565b60006020828403121561572957600080fd5b815161328481614a1a565b6000806000806080858703121561574a57600080fd5b845161575581614a05565b602086015190945061576681614a05565b6040860151606090960151949790965092505050565b80516152e981615332565b600080600080600060a0868803121561579f57600080fd5b85516157aa81614a05565b602087015190955067ffffffffffffffff8111156157c757600080fd5b8601601f810188136157d857600080fd5b80516157e6614db282614e60565b8181528960208385010111156157fb57600080fd5b61580c826020830160208601614c67565b955061581d915050604087016152de565b925061582b606087016152de565b91506158396080870161577c565b90509295509295909350565b60008351615857818460208801614c67565b9190910191825250602001919050565b60008451615879818460208901614c67565b91909101928352506020820152604001919050565b600082516158a0818460208701614c67565b9190910192915050565b6001600160801b0382811682821603908082111561504857615048614fa8565b6001600160801b0381811683821601908082111561504857615048614fa856fea2646970667358221220fe38e6173e208d58a4aef3ddca55a4b42f09c43eca87ea6b80ee8386e2903b5764736f6c63430008130033000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd643966000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd8
Deployed Bytecode
0x6080604052600436106102bb5760003560e01c806374645ff31161016e578063c7ee2a7b116100cb578063e551d11d1161007f578063f46901ed11610064578063f46901ed14610830578063f7dad43414610850578063ff6ff84b1461087057600080fd5b8063e551d11d146107e5578063f2fde38b1461081057600080fd5b8063d8dfeb45116100b0578063d8dfeb4514610777578063dbac26e914610797578063e30c3978146107c757600080fd5b8063c7ee2a7b1461072d578063cd446e221461074357600080fd5b8063876467f811610122578063a53aeb4e11610107578063a53aeb4e146106ce578063aba024f4146106e3578063b6f173d1146106f957600080fd5b8063876467f8146106905780638da5cb5b146106b057600080fd5b80637dc0d1d0116101535780637dc0d1d01461060557806380623444146106255780638285ef401461064557600080fd5b806374645ff3146105ce57806379ba5097146105f057600080fd5b806348e4163e1161021c5780635c975abb116101d05780636b2ace87116101b55780636b2ace871461056f5780636ec097fb146105a3578063715018a6146105b957600080fd5b80635c975abb14610524578063673a7e281461054357600080fd5b80634ddf47d4116102015780634ddf47d4146104de578063517cf6a3146104f1578063568d8cd91461051157600080fd5b806348e4163e1461047c5780634b8a3529146104a957600080fd5b806338b51ce11161027357806345fe329f1161025857806345fe329f146103e0578063473e3ce714610451578063476343ee1461046757600080fd5b806338b51ce11461039a5780633ba0b9a9146103ca57600080fd5b80630ed6f9be116102a45780630ed6f9be1461031f57806315294c401461033f5780631c9e379b1461036d57600080fd5b8063017e7e58146102c057806302c1a42b146102fd575b600080fd5b3480156102cc57600080fd5b506002546102e0906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561030957600080fd5b5061031d610318366004614a28565b610890565b005b34801561032b57600080fd5b5061031d61033a366004614a69565b61097b565b34801561034b57600080fd5b5061035f61035a366004614a28565b610beb565b6040519081526020016102f4565b34801561037957600080fd5b5061035f610388366004614a8d565b600c6020526000908152604090205481565b3480156103a657600080fd5b506103ba6103b5366004614a8d565b610c10565b60405190151581526020016102f4565b3480156103d657600080fd5b5061035f600f5481565b3480156103ec57600080fd5b5060105461041e9067ffffffffffffffff808216916001600160801b03600160401b82041691600160c01b9091041683565b6040805167ffffffffffffffff94851681526001600160801b0390931660208401529216918101919091526060016102f4565b34801561045d57600080fd5b5061035f600a5481565b34801561047357600080fd5b5061031d610c24565b34801561048857600080fd5b5061035f610497366004614a8d565b600d6020526000908152604090205481565b3480156104b557600080fd5b506104c96104c4366004614aaa565b610e9d565b604080519283526020830191909152016102f4565b61031d6104ec366004614ad6565b610f2a565b3480156104fd57600080fd5b5061031d61050c366004614b48565b6111fa565b6104c961051f366004614bcd565b611428565b34801561053057600080fd5b50600154600160a01b900460ff166103ba565b34801561054f57600080fd5b50610558611f34565b6040805192151583526020830191909152016102f4565b34801561057b57600080fd5b506102e07f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd64396681565b3480156105af57600080fd5b5061035f60075481565b3480156105c557600080fd5b5061031d611ff8565b3480156105da57600080fd5b506105e361200c565b6040516102f49190614cb7565b3480156105fc57600080fd5b5061031d61209a565b34801561061157600080fd5b506004546102e0906001600160a01b031681565b34801561063157600080fd5b5061031d610640366004614cca565b612128565b34801561065157600080fd5b50600b54610670906001600160801b0380821691600160801b90041682565b604080516001600160801b039384168152929091166020830152016102f4565b34801561069c57600080fd5b5061031d6106ab366004614aaa565b612437565b3480156106bc57600080fd5b506000546001600160a01b03166102e0565b3480156106da57600080fd5b5061031d6124b9565b3480156106ef57600080fd5b5061035f60085481565b34801561070557600080fd5b506102e07f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd881565b34801561073957600080fd5b5061035f60065481565b34801561074f57600080fd5b506102e07f00000000000000000000000045e15d1e4f92f28a916f4f2971ad9adc278e148b81565b34801561078357600080fd5b506003546102e0906001600160a01b031681565b3480156107a357600080fd5b506103ba6107b2366004614a8d565b600e6020526000908152604090205460ff1681565b3480156107d357600080fd5b506001546001600160a01b03166102e0565b3480156107f157600080fd5b50600954610670906001600160801b0380821691600160801b90041682565b34801561081c57600080fd5b5061031d61082b366004614a8d565b61271c565b34801561083c57600080fd5b5061031d61084b366004614a8d565b61279a565b34801561085c57600080fd5b5061031d61086b366004614cf8565b61284f565b34801561087c57600080fd5b5061031d61088b366004614ed9565b61299a565b61089861321e565b6001600160a01b0383166000908152600c60205260409020546108bb9082613278565b6001600160a01b0384166000908152600c6020526040902055600a546108e18183613278565b600a556003546108fc906001600160a01b031683838661328b565b836001600160a01b0316836109115733610933565b7f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439665b6001600160a01b03167f6278fc0b0b834dd63a777a95fa7ad401bb418e9abd9e2d2fea56de8d614544c98460405161096d91815260200190565b60405180910390a350505050565b7f00000000000000000000000045e15d1e4f92f28a916f4f2971ad9adc278e148b6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fd9190614f8b565b6001600160a01b0316336001600160a01b031614610a625760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e657200000000000000000060448201526064015b60405180910390fd5b601054600160c01b900467ffffffffffffffff166000610a818361340f565b90506004610a90836003614fbe565b610a9a9190615000565b610aa49083615027565b67ffffffffffffffff168167ffffffffffffffff161080610ad357506312e687c067ffffffffffffffff821611155b610b1f5760405162461bcd60e51b815260206004820152601c60248201527f496e746572657374207261746520696e637265617365203e20373525000000006044820152606401610a59565b426011546203f480610b31919061504f565b10610b7e5760405162461bcd60e51b815260206004820152601860248201527f557064617465206f6e6c792065766572792033206461797300000000000000006044820152606401610a59565b42601155601080546001600160c01b0316600160c01b67ffffffffffffffff8481169182029290921790925560408051918516825260208201929092527fa085058b12d3bd9dd32f87f0105f1996237757c583720c194afdd544ab736baa910160405180910390a1505050565b6000610bf561321e565b610bfd6124b9565b610c08848484613430565b949350505050565b6000610c1e82600f54613801565b92915050565b610c2c6124b9565b60007f00000000000000000000000045e15d1e4f92f28a916f4f2971ad9adc278e148b6001600160a01b031663017e7e586040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb09190614f8b565b601054604051636d289ce560e11b81527f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd86001600160a01b039081166004830152600160401b9092046001600160801b03166024820181905260006044830181905293945092917f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd643966169063da5139ca90606401602060405180830381865afa158015610d60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d849190615062565b604051633c6340f360e21b81526001600160a01b037f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd8811660048301523060248301528581166044830152606482018390529192507f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439669091169063f18d03cc90608401600060405180830381600087803b158015610e2157600080fd5b505af1158015610e35573d6000803e3d6000fd5b50506010805477ffffffffffffffffffffffffffffffff00000000000000001916905550506040518281526001600160a01b038416907f51396202093d5d912cb0ed4b8b0b54a6b6fca25abdb7f87eb8027dd11e8bffa99060200160405180910390a2505050565b600080610ea861321e565b610eb06124b9565b610eba848461397c565b90925090506000610ec9611f34565b915050610ed63382613801565b610f225760405162461bcd60e51b815260206004820152601760248201527f4368616d6265723a207573657220696e736f6c76656e740000000000000000006044820152606401610a59565b509250929050565b6003546001600160a01b031615610f835760405162461bcd60e51b815260206004820152601c60248201527f4368616d6265723a20616c726561647920696e697469616c697a6564000000006044820152606401610a59565b610f8f8183018361507b565b600881905560068290556007839055601080546001600160c01b0316600160c01b67ffffffffffffffff871602179055600360006004816005610fd28a82615193565b50815461010091820a6001600160a01b03818102199092169b8216029a909a17909155825491900a8089021990911698881602979097179096555050604080518082019091526001600160801b0380825260209091015250506000196009556003541690506110835760405162461bcd60e51b815260206004820152601160248201527f4368616d6265723a2062616420706169720000000000000000000000000000006044820152606401610a59565b7f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439666001600160a01b03166000818152600e602081815260408084208054600160ff19918216811790925530865282862080549091168217905581517f8da5cb5b0000000000000000000000000000000000000000000000000000000081529151909593949392638da5cb5b92600480820193918290030181865afa15801561112f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111539190614f8b565b6001600160a01b03908116825260208201929092526040908101600020805460ff19169315159390931790925560048054925163d6d7d52560e01b8152929091169163d6d7d525916111a89160059101615253565b60408051808303816000875af11580156111c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ea91906152ee565b600f55506111f66124b9565b5050565b7f00000000000000000000000045e15d1e4f92f28a916f4f2971ad9adc278e148b6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611258573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127c9190614f8b565b6001600160a01b0316336001600160a01b0316146112dc5760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e65720000000000000000006044820152606401610a59565b6001600160a01b0382166113325760405162461bcd60e51b815260206004820152600e60248201527f696e76616c69642063616c6c65650000000000000000000000000000000000006044820152606401610a59565b7f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439666001600160a01b0316826001600160a01b03161415801561137d57506001600160a01b0382163014155b6113c95760405162461bcd60e51b815260206004820152600e60248201527f696e76616c69642063616c6c65650000000000000000000000000000000000006044820152606401610a59565b6001600160a01b0382166000818152600e6020908152604091829020805460ff191685151590811790915591519182527f2e07fc793c38fb148513d7ce2598eade436b44d3062703d7380944a8bf6e9d18910160405180910390a25050565b60008061143361321e565b60408051808201909152600080825260208201528760005b81811015611eba5760008b8b838181106114675761146761531c565b905060200201602081019061147c9190615341565b905083602001511580156114935750600a8160ff16105b156114a8576114a06124b9565b600160208501525b60091960ff8216016115085760008060008a8a868181106114cb576114cb61531c565b90506020028101906114dd919061535e565b8101906114ea91906153a5565b9250925092506115008282610318868d8d613e3e565b505050611ea7565b60011960ff82160161156e5760008060008a8a8681811061152b5761152b61531c565b905060200281019061153d919061535e565b81019061154a91906153a5565b9250925092506115658282611560868d8d613e3e565b613430565b50505050611ea7565b60031960ff8216016115d15760008089898581811061158f5761158f61531c565b90506020028101906115a1919061535e565b8101906115ae91906153e7565b915091506115c6816115c1848b8b613e3e565b613e65565b505060018452611ea7565b60041960ff82160161163a576000808989858181106115f2576115f261531c565b9050602002810190611604919061535e565b81019061161191906153e7565b9150915061162981611624848b8b613e3e565b61397c565b600188529098509650611ea7915050565b600a1960ff82160161170f5760008060008a8a8681811061165d5761165d61531c565b905060200281019061166f919061535e565b81019061167c919061540c565b92509250925060008061168d611f34565b9150915084158061169b5750815b80156116a657508381115b80156116b957508215806116b957508281105b6117055760405162461bcd60e51b815260206004820152601460248201527f4368616d6265723a2072617465206e6f74206f6b0000000000000000000000006044820152606401610a59565b5050505050611ea7565b60171960ff82160161182d576000806000806000808d8d898181106117365761173661531c565b9050602002810190611748919061535e565b8101906117559190615441565b6040517fc0a47c930000000000000000000000000000000000000000000000000000000081526001600160a01b0387811660048301528681166024830152851515604483015260ff851660648301526084820184905260a48201839052969c50949a50929850909650945092507f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439669091169063c0a47c939060c401600060405180830381600087803b15801561180a57600080fd5b505af115801561181e573d6000803e3d6000fd5b50505050505050505050611ea7565b60131960ff8216016118c1576118b788888481811061184e5761184e61531c565b9050602002810190611860919061535e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92508d91508690508181106118a9576118a961531c565b905060200201358888613f80565b9096509450611ea7565b60141960ff821601611932576118b78888848181106118e2576118e261531c565b90506020028101906118f4919061535e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a925089915061409d9050565b60151960ff821601611a305760008060008a8a868181106119555761195561531c565b9050602002810190611967919061535e565b81019061197491906154af565b9250925092507f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439666001600160a01b031663f18d03cc8433856119b7868f8f613e3e565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015292841660248401529216604482015260648101919091526084015b600060405180830381600087803b158015611a1057600080fd5b505af1158015611a24573d6000803e3d6000fd5b50505050505050611ea7565b60161960ff821601611aca5760008060008a8a86818110611a5357611a5361531c565b9050602002810190611a65919061535e565b810190611a7291906154df565b9250925092507f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439666001600160a01b0316630fca8843843385856040518563ffffffff1660e01b81526004016119f69493929190615555565b601d1960ff821601611bad57600080611b578c8c86818110611aee57611aee61531c565b905060200201358b8b87818110611b0757611b0761531c565b9050602002810190611b19919061535e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92508c91506141a99050565b915091508060ff16600103611b815781806020019051810190611b7a9190615062565b9750611ba6565b8060ff16600203611ba65781806020019051810190611ba091906155f1565b90985096505b5050611ea7565b60051960ff821601611cf8576000888884818110611bcd57611bcd61531c565b9050602002810190611bdf919061535e565b810190611bec9190614cca565b90507f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439666001600160a01b031663da5139ca7f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd8611c7c611c4c858c8c613e3e565b60408051808201909152600b546001600160801b038082168352600160801b909104166020820152906001614398565b6040516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482015260016044820152606401602060405180830381865afa158015611ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf09190615062565b965050611ea7565b60061960ff821601611d77576000888884818110611d1857611d1861531c565b9050602002810190611d2a919061535e565b810190611d379190614cca565b9050611cf0611d47828989613e3e565b60408051808201909152600b546001600160801b038082168352600160801b909104166020820152906000614434565b601e1960ff821601611db457611daf888884818110611d9857611d9861531c565b9050602002810190611daa919061535e565b6144a9565b611ea7565b6000806000611e4f84888f8f89818110611dd057611dd061531c565b905060200201358e8e8a818110611de957611de961531c565b9050602002810190611dfb919061535e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060408051808201909152818152602081018290526060999198509650945050505050565b9250925092508096508160ff16600103611e7e5782806020019051810190611e779190615062565b9850611ea3565b8160ff16600203611ea35782806020019051810190611e9d91906155f1565b90995097505b5050505b5080611eb281615615565b91505061144b565b50815115611f27576000611ecc611f34565b915050611ed93382613801565b611f255760405162461bcd60e51b815260206004820152601760248201527f4368616d6265723a207573657220696e736f6c76656e740000000000000000006044820152606401610a59565b505b5050965096945050505050565b6004805460405163d6d7d52560e01b815260009283926001600160a01b03169163d6d7d52591611f679160059101615253565b60408051808303816000875af1158015611f85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa991906152ee565b90925090508115611ff057600f8190556040518181527fa4f3423f4dd10872d278f5fffb845f3639844d295fc8f472ce40b132406d49449060200160405180910390a19091565b50600f549091565b6120006144db565b61200a6000614535565b565b6005805461201990615113565b80601f016020809104026020016040519081016040528092919081815260200182805461204590615113565b80156120925780601f1061206757610100808354040283529160200191612092565b820191906000526020600020905b81548152906001019060200180831161207557829003601f168201915b505050505081565b60015433906001600160a01b0316811461211c5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a59565b61212581614535565b50565b7f00000000000000000000000045e15d1e4f92f28a916f4f2971ad9adc278e148b6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612186573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121aa9190614f8b565b6001600160a01b0316336001600160a01b03161461220a5760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e65720000000000000000006044820152606401610a59565b604051633de222bb60e21b81527f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd86001600160a01b0381811660048401523060248401526000927f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439669190911691635662311891839063f7888aec90604401602060405180830381865afa1580156122a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c99190615062565b6040516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482015260006044820152606401602060405180830381865afa158015612319573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061233d9190615062565b905081811161234c578061234e565b815b6040517f97da6d300000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd88116600483015230602483015233604483015260648201839052600060848301529193507f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd643966909116906397da6d309060a40160408051808303816000875af115801561240d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243191906155f1565b50505050565b61243f61321e565b6124476124b9565b6124518282613e65565b600061245b611f34565b9150506124683382613801565b6124b45760405162461bcd60e51b815260206004820152601760248201527f4368616d6265723a207573657220696e736f6c76656e740000000000000000006044820152606401610a59565b505050565b6124c161321e565b6040805160608101825260105467ffffffffffffffff8082168084526001600160801b03600160401b8404166020850152600160c01b909204169282019290925290600090612510904261562e565b90508060000361251e575050565b67ffffffffffffffff4216825260408051808201909152600b546001600160801b038082168352600160801b90910416602082018190526000036125cd575050805160108054602084015160409094015167ffffffffffffffff908116600160c01b026001600160c01b036001600160801b03909616600160401b027fffffffffffffffff00000000000000000000000000000000000000000000000090931691909416171792909216179055565b6000670de0b6b3a76400006126108461260a876040015167ffffffffffffffff1686600001516001600160801b031661455b90919063ffffffff16565b9061455b565b61261a9190615641565b8251909150612636906001600160801b03908116908316613278565b6001600160801b039081168352602085015161265791908116908316613278565b6001600160801b0390811660208681018290528451858201518416600160801b0290841617600b558651601080546040808b015167ffffffffffffffff908116600160c01b026001600160c01b03600160401b9098027fffffffffffffffff00000000000000000000000000000000000000000000000090941691909516179190911794909416919091179055905191831682527f757b29336b38e0454cafcaa1fee2fc9e8677248c1cb1ba37dd3e2c60a87ab3ab910160405180910390a150505050565b6127246144db565b600180546001600160a01b03831673ffffffffffffffffffffffffffffffffffffffff1990911681179091556127626000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6127a26144db565b6001600160a01b0381166127f85760405162461bcd60e51b815260206004820152601360248201527f63616e6e6f7420626520302061646472657373000000000000000000000000006044820152606401610a59565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f8bc25725ca4ea10a36558b30cebb3baa6f7551e3fe58208d839e44189bdbe3e090600090a250565b7f00000000000000000000000045e15d1e4f92f28a916f4f2971ad9adc278e148b6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d19190614f8b565b6001600160a01b0316336001600160a01b0316146129315760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e65720000000000000000006044820152606401610a59565b6040805180820182526001600160801b038481168083529084166020928301819052600160801b810282176009558351918252918101919091527ff1fce436bc22563026222b3b2bdc088cb69d25192974264114df12ab812628f6910160405180910390a15050565b6129a261321e565b60006129ac611f34565b9150506129b76124b9565b6003546040517f4ffe34db0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918291829182917f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd64396690911690634ffe34db906024016040805180830381865afa158015612a43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a679190615655565b9050895160005b81811015612d0d5760008c8281518110612a8a57612a8a61531c565b60200260200101519050612a9e8189613801565b612cfa576001600160a01b0381166000908152600d60205260408120548d5181908f9086908110612ad157612ad161531c565b602002602001015111612afd578d8481518110612af057612af061531c565b6020026020010151612aff565b805b60408051808201909152600b546001600160801b038082168352600160801b909104166020820152909250600090612b38908483614398565b90506000612b80612b54670de0b6b3a7640000620186a06156b4565b612b6d8e61260a6007548761455b90919063ffffffff16565b612b779190615641565b89906000614434565b9050612b8c8385614567565b6001600160a01b0386166000908152600d6020908152604080832093909355600c90522054612bbb9082614567565b6001600160a01b0386166000908152600c60205260409020558e6001600160a01b0316856001600160a01b03167f77f19d2489899bac4076fc1c140f57208d84c91aca70c5bfce9460130bcc5c5583604051612c1991815260200190565b60405180910390a360408051838152602081018690526001600160a01b0387169133917fa7489af36ce0dad0b30ae45d2d29c07e996839e7ad59e955a9d33ec30372fdeb910160405180910390a38e6001600160a01b0316856001600160a01b0316336001600160a01b03167f66b108dc29b952efc76dccea9b82dce6b59fab4d9af73d8dcc9789afcad5daf6848689604051612cc9939291909283526020830191909152604082015260600190565b60405180910390a4612cdb8b82613278565b9a50612ce78a83613278565b9950612cf38985613278565b9850505050505b5080612d0581615615565b915050612a6e565b5083600003612d5e5760405162461bcd60e51b815260206004820152601860248201527f4368616d6265723a20616c6c2061726520736f6c76656e7400000000000000006044820152606401610a59565b600b54612d74906001600160801b031685614567565b600b80547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001600160801b039283161790819055612dbd91600160801b9091041684614567565b600b80546001600160801b03928316600160801b029216919091179055600a54612de79086614567565b600a8190555060006064612e23600a61260a88620186a0612e136007548c61455b90919063ffffffff16565b612e1d9190615641565b90614567565b612e2d9190615641565b9050612e398582613278565b601054909550612e5990600160401b90046001600160801b031682613278565b601080546001600160801b0392909216600160401b0277ffffffffffffffffffffffffffffffff00000000000000001990921691909117905550604051636d289ce560e11b81526001600160a01b037f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd88116600483015260248201869052600160448301526000917f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439669091169063da5139ca90606401602060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f509190615062565b600354604051633c6340f360e21b81526001600160a01b0391821660048201523060248201528c82166044820152606481018990529192507f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd643966169063f18d03cc90608401600060405180830381600087803b158015612fce57600080fd5b505af1158015612fe2573d6000803e3d6000fd5b505050506001600160a01b038916156130a557886001600160a01b031663a5d4096b600360009054906101000a90046001600160a01b03167f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd833858b8e6040518763ffffffff1660e01b8152600401613060969594939291906156cb565b60408051808303816000875af115801561307e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a291906155f1565b50505b604051636d289ce560e11b81526001600160a01b037f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd88116600483015260248201879052600160448301527f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd643966169063da5139ca90606401602060405180830381865afa158015613139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061315d9190615062565b604051633c6340f360e21b81526001600160a01b037f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd881166004830152336024830152306044830152606482018390529192507f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439669091169063f18d03cc90608401600060405180830381600087803b1580156131f857600080fd5b505af115801561320c573d6000803e3d6000fd5b50505050505050505050505050505050565b600154600160a01b900460ff161561200a5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610a59565b6000613284828461504f565b9392505050565b801561337b57604051633de222bb60e21b81526001600160a01b0385811660048301523060248301526133279184917f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd643966169063f7888aec90604401602060405180830381865afa158015613303573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1d9190615062565b8311156133765760405162461bcd60e51b815260206004820152601660248201527f4368616d6265723a20536b696d20746f6f206d756368000000000000000000006044820152606401610a59565b612431565b604051633c6340f360e21b81526001600160a01b038581166004830152336024830152306044830152606482018590527f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd643966169063f18d03cc90608401600060405180830381600087803b1580156133f157600080fd5b505af1158015613405573d6000803e3d6000fd5b5050505050505050565b60006127106134266312e687c061ffff8516614fbe565b610c1e9190615000565b600061343a61321e565b60408051808201909152600b546001600160801b038082168352600160801b90910416602082015261346e90836001614573565b81516020928301516001600160801b03908116600160801b02911617600b556001600160a01b0386166000908152600d9092526040909120549091506134b49083614567565b6001600160a01b038581166000908152600d6020526040808220939093559151636d289ce560e11b81527f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd88216600482015260248101849052600160448201527f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439669091169063da5139ca90606401602060405180830381865afa15801561355f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135839190615062565b90506135d96001600160a01b037f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd8167f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd643966846145dc565b7f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439666001600160a01b031663f18d03cc7f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd8866136345733613656565b7f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439665b6040516001600160e01b031960e085901b1681526001600160a01b0392831660048201529116602482015230604482015260648101849052608401600060405180830381600087803b1580156136ab57600080fd5b505af11580156136bf573d6000803e3d6000fd5b505060405163095ea7b360e01b81526001600160a01b037f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd64396681166004830152600060248301527f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd816925063095ea7b391506044016020604051808303816000875af1158015613752573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137769190615717565b50846001600160a01b03168461378c57336137ae565b7f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439665b6001600160a01b03167fa7489af36ce0dad0b30ae45d2d29c07e996839e7ad59e955a9d33ec30372fdeb84866040516137f1929190918252602082015260400190565b60405180910390a3509392505050565b6001600160a01b0382166000908152600d602052604081205480820361382b576001915050610c1e565b6001600160a01b0384166000908152600c60205260408120549081900361385757600092505050610c1e565b60408051808201909152600b546001600160801b03808216808452600160801b90920416602083018190529061389490879061260a90879061455b565b61389e9190615641565b6003546006546001600160a01b037f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439668116926356623118929116906138fc9061260a6138f5620186a0670de0b6b3a7640000615641565b899061455b565b6040516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482015260006044820152606401602060405180830381865afa15801561394c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139709190615062565b10159695505050505050565b60008061398761321e565b6000620186a06139a26008548661455b90919063ffffffff16565b6139ac9190615641565b90506139eb6139bb8583613278565b60408051808201909152600b546001600160801b038082168352600160801b909104166020820152906001614748565b81516020909201516001600160801b03908116600160801b02921691909117600b559250613a636001600160a01b037f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd8167f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd643966866145dc565b604080518082019091526009546001600160801b03808216808452600160801b90920481166020840152600b54161115613adf5760405162461bcd60e51b815260206004820152601460248201527f426f72726f77204c696d697420726561636865640000000000000000000000006044820152606401610a59565b601054613b0090600160401b90046001600160801b03908116908416613278565b601080546001600160801b0392909216600160401b0277ffffffffffffffffffffffffffffffff000000000000000019909216919091179055336000908152600d6020526040812054613b539086613278565b905081602001516001600160801b0316811115613bb25760405162461bcd60e51b815260206004820152601460248201527f426f72726f77204c696d697420726561636865640000000000000000000000006044820152606401610a59565b336000908152600d602052604080822083905551636d289ce560e11b81526001600160a01b037f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd8811660048301526024820189905260448201929092527f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439669091169063da5139ca90606401602060405180830381865afa158015613c5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c7e9190615062565b604051633c6340f360e21b81526001600160a01b037f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd8811660048301523060248301528981166044830152606482018390529195507f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439669091169063f18d03cc90608401600060405180830381600087803b158015613d1b57600080fd5b505af1158015613d2f573d6000803e3d6000fd5b505060405163095ea7b360e01b81526001600160a01b037f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd64396681166004830152600060248301527f000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd816925063095ea7b391506044016020604051808303816000875af1158015613dc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613de69190615717565b506001600160a01b038716337f1298465c3dfc2aaba2a18da010d6b969a7e06f6f9dbcc96798660535389d1e7c613e1d8987613278565b60408051918252602082018a90520160405180910390a35050509250929050565b600080841215613e5d576000198414613e575781610c08565b82610c08565b509192915050565b613e6d61321e565b336000908152600c6020526040902054613e879082614567565b336000908152600c6020526040902055600a54613ea49082614567565b600a556040518181526001600160a01b0383169033907f77f19d2489899bac4076fc1c140f57208d84c91aca70c5bfce9460130bcc5c559060200160405180910390a3600354604051633c6340f360e21b81526001600160a01b0391821660048201523060248201528382166044820152606481018390527f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439669091169063f18d03cc90608401600060405180830381600087803b158015613f6457600080fd5b505af1158015613f78573d6000803e3d6000fd5b505050505050565b600080613f8b61321e565b60008060008089806020019051810190613fa59190615734565b9350935093509350613fb8828989613e3e565b9150613fc5818989613e3e565b6040517f02b9446c0000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152336024830152858116604483015260648201859052608482018390529192507f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd643966909116906302b9446c908b9060a401604080518083038185885af1158015614067573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061408c91906155f1565b955095505050505094509492505050565b6000806140a861321e565b600080600080888060200190518101906140c29190615734565b93509350935093507f000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd6439666001600160a01b03166397da6d30853386614107878e8e613e3e565b614112878f8f613e3e565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015293851660248501529390911660448301526064820152608481019190915260a40160408051808303816000875af1158015614175573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061419991906155f1565b9550955050505050935093915050565b606060006141b561321e565b6000806000806000898060200190518101906141d19190615787565b945094509450945094508280156141e6575081155b156142145783896040516020016141fe929190615845565b604051602081830303815290604052935061426d565b8215801561421f5750815b156142375783886040516020016141fe929190615845565b8280156142415750815b1561426d5783898960405160200161425b93929190615867565b60405160208183030381529060405293505b6001600160a01b0385166000908152600e602052604090205460ff16156142d65760405162461bcd60e51b815260206004820152601360248201527f4368616d6265723a2063616e27742063616c6c000000000000000000000000006044820152606401610a59565b600080866001600160a01b03168d876040516142f2919061588e565b60006040518083038185875af1925050503d806000811461432f576040519150601f19603f3d011682016040523d82523d6000602084013e614334565b606091505b5091509150816143865760405162461bcd60e51b815260206004820152601460248201527f4368616d6265723a2063616c6c206661696c65640000000000000000000000006044820152606401610a59565b9c919b50909950505050505050505050565b600083602001516001600160801b03166000036143b6575081613284565b602084015184516001600160801b03918216916143d49116856156b4565b6143de9190615641565b905081801561441c57508284600001516001600160801b031685602001516001600160801b03168361441091906156b4565b61441a9190615641565b105b15613284578061442b81615615565b95945050505050565b82516000906001600160801b0316810361444f575081613284565b835160208501516001600160801b039182169161446d9116856156b4565b6144779190615641565b905081801561441c57508284602001516001600160801b031685600001516001600160801b03168361441091906156b4565b6000808080806144bb86880188614ed9565b945094509450945094506144d2858585858561299a565b50505050505050565b6000546001600160a01b0316331461200a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a59565b6001805473ffffffffffffffffffffffffffffffffffffffff191690556121258161479d565b600061328482846156b4565b6000613284828461562e565b60408051808201909152600080825260208201526000614594858585614398565b905080856000018181516145a891906158aa565b6001600160801b03169052506020850180518591906145c89083906158aa565b6001600160801b0316905250939492505050565b80158061466f57506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015614649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061466d9190615062565b155b6146e15760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610a59565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663095ea7b360e01b1790526124b49084906147fa565b60408051808201909152600080825260208201526000614769858585614434565b9050838560000181815161477d91906158ca565b6001600160801b03169052506020850180518291906145c89083906158ca565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600061484f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166148e29092919063ffffffff16565b90508051600014806148705750808060200190518101906148709190615717565b6124b45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a59565b6060610c08848460008585600080866001600160a01b03168587604051614909919061588e565b60006040518083038185875af1925050503d8060008114614946576040519150601f19603f3d011682016040523d82523d6000602084013e61494b565b606091505b509150915061495c87838387614967565b979650505050505050565b606083156149d65782516000036149cf576001600160a01b0385163b6149cf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a59565b5081610c08565b610c0883838151156149eb5781518083602001fd5b8060405162461bcd60e51b8152600401610a599190614cb7565b6001600160a01b038116811461212557600080fd5b801515811461212557600080fd5b600080600060608486031215614a3d57600080fd5b8335614a4881614a05565b92506020840135614a5881614a1a565b929592945050506040919091013590565b600060208284031215614a7b57600080fd5b813561ffff8116811461328457600080fd5b600060208284031215614a9f57600080fd5b813561328481614a05565b60008060408385031215614abd57600080fd5b8235614ac881614a05565b946020939093013593505050565b60008060208385031215614ae957600080fd5b823567ffffffffffffffff80821115614b0157600080fd5b818501915085601f830112614b1557600080fd5b813581811115614b2457600080fd5b866020828501011115614b3657600080fd5b60209290920196919550909350505050565b60008060408385031215614b5b57600080fd5b8235614b6681614a05565b91506020830135614b7681614a1a565b809150509250929050565b60008083601f840112614b9357600080fd5b50813567ffffffffffffffff811115614bab57600080fd5b6020830191508360208260051b8501011115614bc657600080fd5b9250929050565b60008060008060008060608789031215614be657600080fd5b863567ffffffffffffffff80821115614bfe57600080fd5b614c0a8a838b01614b81565b90985096506020890135915080821115614c2357600080fd5b614c2f8a838b01614b81565b90965094506040890135915080821115614c4857600080fd5b50614c5589828a01614b81565b979a9699509497509295939492505050565b60005b83811015614c82578181015183820152602001614c6a565b50506000910152565b60008151808452614ca3816020860160208601614c67565b601f01601f19169290920160200192915050565b6020815260006132846020830184614c8b565b600060208284031215614cdc57600080fd5b5035919050565b6001600160801b038116811461212557600080fd5b60008060408385031215614d0b57600080fd5b8235614d1681614ce3565b91506020830135614b7681614ce3565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614d6557614d65614d26565b604052919050565b600067ffffffffffffffff821115614d8757614d87614d26565b5060051b60200190565b600082601f830112614da257600080fd5b81356020614db7614db283614d6d565b614d3c565b82815260059290921b84018101918181019086841115614dd657600080fd5b8286015b84811015614dfa578035614ded81614a05565b8352918301918301614dda565b509695505050505050565b600082601f830112614e1657600080fd5b81356020614e26614db283614d6d565b82815260059290921b84018101918181019086841115614e4557600080fd5b8286015b84811015614dfa5780358352918301918301614e49565b600067ffffffffffffffff821115614e7a57614e7a614d26565b50601f01601f191660200190565b600082601f830112614e9957600080fd5b8135614ea7614db282614e60565b818152846020838601011115614ebc57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a08688031215614ef157600080fd5b853567ffffffffffffffff80821115614f0957600080fd5b614f1589838a01614d91565b96506020880135915080821115614f2b57600080fd5b614f3789838a01614e05565b955060408801359150614f4982614a05565b909350606087013590614f5b82614a05565b90925060808701359080821115614f7157600080fd5b50614f7e88828901614e88565b9150509295509295909350565b600060208284031215614f9d57600080fd5b815161328481614a05565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff818116838216028082169190828114614fe257614fe2614fa8565b505092915050565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061501b5761501b614fea565b92169190910492915050565b67ffffffffffffffff81811683821601908082111561504857615048614fa8565b5092915050565b80820180821115610c1e57610c1e614fa8565b60006020828403121561507457600080fd5b5051919050565b600080600080600080600060e0888a03121561509657600080fd5b87356150a181614a05565b965060208801356150b181614a05565b9550604088013567ffffffffffffffff808211156150ce57600080fd5b6150da8b838c01614e88565b965060608a0135915080821682146150f157600080fd5b509699959850939660808101359560a0820135955060c0909101359350915050565b600181811c9082168061512757607f821691505b60208210810361514757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156124b457600081815260208120601f850160051c810160208610156151745750805b601f850160051c820191505b81811015613f7857828155600101615180565b815167ffffffffffffffff8111156151ad576151ad614d26565b6151c1816151bb8454615113565b8461514d565b602080601f8311600181146151f657600084156151de5750858301515b600019600386901b1c1916600185901b178555613f78565b600085815260208120601f198616915b8281101561522557888601518255948401946001909101908401615206565b50858210156152435787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083526000845461526781615113565b8084870152604060018084166000811461528857600181146152a2576152d0565b60ff1985168984015283151560051b8901830195506152d0565b896000528660002060005b858110156152c85781548b82018601529083019088016152ad565b8a0184019650505b509398975050505050505050565b80516152e981614a1a565b919050565b6000806040838503121561530157600080fd5b825161530c81614a1a565b6020939093015192949293505050565b634e487b7160e01b600052603260045260246000fd5b60ff8116811461212557600080fd5b60006020828403121561535357600080fd5b813561328481615332565b6000808335601e1984360301811261537557600080fd5b83018035915067ffffffffffffffff82111561539057600080fd5b602001915036819003821315614bc657600080fd5b6000806000606084860312156153ba57600080fd5b8335925060208401356153cc81614a05565b915060408401356153dc81614a1a565b809150509250925092565b600080604083850312156153fa57600080fd5b823591506020830135614b7681614a05565b60008060006060848603121561542157600080fd5b833561542c81614a1a565b95602085013595506040909401359392505050565b60008060008060008060c0878903121561545a57600080fd5b863561546581614a05565b9550602087013561547581614a05565b9450604087013561548581614a1a565b9350606087013561549581615332565b9598949750929560808101359460a0909101359350915050565b6000806000606084860312156154c457600080fd5b83356154cf81614a05565b92506020840135614a5881614a05565b6000806000606084860312156154f457600080fd5b83356154ff81614a05565b9250602084013567ffffffffffffffff8082111561551c57600080fd5b61552887838801614d91565b9350604086013591508082111561553e57600080fd5b5061554b86828701614e05565b9150509250925092565b6000608082016001600160a01b0380881684526020818816818601526080604086015282875180855260a087019150828901945060005b818110156155aa57855185168352948301949183019160010161558c565b5050858103606087015286518082529082019350915080860160005b838110156155e2578151855293820193908201906001016155c6565b50929998505050505050505050565b6000806040838503121561560457600080fd5b505080516020909101519092909150565b60006001820161562757615627614fa8565b5060010190565b81810381811115610c1e57610c1e614fa8565b60008261565057615650614fea565b500490565b60006040828403121561566757600080fd5b6040516040810181811067ffffffffffffffff8211171561568a5761568a614d26565b604052825161569881614ce3565b815260208301516156a881614ce3565b60208201529392505050565b8082028115828204841417610c1e57610c1e614fa8565b60006001600160a01b038089168352808816602084015280871660408401525084606083015283608083015260c060a083015261570b60c0830184614c8b565b98975050505050505050565b60006020828403121561572957600080fd5b815161328481614a1a565b6000806000806080858703121561574a57600080fd5b845161575581614a05565b602086015190945061576681614a05565b6040860151606090960151949790965092505050565b80516152e981615332565b600080600080600060a0868803121561579f57600080fd5b85516157aa81614a05565b602087015190955067ffffffffffffffff8111156157c757600080fd5b8601601f810188136157d857600080fd5b80516157e6614db282614e60565b8181528960208385010111156157fb57600080fd5b61580c826020830160208601614c67565b955061581d915050604087016152de565b925061582b606087016152de565b91506158396080870161577c565b90509295509295909350565b60008351615857818460208801614c67565b9190910191825250602001919050565b60008451615879818460208901614c67565b91909101928352506020820152604001919050565b600082516158a0818460208701614c67565b9190910192915050565b6001600160801b0382811682821603908082111561504857615048614fa8565b6001600160801b0381811683821601908082111561504857615048614fa856fea2646970667358221220fe38e6173e208d58a4aef3ddca55a4b42f09c43eca87ea6b80ee8386e2903b5764736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd643966000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd8
-----Decoded View---------------
Arg [0] : bentoBox_ (address): 0xF5BCE5077908a1b7370B9ae04AdC565EBd643966
Arg [1] : senUSD_ (address): 0x922406EAFC3CcEb32b0256F287fB977c426EDbd8
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd643966
Arg [1] : 000000000000000000000000922406eafc3cceb32b0256f287fb977c426edbd8
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ARB | 100.00% | $0.003305 | 392,320.7068 | $1,296.75 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.