Source Code
Overview
ETH Balance
0 ETH
Token Holdings
More Info
ContractCreator
Multichain Info
N/A
Latest 25 from a total of 5,910 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Bid | 9027611 | 643 days ago | IN | 0 ETH | 0.000004386635 | ||||
| Open Position | 9027597 | 643 days ago | IN | 0 ETH | 0.000128253049 | ||||
| Bid | 9027565 | 643 days ago | IN | 0 ETH | 0.000003655297 | ||||
| Bid | 9027554 | 643 days ago | IN | 0 ETH | 0.000003352331 | ||||
| Open Position | 9027545 | 643 days ago | IN | 0 ETH | 0.000124859888 | ||||
| Open Position | 9027526 | 643 days ago | IN | 0 ETH | 0.000125725433 | ||||
| Bid | 9027116 | 643 days ago | IN | 0 ETH | 0.000085699646 | ||||
| Bid | 8959782 | 645 days ago | IN | 0 ETH | 0.000002971754 | ||||
| Bid | 8959766 | 645 days ago | IN | 0 ETH | 0.000002618816 | ||||
| Bid | 8959756 | 645 days ago | IN | 0 ETH | 0.000002845863 | ||||
| Bid | 8933590 | 645 days ago | IN | 0 ETH | 0.000003032179 | ||||
| Open Position | 8933578 | 645 days ago | IN | 0 ETH | 0.000004729374 | ||||
| Bid | 8932489 | 645 days ago | IN | 0 ETH | 0.000002789303 | ||||
| Open Position | 8928976 | 646 days ago | IN | 0 ETH | 0.000005221853 | ||||
| Open Position | 8928965 | 646 days ago | IN | 0 ETH | 0.000004700269 | ||||
| Open Position | 8928954 | 646 days ago | IN | 0 ETH | 0.000004252252 | ||||
| Open Position | 8928081 | 646 days ago | IN | 0 ETH | 0.000004552169 | ||||
| Open Position | 8924688 | 646 days ago | IN | 0 ETH | 0.000004687032 | ||||
| Open Position | 8924554 | 646 days ago | IN | 0 ETH | 0.000006869596 | ||||
| Open Position | 8924542 | 646 days ago | IN | 0 ETH | 0.000005967613 | ||||
| Open Position | 8924534 | 646 days ago | IN | 0 ETH | 0.00000538101 | ||||
| Open Position | 8924494 | 646 days ago | IN | 0 ETH | 0.000004084819 | ||||
| Open Position | 8883954 | 647 days ago | IN | 0 ETH | 0.000004230691 | ||||
| Bid | 8874551 | 647 days ago | IN | 0 ETH | 0.000003388202 | ||||
| Open Position | 8874540 | 647 days ago | IN | 0 ETH | 0.000006198902 |
Loading...
Loading
Contract Name:
TetuPawnShop
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 150 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: ISC
/**
* By using this software, you understand, acknowledge and accept that Tetu
* and/or the underlying software are provided “as is” and “as available”
* basis and without warranties or representations of any kind either expressed
* or implied. Any use of this open source software released under the ISC
* Internet Systems Consortium license is done at your own risk to the fullest
* extent permissible pursuant to applicable law any and all liability as well
* as all warranties, including any fitness for a particular purpose with respect
* to Tetu and/or the underlying software and the use thereof are disclaimed.
*/
pragma solidity 0.8.4;
// use copies of openzeppelin contracts with changed names for avoid dependency issues
import "../openzeppelin/ERC721Holder.sol";
import "../openzeppelin/IERC721.sol";
import "../openzeppelin/SafeERC20.sol";
import "../openzeppelin/IERC20.sol";
import "../openzeppelin/ReentrancyGuard.sol";
import "../base/ArrayLib.sol";
import "./ITetuPawnShop.sol";
import "./ERC2771Context.sol";
interface IDelegation {
function clearDelegate(bytes32 _id) external;
function setDelegate(bytes32 _id, address _delegate) external;
}
/// @title TetuPawnShop contract provides a useful and flexible solution for borrowing
/// and lending assets with a unique feature of supporting both ERC721 and ERC20 tokens as collateral.
/// The contract's modular design allows for easy customization of fees, waiting periods,
/// and other parameters, providing a solid foundation for a decentralized borrowing and lending platform.
/// @author belbix
contract TetuPawnShop is ERC721Holder, ReentrancyGuard, ITetuPawnShop, ERC2771Context {
using SafeERC20 for IERC20;
using ArrayLib for uint[];
// ---- CONSTANTS
/// @notice Version of the contract
/// @dev Should be incremented when contract changed
string public constant VERSION = "1.0.7";
/// @dev Time lock for any governance actions
uint constant public TIME_LOCK = 2 days;
/// @dev Denominator for any internal computation with low precision
uint constant public DENOMINATOR = 10000;
/// @dev Governance can't set fee more than this value
uint constant public PLATFORM_FEE_MAX = 500; // 5%
/// @dev Standard auction duration that refresh when a new bid placed
uint constant public AUCTION_DURATION = 1 days;
/// @dev Timestamp date when contract created
uint public immutable createdTs;
/// @dev Block number when contract created
uint public immutable createdBlock;
// ---- CHANGEABLE VARIABLES
/// @dev Contract owner. Should be a multi-signature wallet
/// On Polygon TETU msig gov wallet 3/4 is 0xcc16d636dD05b52FF1D8B9CE09B09BC62b11412B
address public owner;
/// @dev Fee recipient. Assume it will be a place with ability to manage different tokens
address public feeRecipient;
/// @dev 1% by default, percent of acquired tokens that will be used for buybacks
uint public platformFee = 100;
/// @dev Amount of tokens for open position. Protection against spam
uint public positionDepositAmount;
/// @dev Token for antispam protection. TETU assumed
/// Zero address means no protection
address public positionDepositToken;
/// @dev Time-locks for governance actions
mapping(GovernanceAction => TimeLock) public timeLocks;
// ---- POSITIONS
/// @inheritdoc ITetuPawnShop
uint public override positionCounter = 1;
/// @dev PosId => Position. Hold all positions. Any record should not be removed
mapping(uint => Position) public positions;
/// @inheritdoc ITetuPawnShop
uint[] public override openPositions;
/// @inheritdoc ITetuPawnShop
mapping(address => uint[]) public override positionsByCollateral;
/// @inheritdoc ITetuPawnShop
mapping(address => uint[]) public override positionsByAcquired;
/// @inheritdoc ITetuPawnShop
mapping(address => uint[]) public override borrowerPositions;
/// @inheritdoc ITetuPawnShop
mapping(address => uint[]) public override lenderPositions;
/// @inheritdoc ITetuPawnShop
mapping(IndexType => mapping(uint => uint)) public override posIndexes;
// ---- AUCTION
/// @inheritdoc ITetuPawnShop
uint public override auctionBidCounter = 1;
/// @dev BidId => Bid. Hold all bids. Any record should not be removed
mapping(uint => AuctionBid) public auctionBids;
/// @inheritdoc ITetuPawnShop
mapping(address => mapping(uint => uint)) public override lenderOpenBids;
/// @inheritdoc ITetuPawnShop
mapping(uint => uint[]) public override positionToBidIds;
/// @inheritdoc ITetuPawnShop
mapping(uint => uint) public override lastAuctionBidTs;
/// @dev Tetu Controller address requires for governance actions
constructor(
address _owner,
address _depositToken,
uint _positionDepositAmount,
address _feeRecipient
) {
require(_owner != address(0), "TPS: Zero owner");
require(_feeRecipient != address(0), "TPS: Zero feeRecipient");
owner = _owner;
feeRecipient = _feeRecipient;
positionDepositToken = _depositToken;
createdTs = block.timestamp;
createdBlock = block.number;
positionDepositAmount = _positionDepositAmount;
}
modifier onlyOwner() {
require(_msgSender() == owner, "TPS: Not owner");
_;
}
/// @dev Check time lock for governance actions and revert if conditions wrong
modifier checkTimeLock(GovernanceAction action, address _address, uint _uint){
TimeLock memory timeLock = timeLocks[action];
require(timeLock.time != 0 && timeLock.time < block.timestamp, "TPS: Time Lock");
if (_address != address(0)) {
require(timeLock.addressValue == _address, "TPS: Wrong address value");
}
if (_uint != 0) {
require(timeLock.uintValue == _uint, "TPS: Wrong uint value");
}
_;
delete timeLocks[action];
}
// ************* USER ACTIONS *************
/// @inheritdoc ITetuPawnShop
function openPosition(
address _collateralToken,
uint _collateralAmount,
uint _collateralTokenId,
address _acquiredToken,
uint _acquiredAmount,
uint _posDurationBlocks,
uint _posFee,
uint minAuctionAmount
) external nonReentrant override returns (uint){
require(_posFee <= DENOMINATOR * 10, "TPS: Pos fee absurdly high");
require(_posDurationBlocks != 0 || _posFee == 0, "TPS: Fee for instant deal forbidden");
require(_collateralAmount != 0 || _collateralTokenId != 0, "TPS: Wrong amounts");
require(_collateralToken != address(0), "TPS: Zero cToken");
require(_acquiredToken != address(0), "TPS: Zero aToken");
AssetType assetType = _getAssetType(_collateralToken);
require((assetType == AssetType.ERC20 && _collateralAmount != 0 && _collateralTokenId == 0)
|| (assetType == AssetType.ERC721 && _collateralAmount == 0 && _collateralTokenId != 0), "TPS: Incorrect");
Position memory pos;
{
PositionInfo memory info = PositionInfo(
_posDurationBlocks,
_posFee,
block.number,
block.timestamp
);
PositionCollateral memory collateral = PositionCollateral(
_collateralToken,
assetType,
_collateralAmount,
_collateralTokenId
);
PositionAcquired memory acquired = PositionAcquired(
_acquiredToken,
_acquiredAmount
);
PositionExecution memory execution = PositionExecution(
address(0),
0,
0,
0
);
pos = Position(
positionCounter, // id
_msgSender(), // borrower
positionDepositToken,
positionDepositAmount,
true, // open
minAuctionAmount,
info,
collateral,
acquired,
execution
);
}
openPositions.push(pos.id);
posIndexes[IndexType.LIST][pos.id] = openPositions.length - 1;
positionsByCollateral[_collateralToken].push(pos.id);
posIndexes[IndexType.BY_COLLATERAL][pos.id] = positionsByCollateral[_collateralToken].length - 1;
positionsByAcquired[_acquiredToken].push(pos.id);
posIndexes[IndexType.BY_ACQUIRED][pos.id] = positionsByAcquired[_acquiredToken].length - 1;
borrowerPositions[_msgSender()].push(pos.id);
posIndexes[IndexType.BORROWER_POSITION][pos.id] = borrowerPositions[_msgSender()].length - 1;
positions[pos.id] = pos;
positionCounter++;
_takeDeposit(pos.id);
_transferCollateral(pos.collateral, _msgSender(), address(this));
emit PositionOpened(
_msgSender(),
pos.id,
_collateralToken,
_collateralAmount,
_collateralTokenId,
_acquiredToken,
_acquiredAmount,
_posDurationBlocks,
_posFee
);
return pos.id;
}
/// @inheritdoc ITetuPawnShop
function closePosition(uint id) external nonReentrant override {
Position storage pos = positions[id];
require(pos.id == id, "TPS: Wrong ID");
require(pos.borrower == _msgSender(), "TPS: Only borrower can close a position");
require(pos.execution.lender == address(0), "TPS: Can't close executed position");
require(pos.open, "TPS: Position closed");
_removePosFromIndexes(pos);
borrowerPositions[pos.borrower].removeIndexed(posIndexes[IndexType.BORROWER_POSITION], pos.id);
_transferCollateral(pos.collateral, address(this), pos.borrower);
_returnDeposit(id);
pos.open = false;
emit PositionClosed(_msgSender(), id);
}
/// @inheritdoc ITetuPawnShop
function bid(uint id, uint amount) external nonReentrant override {
Position storage pos = positions[id];
require(pos.id == id, "TPS: Wrong ID");
require(pos.open, "TPS: Position closed");
require(pos.execution.lender == address(0), "TPS: Can't bid executed position");
if (pos.acquired.acquiredAmount != 0) {
require(amount == pos.acquired.acquiredAmount, "TPS: Wrong bid amount");
_executeBid(pos, 0, amount, _msgSender(), _msgSender());
} else {
_auctionBid(pos, amount, _msgSender());
}
}
/// @inheritdoc ITetuPawnShop
function claim(uint id) external nonReentrant override {
Position storage pos = positions[id];
require(pos.id == id, "TPS: Wrong ID");
require(pos.execution.lender == _msgSender(), "TPS: Only lender can claim");
uint posEnd = pos.execution.posStartBlock + pos.info.posDurationBlocks;
require(posEnd < block.number, "TPS: Too early to claim");
require(pos.open, "TPS: Position closed");
_endPosition(pos);
_transferCollateral(pos.collateral, address(this), _msgSender());
_returnDeposit(id);
emit PositionClaimed(_msgSender(), id);
}
/// @inheritdoc ITetuPawnShop
function redeem(uint id) external nonReentrant override {
Position storage pos = positions[id];
require(pos.id == id, "TPS: Wrong ID");
require(pos.borrower == _msgSender(), "TPS: Only borrower can redeem");
require(pos.execution.lender != address(0), "TPS: Not executed position");
require(pos.open, "TPS: Position closed");
_endPosition(pos);
uint toSend = _toRedeem(id);
IERC20(pos.acquired.acquiredToken).safeTransferFrom(_msgSender(), pos.execution.lender, toSend);
_transferCollateral(pos.collateral, address(this), _msgSender());
_returnDeposit(id);
emit PositionRedeemed(_msgSender(), id);
}
/// @inheritdoc ITetuPawnShop
function acceptAuctionBid(uint posId) external nonReentrant override {
require(lastAuctionBidTs[posId] + AUCTION_DURATION < block.timestamp, "TPS: Auction not ended");
require(positionToBidIds[posId].length > 0, "TPS: No bids");
uint bidId = positionToBidIds[posId][positionToBidIds[posId].length - 1];
AuctionBid storage _bid = auctionBids[bidId];
require(_bid.id != 0, "TPS: Auction bid not found");
require(_bid.open, "TPS: Bid closed");
require(_bid.posId == posId, "TPS: Wrong bid");
Position storage pos = positions[posId];
require(pos.borrower == _msgSender(), "TPS: Not borrower");
require(pos.open, "TPS: Position closed");
pos.acquired.acquiredAmount = _bid.amount;
_executeBid(pos, bidId, _bid.amount, address(this), _bid.lender);
lenderOpenBids[_bid.lender][pos.id] = 0;
_bid.open = false;
emit AuctionBidAccepted(_msgSender(), posId, _bid.id);
}
/// @inheritdoc ITetuPawnShop
function closeAuctionBid(uint bidId) external nonReentrant override {
AuctionBid storage _bid = auctionBids[bidId];
require(_bid.id != 0, "TPS: Auction bid not found");
Position storage pos = positions[_bid.posId];
uint _lastAuctionBidTs = lastAuctionBidTs[pos.id];
bool isAuctionEnded = _lastAuctionBidTs + AUCTION_DURATION < block.timestamp;
// in case if auction is not accepted during 2 weeks lender can close the bid
bool isAuctionOverdue = _lastAuctionBidTs + AUCTION_DURATION + 2 weeks < block.timestamp;
bool isLastBid = false;
if (positionToBidIds[pos.id].length != 0) {
uint lastBidId = positionToBidIds[pos.id][positionToBidIds[pos.id].length - 1];
isLastBid = lastBidId == bidId;
}
require((isLastBid && isAuctionEnded) || !isLastBid || !pos.open || isAuctionOverdue, "TPS: Auction is not ended");
address lender = _bid.lender;
lenderOpenBids[lender][pos.id] = 0;
_bid.open = false;
IERC20(pos.acquired.acquiredToken).safeTransfer(lender, _bid.amount);
emit AuctionBidClosed(pos.id, bidId);
}
// ************* INTERNAL FUNCTIONS *************
/// @dev Transfer to this contract a deposit
function _takeDeposit(uint posId) internal {
Position storage pos = positions[posId];
if (pos.depositToken != address(0)) {
IERC20(pos.depositToken).safeTransferFrom(pos.borrower, address(this), pos.depositAmount);
}
}
/// @dev Return to borrower a deposit
function _returnDeposit(uint posId) internal {
Position storage pos = positions[posId];
if (pos.depositToken != address(0)) {
IERC20(pos.depositToken).safeTransfer(pos.borrower, pos.depositAmount);
}
}
/// @dev Execute bid for the open position
/// Transfer acquired tokens to borrower
/// In case of instant deal transfer collateral to lender
function _executeBid(
Position storage pos,
uint bidId,
uint amount,
address acquiredMoneyHolder,
address lender
) internal {
uint feeAmount = amount * platformFee / DENOMINATOR;
uint toSend = amount - feeAmount;
if (acquiredMoneyHolder == address(this)) {
IERC20(pos.acquired.acquiredToken).safeTransfer(pos.borrower, toSend);
} else {
IERC20(pos.acquired.acquiredToken).safeTransferFrom(acquiredMoneyHolder, pos.borrower, toSend);
IERC20(pos.acquired.acquiredToken).safeTransferFrom(acquiredMoneyHolder, address(this), feeAmount);
}
_transferFee(pos.acquired.acquiredToken, feeAmount);
pos.execution.lender = lender;
pos.execution.posStartBlock = block.number;
pos.execution.posStartTs = block.timestamp;
_removePosFromIndexes(pos);
lenderPositions[lender].push(pos.id);
posIndexes[IndexType.LENDER_POSITION][pos.id] = lenderPositions[lender].length - 1;
// instant buy
if (pos.info.posDurationBlocks == 0) {
_transferCollateral(pos.collateral, address(this), lender);
_endPosition(pos);
}
emit BidExecuted(
pos.id,
bidId,
amount,
acquiredMoneyHolder,
lender
);
}
/// @dev Open an auction bid
/// Transfer acquired token to this contract
function _auctionBid(Position storage pos, uint amount, address lender) internal {
require(lenderOpenBids[lender][pos.id] == 0, "TPS: Auction bid already exist");
require(amount >= pos.minAuctionAmount, "TPS: Too low bid");
if (positionToBidIds[pos.id].length != 0) {
// if we have bids need to check auction duration
require(lastAuctionBidTs[pos.id] + AUCTION_DURATION > block.timestamp, "TPS: Auction ended");
uint lastBidId = positionToBidIds[pos.id][positionToBidIds[pos.id].length - 1];
AuctionBid storage lastBid = auctionBids[lastBidId];
require(lastBid.amount * 110 / 100 < amount, "TPS: New bid lower than previous");
}
AuctionBid memory _bid = AuctionBid(
auctionBidCounter,
pos.id,
lender,
amount,
true
);
positionToBidIds[pos.id].push(_bid.id);
// write index + 1 for keep zero as empty value
lenderOpenBids[lender][pos.id] = positionToBidIds[pos.id].length;
IERC20(pos.acquired.acquiredToken).safeTransferFrom(_msgSender(), address(this), amount);
lastAuctionBidTs[pos.id] = block.timestamp;
auctionBids[_bid.id] = _bid;
auctionBidCounter++;
emit AuctionBidOpened(pos.id, _bid.id, amount, lender);
}
/// @dev Finalize position. Remove position from indexes
function _endPosition(Position storage pos) internal {
require(pos.execution.posEndTs == 0, "TPS: Position claimed");
pos.open = false;
pos.execution.posEndTs = block.timestamp;
borrowerPositions[pos.borrower].removeIndexed(posIndexes[IndexType.BORROWER_POSITION], pos.id);
if (pos.execution.lender != address(0)) {
lenderPositions[pos.execution.lender].removeIndexed(posIndexes[IndexType.LENDER_POSITION], pos.id);
}
}
/// @dev Transfer collateral from sender to recipient
function _transferCollateral(PositionCollateral memory _collateral, address _sender, address _recipient) internal {
if (_collateral.collateralType == AssetType.ERC20) {
if (_sender == address(this)) {
IERC20(_collateral.collateralToken).safeTransfer(_recipient, _collateral.collateralAmount);
} else {
IERC20(_collateral.collateralToken).safeTransferFrom(_sender, _recipient, _collateral.collateralAmount);
}
} else if (_collateral.collateralType == AssetType.ERC721) {
IERC721(_collateral.collateralToken).safeTransferFrom(_sender, _recipient, _collateral.collateralTokenId);
} else {
revert("TPS: Wrong asset type");
}
}
/// @dev Transfer fee to platform. Assume that token inside this contract
/// Do buyback if possible, otherwise just send to controller for manual handling
function _transferFee(address token, uint amount) internal {
// little deals can have zero fees
if (amount == 0) {
return;
}
IERC20(token).safeTransfer(feeRecipient, amount);
}
/// @dev Remove position from common indexes
function _removePosFromIndexes(Position memory _pos) internal {
openPositions.removeIndexed(posIndexes[IndexType.LIST], _pos.id);
positionsByCollateral[_pos.collateral.collateralToken].removeIndexed(posIndexes[IndexType.BY_COLLATERAL], _pos.id);
positionsByAcquired[_pos.acquired.acquiredToken].removeIndexed(posIndexes[IndexType.BY_ACQUIRED], _pos.id);
}
// ************* VIEWS **************************
/// @inheritdoc ITetuPawnShop
function toRedeem(uint id) external view override returns (uint){
return _toRedeem(id);
}
function _toRedeem(uint id) private view returns (uint){
Position memory pos = positions[id];
return pos.acquired.acquiredAmount +
(pos.acquired.acquiredAmount * pos.info.posFee / DENOMINATOR);
}
/// @inheritdoc ITetuPawnShop
function getAssetType(address _token) external view override returns (AssetType){
return _getAssetType(_token);
}
function _getAssetType(address _token) private view returns (AssetType){
if (_isERC721(_token)) {
return AssetType.ERC721;
} else if (_isERC20(_token)) {
return AssetType.ERC20;
} else {
revert("TPS: Unknown asset");
}
}
/// @dev Return true if given token is ERC721 token
function isERC721(address _token) external view override returns (bool) {
return _isERC721(_token);
}
//noinspection NoReturn
function _isERC721(address _token) private view returns (bool) {
//slither-disable-next-line unused-return,variable-scope,uninitialized-local
try IERC721(_token).supportsInterface{gas: 30000}(type(IERC721).interfaceId) returns (bool result){
return result;
} catch {
return false;
}
}
/// @dev Return true if given token is ERC20 token
function isERC20(address _token) external view override returns (bool) {
return _isERC20(_token);
}
//noinspection NoReturn
function _isERC20(address _token) private view returns (bool) {
//slither-disable-next-line unused-return,variable-scope,uninitialized-local
try IERC20(_token).totalSupply{gas: 30000}() returns (uint){
return true;
} catch {
return false;
}
}
/// @inheritdoc ITetuPawnShop
function openPositionsSize() external view override returns (uint) {
return openPositions.length;
}
/// @inheritdoc ITetuPawnShop
function auctionBidSize(uint posId) external view override returns (uint) {
return positionToBidIds[posId].length;
}
function positionsByCollateralSize(address collateral) external view override returns (uint) {
return positionsByCollateral[collateral].length;
}
function positionsByAcquiredSize(address acquiredToken) external view override returns (uint) {
return positionsByAcquired[acquiredToken].length;
}
function borrowerPositionsSize(address borrower) external view override returns (uint) {
return borrowerPositions[borrower].length;
}
function lenderPositionsSize(address lender) external view override returns (uint) {
return lenderPositions[lender].length;
}
/// @inheritdoc ITetuPawnShop
function getPosition(uint posId) external view override returns (Position memory) {
return positions[posId];
}
/// @inheritdoc ITetuPawnShop
function getAuctionBid(uint bidId) external view override returns (AuctionBid memory) {
return auctionBids[bidId];
}
// ************* GOVERNANCE ACTIONS *************
/// @inheritdoc ITetuPawnShop
function announceGovernanceAction(
GovernanceAction id,
address addressValue,
uint uintValue
) external onlyOwner override {
require(timeLocks[id].time == 0, "TPS: Already announced");
timeLocks[id] = TimeLock(
block.timestamp + TIME_LOCK,
addressValue,
uintValue
);
emit GovernanceActionAnnounced(uint(id), addressValue, uintValue);
}
/// @inheritdoc ITetuPawnShop
function setOwner(address _newOwner) external onlyOwner override
checkTimeLock(GovernanceAction.ChangeOwner, _newOwner, 0) {
require(_newOwner != address(0), "TPS: Zero address");
emit OwnerChanged(owner, _newOwner);
owner = _newOwner;
}
/// @inheritdoc ITetuPawnShop
function setFeeRecipient(address _newFeeRecipient) external onlyOwner override
checkTimeLock(GovernanceAction.ChangeFeeRecipient, _newFeeRecipient, 0) {
require(_newFeeRecipient != address(0), "TPS: Zero address");
emit FeeRecipientChanged(feeRecipient, _newFeeRecipient);
feeRecipient = _newFeeRecipient;
}
/// @inheritdoc ITetuPawnShop
function setPlatformFee(uint _value) external onlyOwner override
checkTimeLock(GovernanceAction.ChangePlatformFee, address(0), _value) {
require(_value <= PLATFORM_FEE_MAX, "TPS: Too high fee");
emit PlatformFeeChanged(platformFee, _value);
platformFee = _value;
}
/// @inheritdoc ITetuPawnShop
function setPositionDepositAmount(uint _value) external onlyOwner override
checkTimeLock(GovernanceAction.ChangePositionDepositAmount, address(0), _value) {
emit DepositAmountChanged(positionDepositAmount, _value);
positionDepositAmount = _value;
}
/// @inheritdoc ITetuPawnShop
function setPositionDepositToken(address _value) external onlyOwner override
checkTimeLock(GovernanceAction.ChangePositionDepositToken, _value, 0) {
emit DepositTokenChanged(positionDepositToken, _value);
positionDepositToken = _value;
}
/// @dev Delegate snapshot votes to another address
function delegateVotes(address _delegateContract,bytes32 _id, address _delegate) external onlyOwner {
IDelegation(_delegateContract).setDelegate(_id, _delegate);
}
/// @dev Remove delegated votes.
function clearDelegatedVotes(address _delegateContract, bytes32 _id) external onlyOwner {
IDelegation(_delegateContract).clearDelegate(_id);
}
}// SPDX-License-Identifier: ISC
/**
* By using this software, you understand, acknowledge and accept that Tetu
* and/or the underlying software are provided “as is” and “as available”
* basis and without warranties or representations of any kind either expressed
* or implied. Any use of this open source software released under the ISC
* Internet Systems Consortium license is done at your own risk to the fullest
* extent permissible pursuant to applicable law any and all liability as well
* as all warranties, including any fitness for a particular purpose with respect
* to Tetu and/or the underlying software and the use thereof are disclaimed.
*/
pragma solidity 0.8.4;
/// @title Library for useful functions for address and uin256 arrays
/// @author bogdoslav, belbix
library ArrayLib {
string constant INDEX_OUT_OF_BOUND = "ArrayLib: Index out of bounds";
string constant NOT_UNIQUE_ITEM = "ArrayLib: Not unique item";
string constant ITEM_NOT_FOUND = "ArrayLib: Item not found";
/// @dev Return true if given item found in address array
function contains(address[] storage array, address _item) internal view returns (bool) {
for (uint256 i = 0; i < array.length; i++) {
if (array[i] == _item) return true;
}
return false;
}
/// @dev Return true if given item found in uin256 array
function contains(uint256[] storage array, uint256 _item) internal view returns (bool) {
for (uint256 i = 0; i < array.length; i++) {
if (array[i] == _item) return true;
}
return false;
}
// -----------------------------------
/// @dev If token not exist in the array push it, otherwise throw an error
function addUnique(address[] storage array, address _item) internal {
require(!contains(array, _item), NOT_UNIQUE_ITEM);
array.push(_item);
}
/// @dev If token not exist in the array push it, otherwise throw an error
function addUnique(uint256[] storage array, uint256 _item) internal {
require(!contains(array, _item), NOT_UNIQUE_ITEM);
array.push(_item);
}
// -----------------------------------
/// @dev Call addUnique for the given items array
function addUniqueArray(address[] storage array, address[] memory _items) internal {
for (uint256 i = 0; i < _items.length; i++) {
addUnique(array, _items[i]);
}
}
/// @dev Call addUnique for the given items array
function addUniqueArray(uint256[] storage array, uint256[] memory _items) internal {
for (uint i = 0; i < _items.length; i++) {
addUnique(array, _items[i]);
}
}
// -----------------------------------
/// @dev Remove an item by given index.
/// @param keepSorting If true the function will shift elements to the place of removed item
/// If false will move the last element on the place of removed item
function removeByIndex(address[] storage array, uint256 index, bool keepSorting) internal {
require(index < array.length, INDEX_OUT_OF_BOUND);
if (keepSorting) {
// shift all elements to the place of removed item
// the loop must not include the last element
for (uint256 i = index; i < array.length - 1; i++) {
array[i] = array[i + 1];
}
} else {
// copy the last address in the array
array[index] = array[array.length - 1];
}
array.pop();
}
/// @dev Remove an item by given index.
/// @param keepSorting If true the function will shift elements to the place of removed item
/// If false will move the last element on the place of removed item
function removeByIndex(uint256[] storage array, uint256 index, bool keepSorting) internal {
require(index < array.length, INDEX_OUT_OF_BOUND);
if (keepSorting) {
// shift all elements to the place of removed item
// the loop must not include the last element
for (uint256 i = index; i < array.length - 1; i++) {
array[i] = array[i + 1];
}
} else {
// copy the last address in the array
array[index] = array[array.length - 1];
}
array.pop();
}
// -----------------------------------
/// @dev Find given item in the array and call removeByIndex function if exist. If not throw an error
function findAndRemove(address[] storage array, address _item, bool keepSorting) internal {
for (uint256 i = 0; i < array.length; i++) {
if (array[i] == _item) {
removeByIndex(array, i, keepSorting);
return;
}
}
revert(ITEM_NOT_FOUND);
}
/// @dev Find given item in the array and call removeByIndex function if exist. If not throw an error
function findAndRemove(uint256[] storage array, uint256 _item, bool keepSorting) internal {
for (uint256 i = 0; i < array.length; i++) {
if (array[i] == _item) {
removeByIndex(array, i, keepSorting);
return;
}
}
revert(ITEM_NOT_FOUND);
}
// -----------------------------------
/// @dev Call findAndRemove function for given item array
function findAndRemoveArray(address[] storage array, address[] memory _items, bool keepSorting) internal {
for (uint256 i = 0; i < _items.length; i++) {
findAndRemove(array, _items[i], keepSorting);
}
}
/// @dev Call findAndRemove function for given item array
function findAndRemoveArray(uint256[] storage array, uint256[] memory _items, bool keepSorting) internal {
for (uint256 i = 0; i < _items.length; i++) {
findAndRemove(array, _items[i], keepSorting);
}
}
// -----------------------------------
/// @dev Remove from array the item with given id and move the last item on it place
/// Use with mapping for keeping indexes in correct ordering
function removeIndexed(
uint256[] storage array,
mapping(uint256 => uint256) storage indexes,
uint256 id
) internal {
uint256 lastId = array[array.length - 1];
uint256 index = indexes[id];
indexes[lastId] = index;
indexes[id] = type(uint256).max;
array[index] = lastId;
array.pop();
}
// ************* SORTING *******************
/// @dev Insertion sorting algorithm for using with arrays fewer than 10 elements
/// Based on https://medium.com/coinmonks/sorting-in-solidity-without-comparison-4eb47e04ff0d
function sortAddressesByUint(address[] storage addressArray, mapping(address => uint) storage uintMap) internal {
for (uint i = 1; i < addressArray.length; i++) {
address key = addressArray[i];
uint j = i - 1;
while ((int(j) >= 0) && uintMap[addressArray[j]] > uintMap[key]) {
addressArray[j + 1] = addressArray[j];
unchecked {j--;}
}
unchecked {
addressArray[j + 1] = key;
}
}
}
/// @dev Insertion sorting algorithm for using with arrays fewer than 10 elements
/// Based on https://medium.com/coinmonks/sorting-in-solidity-without-comparison-4eb47e04ff0d
function sortAddressesByUintReverted(address[] storage addressArray, mapping(address => uint) storage uintMap) internal {
for (uint i = 1; i < addressArray.length; i++) {
address key = addressArray[i];
uint j = i - 1;
while ((int(j) >= 0) && uintMap[addressArray[j]] < uintMap[key]) {
addressArray[j + 1] = addressArray[j];
unchecked {j--;}
}
unchecked {
addressArray[j + 1] = key;
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (metatx/ERC2771Context.sol)
pragma solidity ^0.8.1;
/**
* @dev Context variant with ERC2771 support.
*/
// based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/metatx/ERC2771Context.sol
abstract contract ERC2771Context {
// for whitelist new relayers need to add new constants and update proxies/redeploy contracts
// address private constant GELATO_RELAY = 0xaBcC9b596420A9E9172FD5938620E265a0f9Df92;
// address private constant GELATO_RELAY_ERC_2771 = 0xb539068872230f20456CF38EC52EF2f91AF4AE49;
// address private constant GELATO_RELAY_CONCURRENT_ERC_2771 = 0x8598806401A63Ddf52473F1B3C55bC9E33e2d73b;
// address private constant GELATO_RELAY_1_BALANCE = 0x75bA5Af8EFFDCFca32E1e288806d54277D1fde99;
address private constant GELATO_RELAY_1_BALANCE_ERC_2771 = 0xd8253782c45a12053594b9deB72d8e8aB2Fca54c;
// address private constant GELATO_RELAY_1_BALANCE_CONCURRENT_ERC_2771 = 0xc65d82ECE367EF06bf2AB791B3f3CF037Dc0e816;
function isTrustedForwarder(address forwarder) public view virtual returns (bool){
return forwarder == GELATO_RELAY_1_BALANCE_ERC_2771;
}
function _msgSender() internal view virtual returns (address sender) {
if (isTrustedForwarder(msg.sender)) {
// The assembly code is more direct than the Solidity version using `abi.decode`.
/// @solidity memory-safe-assembly
assembly {
sender := shr(96, calldataload(sub(calldatasize(), 20)))
}
return sender;
} else {
return msg.sender;
}
}
function _msgData() internal view virtual returns (bytes calldata) {
if (isTrustedForwarder(msg.sender)) {
return msg.data[: msg.data.length - 20];
} else {
return msg.data;
}
}
/// @notice Return true if given address is not a smart contract but a wallet address.
/// @dev It is not 100% guarantee after EIP-3074 implementation, use it as an additional check.
/// @return true if the address is a wallet.
function _isNotSmartContract() internal view returns (bool) {
return isTrustedForwarder(msg.sender) || msg.sender == tx.origin;
}
}// SPDX-License-Identifier: ISC
/**
* By using this software, you understand, acknowledge and accept that Tetu
* and/or the underlying software are provided “as is” and “as available”
* basis and without warranties or representations of any kind either expressed
* or implied. Any use of this open source software released under the ISC
* Internet Systems Consortium license is done at your own risk to the fullest
* extent permissible pursuant to applicable law any and all liability as well
* as all warranties, including any fitness for a particular purpose with respect
* to Tetu and/or the underlying software and the use thereof are disclaimed.
*/
pragma solidity 0.8.4;
/// @title Interface for Tetu PawnShop contract
/// @author belbix
interface ITetuPawnShop {
event PositionOpened(
address indexed sender,
uint256 posId,
address collateralToken,
uint256 collateralAmount,
uint256 collateralTokenId,
address acquiredToken,
uint256 acquiredAmount,
uint256 posDurationBlocks,
uint256 posFee
);
event PositionClosed(address indexed borrower, uint256 posId);
event BidExecuted(
uint256 posId,
uint256 bidId,
uint256 amount,
address acquiredMoneyHolder,
address lender
);
event AuctionBidOpened(uint256 posId, uint256 bidId, uint256 amount, address lender);
event PositionClaimed(address indexed sender, uint256 posId);
event PositionRedeemed(address indexed sender, uint256 posId);
event AuctionBidAccepted(address indexed borrower, uint256 posId, uint256 bidId);
event AuctionBidClosed(uint256 posId, uint256 bidId);
event GovernanceActionAnnounced(uint256 id, address addressValue, uint256 uintValue);
event OwnerChanged(address oldOwner, address newOwner);
event FeeRecipientChanged(address oldRecipient, address newRecipient);
event PlatformFeeChanged(uint256 oldFee, uint256 newFee);
event DepositAmountChanged(uint256 oldAmount, uint256 newAmount);
event DepositTokenChanged(address oldToken, address newToken);
enum GovernanceAction {
ChangeOwner, // 0
ChangeFeeRecipient, // 1
ChangePlatformFee, // 2
ChangePositionDepositAmount, // 3
ChangePositionDepositToken // 4
}
enum AssetType {
ERC20, // 0
ERC721 // 1
}
enum IndexType {
LIST, // 0
BY_COLLATERAL, // 1
BY_ACQUIRED, // 2
BORROWER_POSITION, // 3
LENDER_POSITION // 4
}
struct TimeLock {
uint256 time;
address addressValue;
uint256 uintValue;
}
struct Position {
uint256 id;
address borrower;
address depositToken;
uint256 depositAmount;
bool open;
uint minAuctionAmount;
PositionInfo info;
PositionCollateral collateral;
PositionAcquired acquired;
PositionExecution execution;
}
struct PositionInfo {
uint256 posDurationBlocks;
uint256 posFee;
uint256 createdBlock;
uint256 createdTs;
}
struct PositionCollateral {
address collateralToken;
AssetType collateralType;
uint256 collateralAmount;
uint256 collateralTokenId;
}
struct PositionAcquired {
address acquiredToken;
uint256 acquiredAmount;
}
struct PositionExecution {
address lender;
uint256 posStartBlock;
uint256 posStartTs;
uint256 posEndTs;
}
struct AuctionBid {
uint256 id;
uint256 posId;
address lender;
uint256 amount;
bool open;
}
// ****************** VIEWS ****************************
/// @dev PosId counter. Should start from 1 for keep 0 as empty value
function positionCounter() external view returns (uint256);
/// @notice Return Position for given id
/// @dev AbiEncoder not able to auto generate functions for mapping with structs
function getPosition(uint256 posId) external view returns (Position memory);
/// @dev Hold open positions ids. Removed when position closed
function openPositions(uint256 index) external view returns (uint256 posId);
/// @dev Collateral token => PosIds
function positionsByCollateral(address collateralToken, uint256 index) external view returns (uint256 posId);
/// @dev Acquired token => PosIds
function positionsByAcquired(address acquiredToken, uint256 index) external view returns (uint256 posId);
/// @dev Borrower token => PosIds
function borrowerPositions(address borrower, uint256 index) external view returns (uint256 posId);
/// @dev Lender token => PosIds
function lenderPositions(address lender, uint256 index) external view returns (uint256 posId);
/// @dev index type => PosId => index
/// Hold array positions for given type of array
function posIndexes(IndexType typeId, uint256 posId) external view returns (uint256 index);
/// @dev BidId counter. Should start from 1 for keep 0 as empty value
function auctionBidCounter() external view returns (uint256);
/// @notice Return auction bid for given id
/// @dev AbiEncoder not able to auto generate functions for mapping with structs
function getAuctionBid(uint256 bidId) external view returns (AuctionBid memory);
/// @dev lender => PosId => positionToBidIds + 1
/// Lender auction position for given PosId. 0 keep for empty position
function lenderOpenBids(address lender, uint256 posId) external view returns (uint256 index);
/// @dev PosId => bidIds. All open and close bids for the given position
function positionToBidIds(uint256 posId, uint256 index) external view returns (uint256 bidId);
/// @dev PosId => timestamp. Timestamp of the last bid for the auction
function lastAuctionBidTs(uint256 posId) external view returns (uint256 ts);
/// @dev Return amount required for redeem position
function toRedeem(uint256 posId) external view returns (uint256 amount);
/// @dev Return asset type ERC20 or ERC721
function getAssetType(address _token) external view returns (AssetType);
function isERC721(address _token) external view returns (bool);
function isERC20(address _token) external view returns (bool);
/// @dev Return size of active positions
function openPositionsSize() external view returns (uint256);
/// @dev Return size of all auction bids for given position
function auctionBidSize(uint256 posId) external view returns (uint256);
function positionsByCollateralSize(address collateral) external view returns (uint256);
function positionsByAcquiredSize(address acquiredToken) external view returns (uint256);
function borrowerPositionsSize(address borrower) external view returns (uint256);
function lenderPositionsSize(address lender) external view returns (uint256);
// ************* USER ACTIONS *************
/// @dev Borrower action. Assume approve
/// Allows the user to create a new borrowing position by depositing their collateral tokens.
function openPosition(
address _collateralToken,
uint256 _collateralAmount,
uint256 _collateralTokenId,
address _acquiredToken,
uint256 _acquiredAmount,
uint256 _posDurationBlocks,
uint256 _posFee,
uint minAuctionPrice
) external returns (uint256);
/// @dev Borrower action
/// Close not executed position. Return collateral and deposit to borrower
function closePosition(uint256 id) external;
/// @dev Lender action. Assume approve for acquired token
/// Place a bid for given position ID
/// It can be an auction bid if acquired amount is zero
function bid(uint256 id, uint256 amount) external;
/// @dev Lender action
/// Transfer collateral to lender if borrower didn't return the loan
/// Deposit will be returned to borrower
function claim(uint256 id) external;
/// @dev Borrower action. Assume approve on acquired token
/// Return the loan to lender, transfer collateral and deposit to borrower
function redeem(uint256 id) external;
/// @dev Borrower action. Assume that auction ended.
/// Transfer acquired token to borrower
function acceptAuctionBid(uint256 posId) external;
/// @dev Lender action. Requires ended auction, or not the last bid
/// Close auction bid and transfer acquired tokens to lender
function closeAuctionBid(uint256 bidId) external;
/// @dev Announce governance action
function announceGovernanceAction(GovernanceAction id, address addressValue, uint256 uintValue) external;
/// @dev Set new contract owner
function setOwner(address _newOwner) external;
/// @dev Set new fee recipient
function setFeeRecipient(address _newFeeRecipient) external;
/// @dev Platform fee in range 0 - 500, with denominator 10000
function setPlatformFee(uint256 _value) external;
/// @dev Tokens amount that need to deposit for a new position
/// Will be returned when position closed
function setPositionDepositAmount(uint256 _value) external;
/// @dev Tokens that need to deposit for a new position
function setPositionDepositToken(address _value) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @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
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC721Receiver.sol";
/**
* @dev Implementation of the {IERC721Receiver} interface.
*
* Accepts all token transfers.
* Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}.
*/
contract ERC721Holder is IERC721Receiver {
/**
* @dev See {IERC721Receiver-onERC721Received}.
*
* Always returns `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address,
address,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}{
"optimizer": {
"enabled": true,
"runs": 150
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_depositToken","type":"address"},{"internalType":"uint256","name":"_positionDepositAmount","type":"uint256"},{"internalType":"address","name":"_feeRecipient","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"posId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bidId","type":"uint256"}],"name":"AuctionBidAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"posId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bidId","type":"uint256"}],"name":"AuctionBidClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"posId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bidId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"lender","type":"address"}],"name":"AuctionBidOpened","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"posId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bidId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"acquiredMoneyHolder","type":"address"},{"indexed":false,"internalType":"address","name":"lender","type":"address"}],"name":"BidExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newAmount","type":"uint256"}],"name":"DepositAmountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldToken","type":"address"},{"indexed":false,"internalType":"address","name":"newToken","type":"address"}],"name":"DepositTokenChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldRecipient","type":"address"},{"indexed":false,"internalType":"address","name":"newRecipient","type":"address"}],"name":"FeeRecipientChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"addressValue","type":"address"},{"indexed":false,"internalType":"uint256","name":"uintValue","type":"uint256"}],"name":"GovernanceActionAnnounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"PlatformFeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"posId","type":"uint256"}],"name":"PositionClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"posId","type":"uint256"}],"name":"PositionClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"posId","type":"uint256"},{"indexed":false,"internalType":"address","name":"collateralToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralTokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"acquiredToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"acquiredAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"posDurationBlocks","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"posFee","type":"uint256"}],"name":"PositionOpened","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"posId","type":"uint256"}],"name":"PositionRedeemed","type":"event"},{"inputs":[],"name":"AUCTION_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PLATFORM_FEE_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIME_LOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"posId","type":"uint256"}],"name":"acceptAuctionBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ITetuPawnShop.GovernanceAction","name":"id","type":"uint8"},{"internalType":"address","name":"addressValue","type":"address"},{"internalType":"uint256","name":"uintValue","type":"uint256"}],"name":"announceGovernanceAction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"auctionBidCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"posId","type":"uint256"}],"name":"auctionBidSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"auctionBids","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"posId","type":"uint256"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"open","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"bid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"borrowerPositions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"borrower","type":"address"}],"name":"borrowerPositionsSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegateContract","type":"address"},{"internalType":"bytes32","name":"_id","type":"bytes32"}],"name":"clearDelegatedVotes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bidId","type":"uint256"}],"name":"closeAuctionBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"closePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"createdBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"createdTs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_delegateContract","type":"address"},{"internalType":"bytes32","name":"_id","type":"bytes32"},{"internalType":"address","name":"_delegate","type":"address"}],"name":"delegateVotes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getAssetType","outputs":[{"internalType":"enum ITetuPawnShop.AssetType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bidId","type":"uint256"}],"name":"getAuctionBid","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"posId","type":"uint256"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"open","type":"bool"}],"internalType":"struct ITetuPawnShop.AuctionBid","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"posId","type":"uint256"}],"name":"getPosition","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"address","name":"depositToken","type":"address"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"bool","name":"open","type":"bool"},{"internalType":"uint256","name":"minAuctionAmount","type":"uint256"},{"components":[{"internalType":"uint256","name":"posDurationBlocks","type":"uint256"},{"internalType":"uint256","name":"posFee","type":"uint256"},{"internalType":"uint256","name":"createdBlock","type":"uint256"},{"internalType":"uint256","name":"createdTs","type":"uint256"}],"internalType":"struct ITetuPawnShop.PositionInfo","name":"info","type":"tuple"},{"components":[{"internalType":"address","name":"collateralToken","type":"address"},{"internalType":"enum ITetuPawnShop.AssetType","name":"collateralType","type":"uint8"},{"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"internalType":"uint256","name":"collateralTokenId","type":"uint256"}],"internalType":"struct ITetuPawnShop.PositionCollateral","name":"collateral","type":"tuple"},{"components":[{"internalType":"address","name":"acquiredToken","type":"address"},{"internalType":"uint256","name":"acquiredAmount","type":"uint256"}],"internalType":"struct ITetuPawnShop.PositionAcquired","name":"acquired","type":"tuple"},{"components":[{"internalType":"address","name":"lender","type":"address"},{"internalType":"uint256","name":"posStartBlock","type":"uint256"},{"internalType":"uint256","name":"posStartTs","type":"uint256"},{"internalType":"uint256","name":"posEndTs","type":"uint256"}],"internalType":"struct ITetuPawnShop.PositionExecution","name":"execution","type":"tuple"}],"internalType":"struct ITetuPawnShop.Position","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"isERC20","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"isERC721","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastAuctionBidTs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"lenderOpenBids","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"lenderPositions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"lender","type":"address"}],"name":"lenderPositionsSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collateralToken","type":"address"},{"internalType":"uint256","name":"_collateralAmount","type":"uint256"},{"internalType":"uint256","name":"_collateralTokenId","type":"uint256"},{"internalType":"address","name":"_acquiredToken","type":"address"},{"internalType":"uint256","name":"_acquiredAmount","type":"uint256"},{"internalType":"uint256","name":"_posDurationBlocks","type":"uint256"},{"internalType":"uint256","name":"_posFee","type":"uint256"},{"internalType":"uint256","name":"minAuctionAmount","type":"uint256"}],"name":"openPosition","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"openPositions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openPositionsSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ITetuPawnShop.IndexType","name":"","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"posIndexes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"positionCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"positionDepositAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"positionDepositToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"positionToBidIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"positions","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"address","name":"depositToken","type":"address"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"bool","name":"open","type":"bool"},{"internalType":"uint256","name":"minAuctionAmount","type":"uint256"},{"components":[{"internalType":"uint256","name":"posDurationBlocks","type":"uint256"},{"internalType":"uint256","name":"posFee","type":"uint256"},{"internalType":"uint256","name":"createdBlock","type":"uint256"},{"internalType":"uint256","name":"createdTs","type":"uint256"}],"internalType":"struct ITetuPawnShop.PositionInfo","name":"info","type":"tuple"},{"components":[{"internalType":"address","name":"collateralToken","type":"address"},{"internalType":"enum ITetuPawnShop.AssetType","name":"collateralType","type":"uint8"},{"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"internalType":"uint256","name":"collateralTokenId","type":"uint256"}],"internalType":"struct ITetuPawnShop.PositionCollateral","name":"collateral","type":"tuple"},{"components":[{"internalType":"address","name":"acquiredToken","type":"address"},{"internalType":"uint256","name":"acquiredAmount","type":"uint256"}],"internalType":"struct ITetuPawnShop.PositionAcquired","name":"acquired","type":"tuple"},{"components":[{"internalType":"address","name":"lender","type":"address"},{"internalType":"uint256","name":"posStartBlock","type":"uint256"},{"internalType":"uint256","name":"posStartTs","type":"uint256"},{"internalType":"uint256","name":"posEndTs","type":"uint256"}],"internalType":"struct ITetuPawnShop.PositionExecution","name":"execution","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"positionsByAcquired","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"acquiredToken","type":"address"}],"name":"positionsByAcquiredSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"positionsByCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collateral","type":"address"}],"name":"positionsByCollateralSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newFeeRecipient","type":"address"}],"name":"setFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"setPlatformFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"setPositionDepositAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_value","type":"address"}],"name":"setPositionDepositToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ITetuPawnShop.GovernanceAction","name":"","type":"uint8"}],"name":"timeLocks","outputs":[{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"address","name":"addressValue","type":"address"},{"internalType":"uint256","name":"uintValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"toRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60c0604052606460035560016007556001600f553480156200002057600080fd5b5060405162004f9e38038062004f9e83398101604081905262000043916200015d565b60016000556001600160a01b038416620000965760405162461bcd60e51b815260206004820152600f60248201526e2a28299d102d32b9379037bbb732b960891b60448201526064015b60405180910390fd5b6001600160a01b038116620000ee5760405162461bcd60e51b815260206004820152601660248201527f5450533a205a65726f20666565526563697069656e740000000000000000000060448201526064016200008d565b600180546001600160a01b039586166001600160a01b03199182161790915560028054928616928216929092179091556005805493909416921691909117909155426080524360a052600455620001b0565b80516001600160a01b03811681146200015857600080fd5b919050565b6000806000806080858703121562000173578384fd5b6200017e8562000140565b93506200018e6020860162000140565b925060408501519150620001a56060860162000140565b905092959194509250565b60805160a051614dc8620001d6600039600061055a015260006108ef0152614dc86000f3fe608060405234801561001057600080fd5b50600436106102ec5760003560e01c80638137884a11610193578063b8f1a962116100e4578063e0a09c6811610092578063e0a09c681461083f578063e5b595aa14610849578063e74b981b1461085c578063eb02c3011461086f578063eb07365f1461088f578063f070ba03146108ea578063ffa1ad741461091157600080fd5b8063b8f1a9621461074b578063c50981a11461075e578063c84d966514610771578063d2ec0025146107f3578063daa09e5414610806578063db006a7514610819578063db2dbb441461082c57600080fd5b806399fbab881161014157806399fbab88146106a35780639c8ae080146106cc578063a126d601146106df578063a271e525146106f2578063a27219e5146106fc578063a93d789f14610725578063b25a8ea31461073857600080fd5b80638137884a1461063957806382bd0b8c14610642578063884399be1461064b5780638da5cb5b146106535780638e24676214610666578063918f86741461069157806398584c0f1461069a57600080fd5b806326232a2e1161024d57806346904840116101fb578063469048401461057c57806352eb916f146105a7578063572b6c05146105ba578063598647f8146105ea5780635a905e10146105fd57806363d5ab8d1461061057806381165ec61461061957600080fd5b806326232a2e14610495578063263e0c1b1461049e578063347d50c5146104c1578063379607f51461051c5780633a5edc541461052f5780633e87290b146105425780634593144c1461055557600080fd5b806314e5f479116102aa57806314e5f4791461039b578063150b7a02146103c45780631abda8e4146103fb5780631c7c565a146104245780631dcea853146104445780632404e26d1461046f578063248a19bb1461048257600080fd5b80624ce3d3146102f1578063032c49ed1461032d5780630580c0321461034d578063106f76351461036057806312e8e2c31461037557806313af403514610388575b600080fd5b61031a6102ff36600461464d565b6001600160a01b03166000908152600c602052604090205490565b6040519081526020015b60405180910390f35b61034061033b36600461464d565b610942565b6040516103249190614990565b61031a61035b36600461473c565b610953565b61037361036e36600461489f565b610984565b005b61037361038336600461489f565b610bdc565b61037361039636600461464d565b610e43565b61031a6103a936600461464d565b6001600160a01b03166000908152600a602052604090205490565b6103e26103d2366004614667565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610324565b61031a61040936600461464d565b6001600160a01b03166000908152600b602052604090205490565b61031a61043236600461489f565b60009081526012602052604090205490565b61031a610452366004614882565b600e60209081526000928352604080842090915290825290205481565b61031a61047d36600461489f565b61107f565b61037361049036600461489f565b61108a565b61031a60035481565b6104b16104ac36600461464d565b61125c565b6040519015158152602001610324565b6104f96104cf366004614829565b60066020526000908152604090208054600182015460029092015490916001600160a01b03169083565b604080519384526001600160a01b03909216602084015290820152606001610324565b61037361052a36600461489f565b611267565b61031a61053d3660046147a0565b6114a5565b61037361055036600461473c565b611cb6565b61031a7f000000000000000000000000000000000000000000000000000000000000000081565b60025461058f906001600160a01b031681565b6040516001600160a01b039091168152602001610324565b61031a6105b536600461473c565b611d4e565b6104b16105c836600461464d565b6001600160a01b031673d8253782c45a12053594b9deb72d8e8ab2fca54c1490565b6103736105f83660046148cf565b611d6a565b61037361060b366004614845565b611ed1565b61031a60075481565b61031a61062736600461489f565b60136020526000908152604090205481565b61031a6101f481565b61031a600f5481565b60095461031a565b60015461058f906001600160a01b031681565b61031a61067436600461473c565b601160209081526000928352604080842090915290825290205481565b61031a61271081565b61031a60045481565b6106b66106b136600461489f565b6120cc565b6040516103249a99989796959493929190614bfa565b6103736106da36600461489f565b61221e565b6103736106ed36600461489f565b612571565b61031a6201518081565b61031a61070a36600461464d565b6001600160a01b03166000908152600d602052604090205490565b61031a61073336600461473c565b6129ad565b61037361074636600461464d565b6129c9565b61031a61075936600461473c565b612bbb565b61031a61076c3660046148cf565b612bd7565b6107bb61077f36600461489f565b60106020526000908152604090208054600182015460028301546003840154600490940154929391926001600160a01b03909116919060ff1685565b6040805195865260208601949094526001600160a01b039092169284019290925260608301919091521515608082015260a001610324565b61031a61080136600461489f565b612bf3565b6104b161081436600461464d565b612c14565b61037361082736600461489f565b612c1f565b60055461058f906001600160a01b031681565b61031a6202a30081565b610373610857366004614765565b612e35565b61037361086a36600461464d565b612ed7565b61088261087d36600461489f565b613113565b6040516103249190614b0e565b6108a261089d36600461489f565b6132a1565b604051610324919081518152602080830151908201526040808301516001600160a01b0316908201526060808301519082015260809182015115159181019190915260a00190565b61031a7f000000000000000000000000000000000000000000000000000000000000000081565b61093560405180604001604052806005815260200164312e302e3760d81b81525081565b604051610324919061499e565b600061094d8261333b565b92915050565b600c602052816000526040600020818154811061096f57600080fd5b90600052602060002001600091509150505481565b600260005414156109b05760405162461bcd60e51b81526004016109a790614aaf565b60405180910390fd5b600260009081558181526010602052604090208054610a0e5760405162461bcd60e51b815260206004820152601a602482015279151414ce88105d58dd1a5bdb88189a59081b9bdd08199bdd5b9960321b60448201526064016109a7565b60018101546000908152600860209081526040808320805484526013909252822054909142610a406201518084614ca4565b109050600042610a536201518085614ca4565b610a609062127500614ca4565b85546000908152601260205260408120549290911092509015610acb57845460009081526012602052604081208054610a9b90600190614cfb565b81548110610ab957634e487b7160e01b600052603260045260246000fd5b60009182526020909120015488149150505b808015610ad55750825b80610ade575080155b80610aee5750600485015460ff16155b80610af65750815b610b425760405162461bcd60e51b815260206004820152601960248201527f5450533a2041756374696f6e206973206e6f7420656e6465640000000000000060448201526064016109a7565b60028601546001600160a01b0390811660008181526011602090815260408083208a54845290915281205560048801805460ff191690556003880154600d8801549192610b9292169083906133ab565b855460408051918252602082018a90527f6a87dc49655b8e89257f75d88376c42ba5c050bf610a2c3f76148f127947f9c8910160405180910390a150506001600055505050505050565b6001546001600160a01b0316610bf0613413565b6001600160a01b031614610c165760405162461bcd60e51b81526004016109a790614ae6565b6002600081815260066020908152604080516060810182527f8819ef417987f8ae7a81f42cdfb18815282fe989326fbff903d13cf0e03ace29548082527f8819ef417987f8ae7a81f42cdfb18815282fe989326fbff903d13cf0e03ace2a546001600160a01b0316938201939093527f8819ef417987f8ae7a81f42cdfb18815282fe989326fbff903d13cf0e03ace2b5491810191909152849115801590610cbe5750805142115b610cda5760405162461bcd60e51b81526004016109a7906149d1565b6001600160a01b03831615610d1e57826001600160a01b031681602001516001600160a01b031614610d1e5760405162461bcd60e51b81526004016109a790614a56565b8115610d475781816040015114610d475760405162461bcd60e51b81526004016109a790614a27565b6101f4851115610d8d5760405162461bcd60e51b81526020600482015260116024820152705450533a20546f6f20686967682066656560781b60448201526064016109a7565b60035460408051918252602082018790527fc98a8b10b63c929f7799380bb4a0c444c713ebf74d8732f944c915034121aad1910160405180910390a1600385905560066000856004811115610df257634e487b7160e01b600052602160045260246000fd5b6004811115610e1157634e487b7160e01b600052602160045260246000fd5b8152602081019190915260400160009081208181556001810180546001600160a01b0319169055600201555050505050565b6001546001600160a01b0316610e57613413565b6001600160a01b031614610e7d5760405162461bcd60e51b81526004016109a790614ae6565b600080805260066020908152604080516060810182527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8548082527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f9546001600160a01b0316938201939093527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4fa5491810191909152839183919015801590610f265750805142115b610f425760405162461bcd60e51b81526004016109a7906149d1565b6001600160a01b03831615610f8657826001600160a01b031681602001516001600160a01b031614610f865760405162461bcd60e51b81526004016109a790614a56565b8115610faf5781816040015114610faf5760405162461bcd60e51b81526004016109a790614a27565b6001600160a01b038516610ff95760405162461bcd60e51b81526020600482015260116024820152705450533a205a65726f206164647265737360781b60448201526064016109a7565b600154604080516001600160a01b03928316815291871660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180546001600160a01b0319166001600160a01b03871617905560066000856004811115610df257634e487b7160e01b600052602160045260246000fd5b600061094d82613443565b6001546001600160a01b031661109e613413565b6001600160a01b0316146110c45760405162461bcd60e51b81526004016109a790614ae6565b6003600081815260066020908152604080516060810182527f75f96ab15d697e93042dc45b5c896c4b27e89bb6eaf39475c5c371cb2513f7d2548082527f75f96ab15d697e93042dc45b5c896c4b27e89bb6eaf39475c5c371cb2513f7d3546001600160a01b0316938201939093527f75f96ab15d697e93042dc45b5c896c4b27e89bb6eaf39475c5c371cb2513f7d4549181019190915284911580159061116c5750805142115b6111885760405162461bcd60e51b81526004016109a7906149d1565b6001600160a01b038316156111cc57826001600160a01b031681602001516001600160a01b0316146111cc5760405162461bcd60e51b81526004016109a790614a56565b81156111f557818160400151146111f55760405162461bcd60e51b81526004016109a790614a27565b60045460408051918252602082018790527fe8a90a4e7ae8a56c5c24412551b21d6b4557535da5309263e34d818103e15096910160405180910390a18460048190555060066000856004811115610df257634e487b7160e01b600052602160045260246000fd5b600061094d82613613565b6002600054141561128a5760405162461bcd60e51b81526004016109a790614aaf565b60026000908155818152600860205260409020805482146112bd5760405162461bcd60e51b81526004016109a790614a88565b6112c5613413565b600f8201546001600160a01b039081169116146113245760405162461bcd60e51b815260206004820152601a60248201527f5450533a204f6e6c79206c656e6465722063616e20636c61696d00000000000060448201526064016109a7565b6006810154601082015460009161133a91614ca4565b90504381106113855760405162461bcd60e51b81526020600482015260176024820152765450533a20546f6f206561726c7920746f20636c61696d60481b60448201526064016109a7565b600482015460ff166113a95760405162461bcd60e51b81526004016109a7906149f9565b6113b282613697565b6040805160808101909152600a830180546001600160a01b03811683526114489291906020830190600160a01b900460ff16600181111561140357634e487b7160e01b600052602160045260246000fd5b600181111561142257634e487b7160e01b600052602160045260246000fd5b81526020016001820154815260200160028201548152505030611443613413565b613760565b6114518361388c565b611459613413565b6001600160a01b03167ffa6e92366c16d5c789e26dd0b930fddd4e37c6115049c4d123cb73c529362fa98460405161149391815260200190565b60405180910390a25050600160005550565b6000600260005414156114ca5760405162461bcd60e51b81526004016109a790614aaf565b60026000556114dc612710600a614cdc565b83111561152b5760405162461bcd60e51b815260206004820152601a60248201527f5450533a20506f7320666565206162737572646c79206869676800000000000060448201526064016109a7565b83151580611537575082155b61158f5760405162461bcd60e51b815260206004820152602360248201527f5450533a2046656520666f7220696e7374616e74206465616c20666f726269646044820152623232b760e91b60648201526084016109a7565b8715158061159c57508615155b6115dd5760405162461bcd60e51b81526020600482015260126024820152715450533a2057726f6e6720616d6f756e747360701b60448201526064016109a7565b6001600160a01b0389166116265760405162461bcd60e51b815260206004820152601060248201526f2a28299d102d32b9379031aa37b5b2b760811b60448201526064016109a7565b6001600160a01b03861661166f5760405162461bcd60e51b815260206004820152601060248201526f2a28299d102d32b9379030aa37b5b2b760811b60448201526064016109a7565b600061167a8a61333b565b9050600081600181111561169e57634e487b7160e01b600052602160045260246000fd5b1480156116aa57508815155b80156116b4575087155b806116f2575060018160018111156116dc57634e487b7160e01b600052602160045260246000fd5b1480156116e7575088155b80156116f257508715155b61172f5760405162461bcd60e51b815260206004820152600e60248201526d151414ce88125b98dbdc9c9958dd60921b60448201526064016109a7565b611737614545565b60006040518060800160405280888152602001878152602001438152602001428152509050600060405180608001604052808e6001600160a01b0316815260200185600181111561179857634e487b7160e01b600052602160045260246000fd5b815260208082018f905260409182018e9052815180830183526001600160a01b038e1681528082018d90528251608081018452600080825281840181905281850181905260608201528351610140810190945260075484529394509291908101611800613413565b6001600160a01b0390811682526005541660208201526004546040820152600160608201819052608082018b905260a082019690965260c081019490945260e084019290925261010090920191909152805160098054808501825560008290527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0191909155549092506118949190614cfb565b6000808052600e6020908152835182527fe710864318d4a32f37d6ce54cb3fadbef648dd12d8dbdf53973564d56b7f881c81526040808320939093556001600160a01b038e16808352600a8252928220845181546001808201845583865293852001559290915290546119079190614cfb565b60016000818152600e6020908152845182527fa7c5ba7114a813b50159add3a36832908dc83db71d0b9a24c2ad0f83be95820781526040808320949094556001600160a01b038c16808352600b825293822085518154808601835582855292842090920191909155929052905461197e9190614cfb565b60026000908152600e6020908152835182527f9adb202b1492743bc00c81d33cdc6423fa8c79109027eb6a845391e8fc1f048190526040812091909155600c906119c6613413565b6001600160a01b031681526020808201929092526040016000908120835181546001818101845592845293832090930192909255600c90611a05613413565b6001600160a01b03168152602081019190915260400160002054611a299190614cfb565b60036000818152600e6020908152845182527fe0283e559c29e31ee7f56467acc9dd307779c843a883aeeb3bf5c6128c9081448152604080832094909455845182526008808252918490208551815585820151600180830180546001600160a01b03199081166001600160a01b03948516179091558888015160028501805483169185169190911790556060808a015197850197909755608089015160048501805460ff191691151591909117905560a0890151600585015560c08901518051600686015580860151600786015597880151958401959095559590940151600982015560e08601518051600a83018054958616919096169081178655928101518796929591949193909284926001600160a81b03191690911790600160a01b908490811115611b6857634e487b7160e01b600052602160045260246000fd5b021790555060408281015160018301556060928301516002909201919091556101008401518051600d850180546001600160a01b039283166001600160a01b031991821617909155602092830151600e870155610120909601518051600f8701805491909316971696909617905584015160108401558301516011830155919091015160129091015560078054906000611c0183614d3e565b90915550508051611c11906138d8565b611c278160e00151611c21613413565b30613760565b611c2f613413565b8151604080519182526001600160a01b038e811660208401528282018e9052606083018d90528b8116608084015260a083018b905260c083018a905260e0830189905290519216917fb3a36ac05090f711e42b60c13a82d445eeea0e6aa81bb29143354d10f02de515918190036101000190a25160016000559a9950505050505050505050565b6001546001600160a01b0316611cca613413565b6001600160a01b031614611cf05760405162461bcd60e51b81526004016109a790614ae6565b60405163785f6df160e11b8152600481018290526001600160a01b0383169063f0bedbe290602401600060405180830381600087803b158015611d3257600080fd5b505af1158015611d46573d6000803e3d6000fd5b505050505050565b600b602052816000526040600020818154811061096f57600080fd5b60026000541415611d8d5760405162461bcd60e51b81526004016109a790614aaf565b6002600090815582815260086020526040902080548314611dc05760405162461bcd60e51b81526004016109a790614a88565b600481015460ff16611de45760405162461bcd60e51b81526004016109a7906149f9565b600f8101546001600160a01b031615611e3f5760405162461bcd60e51b815260206004820181905260248201527f5450533a2043616e27742062696420657865637574656420706f736974696f6e60448201526064016109a7565b600e81015415611eb557600e8101548214611e945760405162461bcd60e51b8152602060048201526015602482015274151414ce8815dc9bdb99c8189a5908185b5bdd5b9d605a1b60448201526064016109a7565b611eb081600084611ea3613413565b611eab613413565b613922565b611ec7565b611ec78183611ec2613413565b613ce3565b5050600160005550565b6001546001600160a01b0316611ee5613413565b6001600160a01b031614611f0b5760405162461bcd60e51b81526004016109a790614ae6565b60066000846004811115611f2f57634e487b7160e01b600052602160045260246000fd5b6004811115611f4e57634e487b7160e01b600052602160045260246000fd5b815260208101919091526040016000205415611fa55760405162461bcd60e51b8152602060048201526016602482015275151414ce88105b1c9958591e48185b9b9bdd5b98d95960521b60448201526064016109a7565b60405180606001604052806202a30042611fbf9190614ca4565b81526001600160a01b038416602082015260400182905260066000856004811115611ffa57634e487b7160e01b600052602160045260246000fd5b600481111561201957634e487b7160e01b600052602160045260246000fd5b8152602080820192909252604090810160002083518155918301516001830180546001600160a01b0319166001600160a01b0390921691909117905591909101516002909101557f86496aa80f046dc4404f94bce44e24d8e17dc1bb123e8c774ff23ce0e6f0aabe8360048111156120a157634e487b7160e01b600052602160045260246000fd5b604080519182526001600160a01b0385166020830152810183905260600160405180910390a1505050565b600860208181526000928352604092839020805460018083015460028401546003850154600486015460058701548a5160808082018d5260068a0154825260078a0154828c01529a890154818d0152600989015460608201528b519a8b01909b52600a880180546001600160a01b038181168d52989c9689169b9590981699939860ff938416989297909594919391850192600160a01b90049091169081111561218657634e487b7160e01b600052602160045260246000fd5b60018111156121a557634e487b7160e01b600052602160045260246000fd5b8152600182015460208083019190915260029092015460409182015280518082018252600d8501546001600160a01b039081168252600e860154828501528251608081018452600f870154909116815260108601549381019390935260118501549183019190915260129093015460608201529091908a565b600260005414156122415760405162461bcd60e51b81526004016109a790614aaf565b60026000908155818152601360205260409020544290612265906201518090614ca4565b106122ab5760405162461bcd60e51b8152602060048201526016602482015275151414ce88105d58dd1a5bdb881b9bdd08195b99195960521b60448201526064016109a7565b6000818152601260205260409020546122f55760405162461bcd60e51b815260206004820152600c60248201526b5450533a204e6f206269647360a01b60448201526064016109a7565b6000818152601260205260408120805461231190600190614cfb565b8154811061232f57634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910154808352601090915260409091208054919250906123995760405162461bcd60e51b815260206004820152601a602482015279151414ce88105d58dd1a5bdb88189a59081b9bdd08199bdd5b9960321b60448201526064016109a7565b600481015460ff166123df5760405162461bcd60e51b815260206004820152600f60248201526e151414ce88109a590818db1bdcd959608a1b60448201526064016109a7565b828160010154146124235760405162461bcd60e51b815260206004820152600e60248201526d151414ce8815dc9bdb99c8189a5960921b60448201526064016109a7565b6000838152600860205260409020612439613413565b60018201546001600160a01b0390811691161461248c5760405162461bcd60e51b81526020600482015260116024820152702a28299d102737ba103137b93937bbb2b960791b60448201526064016109a7565b600481015460ff166124b05760405162461bcd60e51b81526004016109a7906149f9565b6003820154600e820181905560028301546124da91839186919030906001600160a01b0316613922565b60028201546001600160a01b031660009081526011602090815260408083208454845290915281205560048201805460ff19169055612517613413565b6001600160a01b03167f493e1e7f0e9233f36d4697a11b43b59a1507e08e3c1f920549858785646ac17985846000015460405161255e929190918252602082015260400190565b60405180910390a2505060016000555050565b600260005414156125945760405162461bcd60e51b81526004016109a790614aaf565b60026000908155818152600860205260409020805482146125c75760405162461bcd60e51b81526004016109a790614a88565b6125cf613413565b60018201546001600160a01b0390811691161461263e5760405162461bcd60e51b815260206004820152602760248201527f5450533a204f6e6c7920626f72726f7765722063616e20636c6f73652061207060448201526637b9b4ba34b7b760c91b60648201526084016109a7565b600f8101546001600160a01b0316156126a45760405162461bcd60e51b815260206004820152602260248201527f5450533a2043616e277420636c6f736520657865637574656420706f7369746960448201526137b760f11b60648201526084016109a7565b600481015460ff166126c85760405162461bcd60e51b81526004016109a7906149f9565b6040805161014081018252825481526001808401546001600160a01b0390811660208085019190915260028601548216848601526003860154606080860191909152600487015460ff9081161515608080880191909152600589015460a08801528751808201895260068a0154815260078a01548186015260088a0154818a015260098a01549381019390935260c08701929092528651918201909652600a87018054938416825261284b96889560e08801959394929392850192600160a01b9004909116908111156127ab57634e487b7160e01b600052602160045260246000fd5b60018111156127ca57634e487b7160e01b600052602160045260246000fd5b8152600182015460208083019190915260029092015460409182015291835281518083018352600d8501546001600160a01b039081168252600e86015482840152848301919091528251608081018452600f86015490911681526010850154918101919091526011840154818301526012909301546060840152015261405e565b6128a9600e600060035b600481111561287457634e487b7160e01b600052602160045260246000fd5b815260208082019290925260409081016000908120855460018701546001600160a01b03168352600c90945291902091614140565b6040805160808101909152600a820180546001600160a01b03811683526129459291906020830190600160a01b900460ff1660018111156128fa57634e487b7160e01b600052602160045260246000fd5b600181111561291957634e487b7160e01b600052602160045260246000fd5b8152600182810154602083015260029092015460409091015283015430906001600160a01b0316613760565b61294e8261388c565b60048101805460ff19169055612962613413565b6001600160a01b03167fa9e0cdf27a7965d21573ebb808fbcb2c2a1cfd656e1ecf3f82549437b47406778360405161299c91815260200190565b60405180910390a250506001600055565b600d602052816000526040600020818154811061096f57600080fd5b6001546001600160a01b03166129dd613413565b6001600160a01b031614612a035760405162461bcd60e51b81526004016109a790614ae6565b6004600081815260066020908152604080516060810182527fc5069e24aaadb2addc3e52e868fcf3f4f8acf5a87e24300992fd4540c2a87eed548082527fc5069e24aaadb2addc3e52e868fcf3f4f8acf5a87e24300992fd4540c2a87eee546001600160a01b0316938201939093527fc5069e24aaadb2addc3e52e868fcf3f4f8acf5a87e24300992fd4540c2a87eef549181019190915284929115801590612aac5750805142115b612ac85760405162461bcd60e51b81526004016109a7906149d1565b6001600160a01b03831615612b0c57826001600160a01b031681602001516001600160a01b031614612b0c5760405162461bcd60e51b81526004016109a790614a56565b8115612b355781816040015114612b355760405162461bcd60e51b81526004016109a790614a27565b600554604080516001600160a01b03928316815291871660208301527f709d4a2a735567787a6859678c4b234a262c4355d6d33796ddb4ef59f80c6621910160405180910390a1600580546001600160a01b0319166001600160a01b03871617905560066000856004811115610df257634e487b7160e01b600052602160045260246000fd5b600a602052816000526040600020818154811061096f57600080fd5b6012602052816000526040600020818154811061096f57600080fd5b60098181548110612c0357600080fd5b600091825260209091200154905081565b600061094d82614210565b60026000541415612c425760405162461bcd60e51b81526004016109a790614aaf565b6002600090815581815260086020526040902080548214612c755760405162461bcd60e51b81526004016109a790614a88565b612c7d613413565b60018201546001600160a01b03908116911614612cdc5760405162461bcd60e51b815260206004820152601d60248201527f5450533a204f6e6c7920626f72726f7765722063616e2072656465656d00000060448201526064016109a7565b600f8101546001600160a01b0316612d365760405162461bcd60e51b815260206004820152601a60248201527f5450533a204e6f7420657865637574656420706f736974696f6e00000000000060448201526064016109a7565b600481015460ff16612d5a5760405162461bcd60e51b81526004016109a7906149f9565b612d6381613697565b6000612d6e83613443565b9050612d99612d7b613413565b600f840154600d8501546001600160a01b039081169291168461429a565b6040805160808101909152600a830180546001600160a01b0381168352612dea9291906020830190600160a01b900460ff16600181111561140357634e487b7160e01b600052602160045260246000fd5b612df38361388c565b612dfb613413565b6001600160a01b03167f573152bdc3a6b0ce7d310a9875f49776804dd1634202817985b567975731711f8460405161149391815260200190565b6001546001600160a01b0316612e49613413565b6001600160a01b031614612e6f5760405162461bcd60e51b81526004016109a790614ae6565b6040516317b0dca160e31b8152600481018390526001600160a01b03828116602483015284169063bd86e508906044015b600060405180830381600087803b158015612eba57600080fd5b505af1158015612ece573d6000803e3d6000fd5b50505050505050565b6001546001600160a01b0316612eeb613413565b6001600160a01b031614612f115760405162461bcd60e51b81526004016109a790614ae6565b6001600081815260066020908152604080516060810182527f3e5fec24aa4dc4e5aee2e025e51e1392c72a2500577559fae9665c6d52bd6a31548082527f3e5fec24aa4dc4e5aee2e025e51e1392c72a2500577559fae9665c6d52bd6a32546001600160a01b0316938201939093527f3e5fec24aa4dc4e5aee2e025e51e1392c72a2500577559fae9665c6d52bd6a33549181019190915284929115801590612fba5750805142115b612fd65760405162461bcd60e51b81526004016109a7906149d1565b6001600160a01b0383161561301a57826001600160a01b031681602001516001600160a01b03161461301a5760405162461bcd60e51b81526004016109a790614a56565b811561304357818160400151146130435760405162461bcd60e51b81526004016109a790614a27565b6001600160a01b03851661308d5760405162461bcd60e51b81526020600482015260116024820152705450533a205a65726f206164647265737360781b60448201526064016109a7565b600254604080516001600160a01b03928316815291871660208301527f0bc21fe5c3ab742ff1d15b5c4477ffbacf1167e618228078fa625edebe7f331d910160405180910390a1600280546001600160a01b0319166001600160a01b03871617905560066000856004811115610df257634e487b7160e01b600052602160045260246000fd5b61311b614545565b600082815260086020818152604092839020835161014081018552815481526001808301546001600160a01b039081168386015260028401548116838801526003840154606080850191909152600485015460ff9081161515608080870191909152600587015460a087015289518082018b52600688015481526007880154818a015298870154898b015260098701549289019290925260c08501979097528751908101909752600a8401805491821688529296939560e0880195850192600160a01b909204169081111561320057634e487b7160e01b600052602160045260246000fd5b600181111561321f57634e487b7160e01b600052602160045260246000fd5b8152600182015460208083019190915260029092015460409182015291835281518083018352600d8501546001600160a01b039081168252600e86015482840152848301919091528251608081018452600f86015490911681526010850154918101919091526011840154818301526012909301546060840152015292915050565b6132de6040518060a00160405280600081526020016000815260200160006001600160a01b03168152602001600081526020016000151581525090565b50600090815260106020908152604091829020825160a0810184528154815260018201549281019290925260028101546001600160a01b0316928201929092526003820154606082015260049091015460ff161515608082015290565b600061334682614210565b1561335357506001919050565b61335c82613613565b1561336957506000919050565b60405162461bcd60e51b8152602060048201526012602482015271151414ce88155b9adb9bdddb88185cdcd95d60721b60448201526064016109a7565b919050565b6040516001600160a01b03831660248201526044810182905261340e90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526142d8565b505050565b600073d8253782c45a12053594b9deb72d8e8ab2fca54c33141561343e575060131936013560601c90565b503390565b6000818152600860208181526040808420815161014081018352815481526001808301546001600160a01b039081168387015260028401548116838601526003840154606080850191909152600485015460ff9081161515608080870191909152600587015460a087015287518082018952600688015481526007880154818b0152998701548a8901526009870154928a019290925260c08501989098528551908101909552600a84018054918216865288979396949560e08801959094919390850192600160a01b90049091169081111561352f57634e487b7160e01b600052602160045260246000fd5b600181111561354e57634e487b7160e01b600052602160045260246000fd5b8152600182015460208083019190915260029092015460409182015291835281518083018352600d8501546001600160a01b039081168252600e86015482840152848301919091528251608081018452600f8601549091168152601085015481830152601185015481840152601290940154606085015291019190915260c082015181015161010083015190910151919250612710916135ee9190614cdc565b6135f89190614cbc565b8161010001516020015161360c9190614ca4565b9392505050565b6000816001600160a01b03166318160ddd6175306040518263ffffffff1660e01b815260040160206040518083038187803b15801561365157600080fd5b5086fa93505050508015613682575060408051601f3d908101601f1916820190925261367f918101906148b7565b60015b61368e57506000919050565b50600192915050565b6012810154156136e15760405162461bcd60e51b8152602060048201526015602482015274151414ce88141bdcda5d1a5bdb8818db185a5b5959605a1b60448201526064016109a7565b60048101805460ff19169055426012820155613701600e60006003612855565b600f8101546001600160a01b03161561375d578054600f8201546001600160a01b03166000908152600d6020526040902061375d917fa1d6913cd9e08c872be3e7525cca82e4fc0fc298a783f19022be725b19be685a90614140565b50565b60008360200151600181111561378657634e487b7160e01b600052602160045260246000fd5b14156137db576001600160a01b0382163014156137bb576040830151835161340e916001600160a01b039091169083906133ab565b6040830151835161340e916001600160a01b03909116908490849061429a565b60018360200151600181111561380157634e487b7160e01b600052602160045260246000fd5b141561384c5782516060840151604051632142170760e11b81526001600160a01b038581166004830152848116602483015260448201929092529116906342842e0e90606401612ea0565b60405162461bcd60e51b81526020600482015260156024820152745450533a2057726f6e67206173736574207479706560581b60448201526064016109a7565b600081815260086020526040902060028101546001600160a01b0316156138d4576001810154600382015460028301546138d4926001600160a01b03918216929116906133ab565b5050565b600081815260086020526040902060028101546001600160a01b0316156138d4576001810154600382015460028301546138d4926001600160a01b0391821692911690309061429a565b6000612710600354856139359190614cdc565b61393f9190614cbc565b9050600061394d8286614cfb565b90506001600160a01b038416301415613986576001870154600d880154613981916001600160a01b039182169116836133ab565b6139c3565b6001870154600d8801546139a9916001600160a01b03918216918791168461429a565b600d8701546139c3906001600160a01b031685308561429a565b600d8701546139db906001600160a01b0316836143aa565b8287600f0160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055504387600f01600101819055504287600f0160020181905550613b738760405180610140016040529081600082015481526020016001820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016002820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b03168152602001600382015481526020016004820160009054906101000a900460ff1615151515815260200160058201548152602001600682016040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250508152602001600a82016040518060800160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016000820160149054906101000a900460ff1660018111156127ab57634e487b7160e01b600052602160045260246000fd5b6001600160a01b0383166000818152600d6020908152604082208a548154600181810184558386529385200155929091529054613bb09190614cfb565b875460009081527fa1d6913cd9e08c872be3e7525cca82e4fc0fc298a783f19022be725b19be685a60205260409020556006870154613c81576040805160808101909152600a880180546001600160a01b0381168352613c789291906020830190600160a01b900460ff166001811115613c3a57634e487b7160e01b600052602160045260246000fd5b6001811115613c5957634e487b7160e01b600052602160045260246000fd5b8152602001600182015481526020016002820154815250503085613760565b613c8187613697565b8654604080519182526020820188905281018690526001600160a01b038086166060830152841660808201527fb4a7227fb0dfeb98811f5d56165a8829f9656773c1b9dc94821d75c46f42f7639060a00160405180910390a150505050505050565b6001600160a01b03811660009081526011602090815260408083208654845290915290205415613d555760405162461bcd60e51b815260206004820152601e60248201527f5450533a2041756374696f6e2062696420616c7265616479206578697374000060448201526064016109a7565b8260050154821015613d9c5760405162461bcd60e51b815260206004820152601060248201526f151414ce88151bdbc81b1bddc8189a5960821b60448201526064016109a7565b825460009081526012602052604090205415613ee35782546000908152601360205260409020544290613dd3906201518090614ca4565b11613e155760405162461bcd60e51b8152602060048201526012602482015271151414ce88105d58dd1a5bdb88195b99195960721b60448201526064016109a7565b825460009081526012602052604081208054613e3390600190614cfb565b81548110613e5157634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905060006010600083815260200190815260200160002090508360648260030154606e613e899190614cdc565b613e939190614cbc565b10613ee05760405162461bcd60e51b815260206004820181905260248201527f5450533a204e657720626964206c6f776572207468616e2070726576696f757360448201526064016109a7565b50505b6040805160a081018252600f548152845460208083018290526001600160a01b03851683850181905260608401879052600160808501819052600093845260128352858420855181549283018255908552838520909101558754808452858420549184526011835285842090845290915292902091909155613f7c613f66613413565b600d8601546001600160a01b031690308661429a565b835460009081526013602090815260408083204290558351835260108252808320845181559184015160018301558301516002820180546001600160a01b0319166001600160a01b039092169190911790556060830151600382015560808301516004909101805460ff1916911515919091179055600f805491613fff83614d3e565b90915550508354815160408051928352602083019190915281018490526001600160a01b03831660608201527f212de920a843943385be4d0be6f5375802a6c0eb13258959f94184f8599aa1f19060800160405180910390a150505050565b60008052600e6020528051614097906009907fe710864318d4a32f37d6ce54cb3fadbef648dd12d8dbdf53973564d56b7f881c90614140565b60016000908152600e6020908152825160e0840151516001600160a01b03168352600a90915260409091206140ed917fa7c5ba7114a813b50159add3a36832908dc83db71d0b9a24c2ad0f83be95820790614140565b60026000908152600e60209081528251610100840151516001600160a01b03168352600b909152604090912061375d917f9adb202b1492743bc00c81d33cdc6423fa8c79109027eb6a845391e8fc1f0481905b8254600090849061415390600190614cfb565b8154811061417157634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910154848352908590526040808320805483855291842082905592859052600019909255855490925082908690839081106141c757634e487b7160e01b600052603260045260246000fd5b9060005260206000200181905550848054806141f357634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590555050505050565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526000906001600160a01b038316906301ffc9a7906175309060240160206040518083038187803b15801561425d57600080fd5b5086fa9350505050801561428e575060408051601f3d908101601f1916820190925261428b91810190614809565b60015b61094d57506000919050565b6040516001600160a01b03808516602483015283166044820152606481018290526142d29085906323b872dd60e01b906084016133d7565b50505050565b600061432d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166143cd9092919063ffffffff16565b80519091501561340e578080602001905181019061434b9190614809565b61340e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109a7565b806143b3575050565b6002546138d4906001600160a01b038481169116836133ab565b60606143dc84846000856143e4565b949350505050565b6060824710156144455760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109a7565b843b6144935760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109a7565b600080866001600160a01b031685876040516144af9190614974565b60006040518083038185875af1925050503d80600081146144ec576040519150601f19603f3d011682016040523d82523d6000602084013e6144f1565b606091505b509150915061450182828661450c565b979650505050505050565b6060831561451b57508161360c565b82511561452b5782518084602001fd5b8160405162461bcd60e51b81526004016109a7919061499e565b6040518061014001604052806000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600015158152602001600081526020016145ba6040518060800160405280600081526020016000815260200160008152602001600081525090565b81526040805160808101825260008082526020808301829052828401829052606083018290528085019290925282518084018452818152918201529101908152602001614631604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b905290565b80356001600160a01b03811681146133a657600080fd5b60006020828403121561465e578081fd5b61360c82614636565b6000806000806080858703121561467c578283fd5b61468585614636565b935061469360208601614636565b925060408501359150606085013567ffffffffffffffff808211156146b6578283fd5b818701915087601f8301126146c9578283fd5b8135818111156146db576146db614d6f565b604051601f8201601f19908116603f0116810190838211818310171561470357614703614d6f565b816040528281528a602084870101111561471b578586fd5b82602086016020830137918201602001949094529598949750929550505050565b6000806040838503121561474e578182fd5b61475783614636565b946020939093013593505050565b600080600060608486031215614779578283fd5b61478284614636565b92506020840135915061479760408501614636565b90509250925092565b600080600080600080600080610100898b0312156147bc578384fd5b6147c589614636565b975060208901359650604089013595506147e160608a01614636565b979a969950949760808101359660a0820135965060c0820135955060e0909101359350915050565b60006020828403121561481a578081fd5b8151801515811461360c578182fd5b60006020828403121561483a578081fd5b813561360c81614d85565b600080600060608486031215614859578283fd5b833561486481614d85565b925061487260208501614636565b9150604084013590509250925092565b60008060408385031215614894578182fd5b823561475781614d85565b6000602082840312156148b0578081fd5b5035919050565b6000602082840312156148c8578081fd5b5051919050565b600080604083850312156148e1578182fd5b50508035926020909101359150565b6002811061490e57634e487b7160e01b600052602160045260246000fd5b9052565b80516001600160a01b0316825260208082015190614932908401826148f0565b5060408181015190830152606090810151910152565b80516001600160a01b031682526020808201519083015260408082015190830152606090810151910152565b60008251614986818460208701614d12565b9190910192915050565b6020810161094d82846148f0565b60208152600082518060208401526149bd816040850160208701614d12565b601f01601f19169190910160400192915050565b6020808252600e908201526d5450533a2054696d65204c6f636b60901b604082015260600190565b602080825260149082015273151414ce88141bdcda5d1a5bdb8818db1bdcd95960621b604082015260600190565b6020808252601590820152745450533a2057726f6e672075696e742076616c756560581b604082015260600190565b6020808252601890820152775450533a2057726f6e6720616464726573732076616c756560401b604082015260600190565b6020808252600d908201526c151414ce8815dc9bdb99c81251609a1b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252600e908201526d2a28299d102737ba1037bbb732b960911b604082015260600190565b81518152602080830151610280830191614b32908401826001600160a01b03169052565b506040830151614b4d60408401826001600160a01b03169052565b50606083015160608301526080830151614b6b608084018215159052565b5060a083015160a083015260c0830151614ba960c0840182805182526020810151602083015260408101516040830152606081015160608301525050565b5060e0830151614bbd610140840182614912565b5061010083015180516001600160a01b03166101c0840152602001516101e0830152610120830151614bf3610200840182614948565b5092915050565b8a81526001600160a01b038a811660208301528916604082015260608101889052861515608082015260a081018690526102808101614c5d60c0830187805182526020810151602083015260408101516040830152606081015160608301525050565b614c6b610140830186614912565b83516001600160a01b03166101c083015260208401516101e0830152614c95610200830184614948565b9b9a5050505050505050505050565b60008219821115614cb757614cb7614d59565b500190565b600082614cd757634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615614cf657614cf6614d59565b500290565b600082821015614d0d57614d0d614d59565b500390565b60005b83811015614d2d578181015183820152602001614d15565b838111156142d25750506000910152565b6000600019821415614d5257614d52614d59565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6005811061375d57600080fdfea2646970667358221220111f21b9ad4c5156f31d658ebe7827862cab39774a33135d45fcf2a313e693b764736f6c63430008040033000000000000000000000000bbbbb8c4364ec2ce52c59d2ed3e56f307e529a94000000000000000000000000b8ba82f19a9be6cbf6daf9bf4fbcc5bdfcf8bee6000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000bbbbb8c4364ec2ce52c59d2ed3e56f307e529a94
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102ec5760003560e01c80638137884a11610193578063b8f1a962116100e4578063e0a09c6811610092578063e0a09c681461083f578063e5b595aa14610849578063e74b981b1461085c578063eb02c3011461086f578063eb07365f1461088f578063f070ba03146108ea578063ffa1ad741461091157600080fd5b8063b8f1a9621461074b578063c50981a11461075e578063c84d966514610771578063d2ec0025146107f3578063daa09e5414610806578063db006a7514610819578063db2dbb441461082c57600080fd5b806399fbab881161014157806399fbab88146106a35780639c8ae080146106cc578063a126d601146106df578063a271e525146106f2578063a27219e5146106fc578063a93d789f14610725578063b25a8ea31461073857600080fd5b80638137884a1461063957806382bd0b8c14610642578063884399be1461064b5780638da5cb5b146106535780638e24676214610666578063918f86741461069157806398584c0f1461069a57600080fd5b806326232a2e1161024d57806346904840116101fb578063469048401461057c57806352eb916f146105a7578063572b6c05146105ba578063598647f8146105ea5780635a905e10146105fd57806363d5ab8d1461061057806381165ec61461061957600080fd5b806326232a2e14610495578063263e0c1b1461049e578063347d50c5146104c1578063379607f51461051c5780633a5edc541461052f5780633e87290b146105425780634593144c1461055557600080fd5b806314e5f479116102aa57806314e5f4791461039b578063150b7a02146103c45780631abda8e4146103fb5780631c7c565a146104245780631dcea853146104445780632404e26d1461046f578063248a19bb1461048257600080fd5b80624ce3d3146102f1578063032c49ed1461032d5780630580c0321461034d578063106f76351461036057806312e8e2c31461037557806313af403514610388575b600080fd5b61031a6102ff36600461464d565b6001600160a01b03166000908152600c602052604090205490565b6040519081526020015b60405180910390f35b61034061033b36600461464d565b610942565b6040516103249190614990565b61031a61035b36600461473c565b610953565b61037361036e36600461489f565b610984565b005b61037361038336600461489f565b610bdc565b61037361039636600461464d565b610e43565b61031a6103a936600461464d565b6001600160a01b03166000908152600a602052604090205490565b6103e26103d2366004614667565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610324565b61031a61040936600461464d565b6001600160a01b03166000908152600b602052604090205490565b61031a61043236600461489f565b60009081526012602052604090205490565b61031a610452366004614882565b600e60209081526000928352604080842090915290825290205481565b61031a61047d36600461489f565b61107f565b61037361049036600461489f565b61108a565b61031a60035481565b6104b16104ac36600461464d565b61125c565b6040519015158152602001610324565b6104f96104cf366004614829565b60066020526000908152604090208054600182015460029092015490916001600160a01b03169083565b604080519384526001600160a01b03909216602084015290820152606001610324565b61037361052a36600461489f565b611267565b61031a61053d3660046147a0565b6114a5565b61037361055036600461473c565b611cb6565b61031a7f0000000000000000000000000000000000000000000000000000000000501d9a81565b60025461058f906001600160a01b031681565b6040516001600160a01b039091168152602001610324565b61031a6105b536600461473c565b611d4e565b6104b16105c836600461464d565b6001600160a01b031673d8253782c45a12053594b9deb72d8e8ab2fca54c1490565b6103736105f83660046148cf565b611d6a565b61037361060b366004614845565b611ed1565b61031a60075481565b61031a61062736600461489f565b60136020526000908152604090205481565b61031a6101f481565b61031a600f5481565b60095461031a565b60015461058f906001600160a01b031681565b61031a61067436600461473c565b601160209081526000928352604080842090915290825290205481565b61031a61271081565b61031a60045481565b6106b66106b136600461489f565b6120cc565b6040516103249a99989796959493929190614bfa565b6103736106da36600461489f565b61221e565b6103736106ed36600461489f565b612571565b61031a6201518081565b61031a61070a36600461464d565b6001600160a01b03166000908152600d602052604090205490565b61031a61073336600461473c565b6129ad565b61037361074636600461464d565b6129c9565b61031a61075936600461473c565b612bbb565b61031a61076c3660046148cf565b612bd7565b6107bb61077f36600461489f565b60106020526000908152604090208054600182015460028301546003840154600490940154929391926001600160a01b03909116919060ff1685565b6040805195865260208601949094526001600160a01b039092169284019290925260608301919091521515608082015260a001610324565b61031a61080136600461489f565b612bf3565b6104b161081436600461464d565b612c14565b61037361082736600461489f565b612c1f565b60055461058f906001600160a01b031681565b61031a6202a30081565b610373610857366004614765565b612e35565b61037361086a36600461464d565b612ed7565b61088261087d36600461489f565b613113565b6040516103249190614b0e565b6108a261089d36600461489f565b6132a1565b604051610324919081518152602080830151908201526040808301516001600160a01b0316908201526060808301519082015260809182015115159181019190915260a00190565b61031a7f00000000000000000000000000000000000000000000000000000000657716e081565b61093560405180604001604052806005815260200164312e302e3760d81b81525081565b604051610324919061499e565b600061094d8261333b565b92915050565b600c602052816000526040600020818154811061096f57600080fd5b90600052602060002001600091509150505481565b600260005414156109b05760405162461bcd60e51b81526004016109a790614aaf565b60405180910390fd5b600260009081558181526010602052604090208054610a0e5760405162461bcd60e51b815260206004820152601a602482015279151414ce88105d58dd1a5bdb88189a59081b9bdd08199bdd5b9960321b60448201526064016109a7565b60018101546000908152600860209081526040808320805484526013909252822054909142610a406201518084614ca4565b109050600042610a536201518085614ca4565b610a609062127500614ca4565b85546000908152601260205260408120549290911092509015610acb57845460009081526012602052604081208054610a9b90600190614cfb565b81548110610ab957634e487b7160e01b600052603260045260246000fd5b60009182526020909120015488149150505b808015610ad55750825b80610ade575080155b80610aee5750600485015460ff16155b80610af65750815b610b425760405162461bcd60e51b815260206004820152601960248201527f5450533a2041756374696f6e206973206e6f7420656e6465640000000000000060448201526064016109a7565b60028601546001600160a01b0390811660008181526011602090815260408083208a54845290915281205560048801805460ff191690556003880154600d8801549192610b9292169083906133ab565b855460408051918252602082018a90527f6a87dc49655b8e89257f75d88376c42ba5c050bf610a2c3f76148f127947f9c8910160405180910390a150506001600055505050505050565b6001546001600160a01b0316610bf0613413565b6001600160a01b031614610c165760405162461bcd60e51b81526004016109a790614ae6565b6002600081815260066020908152604080516060810182527f8819ef417987f8ae7a81f42cdfb18815282fe989326fbff903d13cf0e03ace29548082527f8819ef417987f8ae7a81f42cdfb18815282fe989326fbff903d13cf0e03ace2a546001600160a01b0316938201939093527f8819ef417987f8ae7a81f42cdfb18815282fe989326fbff903d13cf0e03ace2b5491810191909152849115801590610cbe5750805142115b610cda5760405162461bcd60e51b81526004016109a7906149d1565b6001600160a01b03831615610d1e57826001600160a01b031681602001516001600160a01b031614610d1e5760405162461bcd60e51b81526004016109a790614a56565b8115610d475781816040015114610d475760405162461bcd60e51b81526004016109a790614a27565b6101f4851115610d8d5760405162461bcd60e51b81526020600482015260116024820152705450533a20546f6f20686967682066656560781b60448201526064016109a7565b60035460408051918252602082018790527fc98a8b10b63c929f7799380bb4a0c444c713ebf74d8732f944c915034121aad1910160405180910390a1600385905560066000856004811115610df257634e487b7160e01b600052602160045260246000fd5b6004811115610e1157634e487b7160e01b600052602160045260246000fd5b8152602081019190915260400160009081208181556001810180546001600160a01b0319169055600201555050505050565b6001546001600160a01b0316610e57613413565b6001600160a01b031614610e7d5760405162461bcd60e51b81526004016109a790614ae6565b600080805260066020908152604080516060810182527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8548082527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f9546001600160a01b0316938201939093527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4fa5491810191909152839183919015801590610f265750805142115b610f425760405162461bcd60e51b81526004016109a7906149d1565b6001600160a01b03831615610f8657826001600160a01b031681602001516001600160a01b031614610f865760405162461bcd60e51b81526004016109a790614a56565b8115610faf5781816040015114610faf5760405162461bcd60e51b81526004016109a790614a27565b6001600160a01b038516610ff95760405162461bcd60e51b81526020600482015260116024820152705450533a205a65726f206164647265737360781b60448201526064016109a7565b600154604080516001600160a01b03928316815291871660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180546001600160a01b0319166001600160a01b03871617905560066000856004811115610df257634e487b7160e01b600052602160045260246000fd5b600061094d82613443565b6001546001600160a01b031661109e613413565b6001600160a01b0316146110c45760405162461bcd60e51b81526004016109a790614ae6565b6003600081815260066020908152604080516060810182527f75f96ab15d697e93042dc45b5c896c4b27e89bb6eaf39475c5c371cb2513f7d2548082527f75f96ab15d697e93042dc45b5c896c4b27e89bb6eaf39475c5c371cb2513f7d3546001600160a01b0316938201939093527f75f96ab15d697e93042dc45b5c896c4b27e89bb6eaf39475c5c371cb2513f7d4549181019190915284911580159061116c5750805142115b6111885760405162461bcd60e51b81526004016109a7906149d1565b6001600160a01b038316156111cc57826001600160a01b031681602001516001600160a01b0316146111cc5760405162461bcd60e51b81526004016109a790614a56565b81156111f557818160400151146111f55760405162461bcd60e51b81526004016109a790614a27565b60045460408051918252602082018790527fe8a90a4e7ae8a56c5c24412551b21d6b4557535da5309263e34d818103e15096910160405180910390a18460048190555060066000856004811115610df257634e487b7160e01b600052602160045260246000fd5b600061094d82613613565b6002600054141561128a5760405162461bcd60e51b81526004016109a790614aaf565b60026000908155818152600860205260409020805482146112bd5760405162461bcd60e51b81526004016109a790614a88565b6112c5613413565b600f8201546001600160a01b039081169116146113245760405162461bcd60e51b815260206004820152601a60248201527f5450533a204f6e6c79206c656e6465722063616e20636c61696d00000000000060448201526064016109a7565b6006810154601082015460009161133a91614ca4565b90504381106113855760405162461bcd60e51b81526020600482015260176024820152765450533a20546f6f206561726c7920746f20636c61696d60481b60448201526064016109a7565b600482015460ff166113a95760405162461bcd60e51b81526004016109a7906149f9565b6113b282613697565b6040805160808101909152600a830180546001600160a01b03811683526114489291906020830190600160a01b900460ff16600181111561140357634e487b7160e01b600052602160045260246000fd5b600181111561142257634e487b7160e01b600052602160045260246000fd5b81526020016001820154815260200160028201548152505030611443613413565b613760565b6114518361388c565b611459613413565b6001600160a01b03167ffa6e92366c16d5c789e26dd0b930fddd4e37c6115049c4d123cb73c529362fa98460405161149391815260200190565b60405180910390a25050600160005550565b6000600260005414156114ca5760405162461bcd60e51b81526004016109a790614aaf565b60026000556114dc612710600a614cdc565b83111561152b5760405162461bcd60e51b815260206004820152601a60248201527f5450533a20506f7320666565206162737572646c79206869676800000000000060448201526064016109a7565b83151580611537575082155b61158f5760405162461bcd60e51b815260206004820152602360248201527f5450533a2046656520666f7220696e7374616e74206465616c20666f726269646044820152623232b760e91b60648201526084016109a7565b8715158061159c57508615155b6115dd5760405162461bcd60e51b81526020600482015260126024820152715450533a2057726f6e6720616d6f756e747360701b60448201526064016109a7565b6001600160a01b0389166116265760405162461bcd60e51b815260206004820152601060248201526f2a28299d102d32b9379031aa37b5b2b760811b60448201526064016109a7565b6001600160a01b03861661166f5760405162461bcd60e51b815260206004820152601060248201526f2a28299d102d32b9379030aa37b5b2b760811b60448201526064016109a7565b600061167a8a61333b565b9050600081600181111561169e57634e487b7160e01b600052602160045260246000fd5b1480156116aa57508815155b80156116b4575087155b806116f2575060018160018111156116dc57634e487b7160e01b600052602160045260246000fd5b1480156116e7575088155b80156116f257508715155b61172f5760405162461bcd60e51b815260206004820152600e60248201526d151414ce88125b98dbdc9c9958dd60921b60448201526064016109a7565b611737614545565b60006040518060800160405280888152602001878152602001438152602001428152509050600060405180608001604052808e6001600160a01b0316815260200185600181111561179857634e487b7160e01b600052602160045260246000fd5b815260208082018f905260409182018e9052815180830183526001600160a01b038e1681528082018d90528251608081018452600080825281840181905281850181905260608201528351610140810190945260075484529394509291908101611800613413565b6001600160a01b0390811682526005541660208201526004546040820152600160608201819052608082018b905260a082019690965260c081019490945260e084019290925261010090920191909152805160098054808501825560008290527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0191909155549092506118949190614cfb565b6000808052600e6020908152835182527fe710864318d4a32f37d6ce54cb3fadbef648dd12d8dbdf53973564d56b7f881c81526040808320939093556001600160a01b038e16808352600a8252928220845181546001808201845583865293852001559290915290546119079190614cfb565b60016000818152600e6020908152845182527fa7c5ba7114a813b50159add3a36832908dc83db71d0b9a24c2ad0f83be95820781526040808320949094556001600160a01b038c16808352600b825293822085518154808601835582855292842090920191909155929052905461197e9190614cfb565b60026000908152600e6020908152835182527f9adb202b1492743bc00c81d33cdc6423fa8c79109027eb6a845391e8fc1f048190526040812091909155600c906119c6613413565b6001600160a01b031681526020808201929092526040016000908120835181546001818101845592845293832090930192909255600c90611a05613413565b6001600160a01b03168152602081019190915260400160002054611a299190614cfb565b60036000818152600e6020908152845182527fe0283e559c29e31ee7f56467acc9dd307779c843a883aeeb3bf5c6128c9081448152604080832094909455845182526008808252918490208551815585820151600180830180546001600160a01b03199081166001600160a01b03948516179091558888015160028501805483169185169190911790556060808a015197850197909755608089015160048501805460ff191691151591909117905560a0890151600585015560c08901518051600686015580860151600786015597880151958401959095559590940151600982015560e08601518051600a83018054958616919096169081178655928101518796929591949193909284926001600160a81b03191690911790600160a01b908490811115611b6857634e487b7160e01b600052602160045260246000fd5b021790555060408281015160018301556060928301516002909201919091556101008401518051600d850180546001600160a01b039283166001600160a01b031991821617909155602092830151600e870155610120909601518051600f8701805491909316971696909617905584015160108401558301516011830155919091015160129091015560078054906000611c0183614d3e565b90915550508051611c11906138d8565b611c278160e00151611c21613413565b30613760565b611c2f613413565b8151604080519182526001600160a01b038e811660208401528282018e9052606083018d90528b8116608084015260a083018b905260c083018a905260e0830189905290519216917fb3a36ac05090f711e42b60c13a82d445eeea0e6aa81bb29143354d10f02de515918190036101000190a25160016000559a9950505050505050505050565b6001546001600160a01b0316611cca613413565b6001600160a01b031614611cf05760405162461bcd60e51b81526004016109a790614ae6565b60405163785f6df160e11b8152600481018290526001600160a01b0383169063f0bedbe290602401600060405180830381600087803b158015611d3257600080fd5b505af1158015611d46573d6000803e3d6000fd5b505050505050565b600b602052816000526040600020818154811061096f57600080fd5b60026000541415611d8d5760405162461bcd60e51b81526004016109a790614aaf565b6002600090815582815260086020526040902080548314611dc05760405162461bcd60e51b81526004016109a790614a88565b600481015460ff16611de45760405162461bcd60e51b81526004016109a7906149f9565b600f8101546001600160a01b031615611e3f5760405162461bcd60e51b815260206004820181905260248201527f5450533a2043616e27742062696420657865637574656420706f736974696f6e60448201526064016109a7565b600e81015415611eb557600e8101548214611e945760405162461bcd60e51b8152602060048201526015602482015274151414ce8815dc9bdb99c8189a5908185b5bdd5b9d605a1b60448201526064016109a7565b611eb081600084611ea3613413565b611eab613413565b613922565b611ec7565b611ec78183611ec2613413565b613ce3565b5050600160005550565b6001546001600160a01b0316611ee5613413565b6001600160a01b031614611f0b5760405162461bcd60e51b81526004016109a790614ae6565b60066000846004811115611f2f57634e487b7160e01b600052602160045260246000fd5b6004811115611f4e57634e487b7160e01b600052602160045260246000fd5b815260208101919091526040016000205415611fa55760405162461bcd60e51b8152602060048201526016602482015275151414ce88105b1c9958591e48185b9b9bdd5b98d95960521b60448201526064016109a7565b60405180606001604052806202a30042611fbf9190614ca4565b81526001600160a01b038416602082015260400182905260066000856004811115611ffa57634e487b7160e01b600052602160045260246000fd5b600481111561201957634e487b7160e01b600052602160045260246000fd5b8152602080820192909252604090810160002083518155918301516001830180546001600160a01b0319166001600160a01b0390921691909117905591909101516002909101557f86496aa80f046dc4404f94bce44e24d8e17dc1bb123e8c774ff23ce0e6f0aabe8360048111156120a157634e487b7160e01b600052602160045260246000fd5b604080519182526001600160a01b0385166020830152810183905260600160405180910390a1505050565b600860208181526000928352604092839020805460018083015460028401546003850154600486015460058701548a5160808082018d5260068a0154825260078a0154828c01529a890154818d0152600989015460608201528b519a8b01909b52600a880180546001600160a01b038181168d52989c9689169b9590981699939860ff938416989297909594919391850192600160a01b90049091169081111561218657634e487b7160e01b600052602160045260246000fd5b60018111156121a557634e487b7160e01b600052602160045260246000fd5b8152600182015460208083019190915260029092015460409182015280518082018252600d8501546001600160a01b039081168252600e860154828501528251608081018452600f870154909116815260108601549381019390935260118501549183019190915260129093015460608201529091908a565b600260005414156122415760405162461bcd60e51b81526004016109a790614aaf565b60026000908155818152601360205260409020544290612265906201518090614ca4565b106122ab5760405162461bcd60e51b8152602060048201526016602482015275151414ce88105d58dd1a5bdb881b9bdd08195b99195960521b60448201526064016109a7565b6000818152601260205260409020546122f55760405162461bcd60e51b815260206004820152600c60248201526b5450533a204e6f206269647360a01b60448201526064016109a7565b6000818152601260205260408120805461231190600190614cfb565b8154811061232f57634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910154808352601090915260409091208054919250906123995760405162461bcd60e51b815260206004820152601a602482015279151414ce88105d58dd1a5bdb88189a59081b9bdd08199bdd5b9960321b60448201526064016109a7565b600481015460ff166123df5760405162461bcd60e51b815260206004820152600f60248201526e151414ce88109a590818db1bdcd959608a1b60448201526064016109a7565b828160010154146124235760405162461bcd60e51b815260206004820152600e60248201526d151414ce8815dc9bdb99c8189a5960921b60448201526064016109a7565b6000838152600860205260409020612439613413565b60018201546001600160a01b0390811691161461248c5760405162461bcd60e51b81526020600482015260116024820152702a28299d102737ba103137b93937bbb2b960791b60448201526064016109a7565b600481015460ff166124b05760405162461bcd60e51b81526004016109a7906149f9565b6003820154600e820181905560028301546124da91839186919030906001600160a01b0316613922565b60028201546001600160a01b031660009081526011602090815260408083208454845290915281205560048201805460ff19169055612517613413565b6001600160a01b03167f493e1e7f0e9233f36d4697a11b43b59a1507e08e3c1f920549858785646ac17985846000015460405161255e929190918252602082015260400190565b60405180910390a2505060016000555050565b600260005414156125945760405162461bcd60e51b81526004016109a790614aaf565b60026000908155818152600860205260409020805482146125c75760405162461bcd60e51b81526004016109a790614a88565b6125cf613413565b60018201546001600160a01b0390811691161461263e5760405162461bcd60e51b815260206004820152602760248201527f5450533a204f6e6c7920626f72726f7765722063616e20636c6f73652061207060448201526637b9b4ba34b7b760c91b60648201526084016109a7565b600f8101546001600160a01b0316156126a45760405162461bcd60e51b815260206004820152602260248201527f5450533a2043616e277420636c6f736520657865637574656420706f7369746960448201526137b760f11b60648201526084016109a7565b600481015460ff166126c85760405162461bcd60e51b81526004016109a7906149f9565b6040805161014081018252825481526001808401546001600160a01b0390811660208085019190915260028601548216848601526003860154606080860191909152600487015460ff9081161515608080880191909152600589015460a08801528751808201895260068a0154815260078a01548186015260088a0154818a015260098a01549381019390935260c08701929092528651918201909652600a87018054938416825261284b96889560e08801959394929392850192600160a01b9004909116908111156127ab57634e487b7160e01b600052602160045260246000fd5b60018111156127ca57634e487b7160e01b600052602160045260246000fd5b8152600182015460208083019190915260029092015460409182015291835281518083018352600d8501546001600160a01b039081168252600e86015482840152848301919091528251608081018452600f86015490911681526010850154918101919091526011840154818301526012909301546060840152015261405e565b6128a9600e600060035b600481111561287457634e487b7160e01b600052602160045260246000fd5b815260208082019290925260409081016000908120855460018701546001600160a01b03168352600c90945291902091614140565b6040805160808101909152600a820180546001600160a01b03811683526129459291906020830190600160a01b900460ff1660018111156128fa57634e487b7160e01b600052602160045260246000fd5b600181111561291957634e487b7160e01b600052602160045260246000fd5b8152600182810154602083015260029092015460409091015283015430906001600160a01b0316613760565b61294e8261388c565b60048101805460ff19169055612962613413565b6001600160a01b03167fa9e0cdf27a7965d21573ebb808fbcb2c2a1cfd656e1ecf3f82549437b47406778360405161299c91815260200190565b60405180910390a250506001600055565b600d602052816000526040600020818154811061096f57600080fd5b6001546001600160a01b03166129dd613413565b6001600160a01b031614612a035760405162461bcd60e51b81526004016109a790614ae6565b6004600081815260066020908152604080516060810182527fc5069e24aaadb2addc3e52e868fcf3f4f8acf5a87e24300992fd4540c2a87eed548082527fc5069e24aaadb2addc3e52e868fcf3f4f8acf5a87e24300992fd4540c2a87eee546001600160a01b0316938201939093527fc5069e24aaadb2addc3e52e868fcf3f4f8acf5a87e24300992fd4540c2a87eef549181019190915284929115801590612aac5750805142115b612ac85760405162461bcd60e51b81526004016109a7906149d1565b6001600160a01b03831615612b0c57826001600160a01b031681602001516001600160a01b031614612b0c5760405162461bcd60e51b81526004016109a790614a56565b8115612b355781816040015114612b355760405162461bcd60e51b81526004016109a790614a27565b600554604080516001600160a01b03928316815291871660208301527f709d4a2a735567787a6859678c4b234a262c4355d6d33796ddb4ef59f80c6621910160405180910390a1600580546001600160a01b0319166001600160a01b03871617905560066000856004811115610df257634e487b7160e01b600052602160045260246000fd5b600a602052816000526040600020818154811061096f57600080fd5b6012602052816000526040600020818154811061096f57600080fd5b60098181548110612c0357600080fd5b600091825260209091200154905081565b600061094d82614210565b60026000541415612c425760405162461bcd60e51b81526004016109a790614aaf565b6002600090815581815260086020526040902080548214612c755760405162461bcd60e51b81526004016109a790614a88565b612c7d613413565b60018201546001600160a01b03908116911614612cdc5760405162461bcd60e51b815260206004820152601d60248201527f5450533a204f6e6c7920626f72726f7765722063616e2072656465656d00000060448201526064016109a7565b600f8101546001600160a01b0316612d365760405162461bcd60e51b815260206004820152601a60248201527f5450533a204e6f7420657865637574656420706f736974696f6e00000000000060448201526064016109a7565b600481015460ff16612d5a5760405162461bcd60e51b81526004016109a7906149f9565b612d6381613697565b6000612d6e83613443565b9050612d99612d7b613413565b600f840154600d8501546001600160a01b039081169291168461429a565b6040805160808101909152600a830180546001600160a01b0381168352612dea9291906020830190600160a01b900460ff16600181111561140357634e487b7160e01b600052602160045260246000fd5b612df38361388c565b612dfb613413565b6001600160a01b03167f573152bdc3a6b0ce7d310a9875f49776804dd1634202817985b567975731711f8460405161149391815260200190565b6001546001600160a01b0316612e49613413565b6001600160a01b031614612e6f5760405162461bcd60e51b81526004016109a790614ae6565b6040516317b0dca160e31b8152600481018390526001600160a01b03828116602483015284169063bd86e508906044015b600060405180830381600087803b158015612eba57600080fd5b505af1158015612ece573d6000803e3d6000fd5b50505050505050565b6001546001600160a01b0316612eeb613413565b6001600160a01b031614612f115760405162461bcd60e51b81526004016109a790614ae6565b6001600081815260066020908152604080516060810182527f3e5fec24aa4dc4e5aee2e025e51e1392c72a2500577559fae9665c6d52bd6a31548082527f3e5fec24aa4dc4e5aee2e025e51e1392c72a2500577559fae9665c6d52bd6a32546001600160a01b0316938201939093527f3e5fec24aa4dc4e5aee2e025e51e1392c72a2500577559fae9665c6d52bd6a33549181019190915284929115801590612fba5750805142115b612fd65760405162461bcd60e51b81526004016109a7906149d1565b6001600160a01b0383161561301a57826001600160a01b031681602001516001600160a01b03161461301a5760405162461bcd60e51b81526004016109a790614a56565b811561304357818160400151146130435760405162461bcd60e51b81526004016109a790614a27565b6001600160a01b03851661308d5760405162461bcd60e51b81526020600482015260116024820152705450533a205a65726f206164647265737360781b60448201526064016109a7565b600254604080516001600160a01b03928316815291871660208301527f0bc21fe5c3ab742ff1d15b5c4477ffbacf1167e618228078fa625edebe7f331d910160405180910390a1600280546001600160a01b0319166001600160a01b03871617905560066000856004811115610df257634e487b7160e01b600052602160045260246000fd5b61311b614545565b600082815260086020818152604092839020835161014081018552815481526001808301546001600160a01b039081168386015260028401548116838801526003840154606080850191909152600485015460ff9081161515608080870191909152600587015460a087015289518082018b52600688015481526007880154818a015298870154898b015260098701549289019290925260c08501979097528751908101909752600a8401805491821688529296939560e0880195850192600160a01b909204169081111561320057634e487b7160e01b600052602160045260246000fd5b600181111561321f57634e487b7160e01b600052602160045260246000fd5b8152600182015460208083019190915260029092015460409182015291835281518083018352600d8501546001600160a01b039081168252600e86015482840152848301919091528251608081018452600f86015490911681526010850154918101919091526011840154818301526012909301546060840152015292915050565b6132de6040518060a00160405280600081526020016000815260200160006001600160a01b03168152602001600081526020016000151581525090565b50600090815260106020908152604091829020825160a0810184528154815260018201549281019290925260028101546001600160a01b0316928201929092526003820154606082015260049091015460ff161515608082015290565b600061334682614210565b1561335357506001919050565b61335c82613613565b1561336957506000919050565b60405162461bcd60e51b8152602060048201526012602482015271151414ce88155b9adb9bdddb88185cdcd95d60721b60448201526064016109a7565b919050565b6040516001600160a01b03831660248201526044810182905261340e90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526142d8565b505050565b600073d8253782c45a12053594b9deb72d8e8ab2fca54c33141561343e575060131936013560601c90565b503390565b6000818152600860208181526040808420815161014081018352815481526001808301546001600160a01b039081168387015260028401548116838601526003840154606080850191909152600485015460ff9081161515608080870191909152600587015460a087015287518082018952600688015481526007880154818b0152998701548a8901526009870154928a019290925260c08501989098528551908101909552600a84018054918216865288979396949560e08801959094919390850192600160a01b90049091169081111561352f57634e487b7160e01b600052602160045260246000fd5b600181111561354e57634e487b7160e01b600052602160045260246000fd5b8152600182015460208083019190915260029092015460409182015291835281518083018352600d8501546001600160a01b039081168252600e86015482840152848301919091528251608081018452600f8601549091168152601085015481830152601185015481840152601290940154606085015291019190915260c082015181015161010083015190910151919250612710916135ee9190614cdc565b6135f89190614cbc565b8161010001516020015161360c9190614ca4565b9392505050565b6000816001600160a01b03166318160ddd6175306040518263ffffffff1660e01b815260040160206040518083038187803b15801561365157600080fd5b5086fa93505050508015613682575060408051601f3d908101601f1916820190925261367f918101906148b7565b60015b61368e57506000919050565b50600192915050565b6012810154156136e15760405162461bcd60e51b8152602060048201526015602482015274151414ce88141bdcda5d1a5bdb8818db185a5b5959605a1b60448201526064016109a7565b60048101805460ff19169055426012820155613701600e60006003612855565b600f8101546001600160a01b03161561375d578054600f8201546001600160a01b03166000908152600d6020526040902061375d917fa1d6913cd9e08c872be3e7525cca82e4fc0fc298a783f19022be725b19be685a90614140565b50565b60008360200151600181111561378657634e487b7160e01b600052602160045260246000fd5b14156137db576001600160a01b0382163014156137bb576040830151835161340e916001600160a01b039091169083906133ab565b6040830151835161340e916001600160a01b03909116908490849061429a565b60018360200151600181111561380157634e487b7160e01b600052602160045260246000fd5b141561384c5782516060840151604051632142170760e11b81526001600160a01b038581166004830152848116602483015260448201929092529116906342842e0e90606401612ea0565b60405162461bcd60e51b81526020600482015260156024820152745450533a2057726f6e67206173736574207479706560581b60448201526064016109a7565b600081815260086020526040902060028101546001600160a01b0316156138d4576001810154600382015460028301546138d4926001600160a01b03918216929116906133ab565b5050565b600081815260086020526040902060028101546001600160a01b0316156138d4576001810154600382015460028301546138d4926001600160a01b0391821692911690309061429a565b6000612710600354856139359190614cdc565b61393f9190614cbc565b9050600061394d8286614cfb565b90506001600160a01b038416301415613986576001870154600d880154613981916001600160a01b039182169116836133ab565b6139c3565b6001870154600d8801546139a9916001600160a01b03918216918791168461429a565b600d8701546139c3906001600160a01b031685308561429a565b600d8701546139db906001600160a01b0316836143aa565b8287600f0160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055504387600f01600101819055504287600f0160020181905550613b738760405180610140016040529081600082015481526020016001820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016002820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b03168152602001600382015481526020016004820160009054906101000a900460ff1615151515815260200160058201548152602001600682016040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250508152602001600a82016040518060800160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016000820160149054906101000a900460ff1660018111156127ab57634e487b7160e01b600052602160045260246000fd5b6001600160a01b0383166000818152600d6020908152604082208a548154600181810184558386529385200155929091529054613bb09190614cfb565b875460009081527fa1d6913cd9e08c872be3e7525cca82e4fc0fc298a783f19022be725b19be685a60205260409020556006870154613c81576040805160808101909152600a880180546001600160a01b0381168352613c789291906020830190600160a01b900460ff166001811115613c3a57634e487b7160e01b600052602160045260246000fd5b6001811115613c5957634e487b7160e01b600052602160045260246000fd5b8152602001600182015481526020016002820154815250503085613760565b613c8187613697565b8654604080519182526020820188905281018690526001600160a01b038086166060830152841660808201527fb4a7227fb0dfeb98811f5d56165a8829f9656773c1b9dc94821d75c46f42f7639060a00160405180910390a150505050505050565b6001600160a01b03811660009081526011602090815260408083208654845290915290205415613d555760405162461bcd60e51b815260206004820152601e60248201527f5450533a2041756374696f6e2062696420616c7265616479206578697374000060448201526064016109a7565b8260050154821015613d9c5760405162461bcd60e51b815260206004820152601060248201526f151414ce88151bdbc81b1bddc8189a5960821b60448201526064016109a7565b825460009081526012602052604090205415613ee35782546000908152601360205260409020544290613dd3906201518090614ca4565b11613e155760405162461bcd60e51b8152602060048201526012602482015271151414ce88105d58dd1a5bdb88195b99195960721b60448201526064016109a7565b825460009081526012602052604081208054613e3390600190614cfb565b81548110613e5157634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905060006010600083815260200190815260200160002090508360648260030154606e613e899190614cdc565b613e939190614cbc565b10613ee05760405162461bcd60e51b815260206004820181905260248201527f5450533a204e657720626964206c6f776572207468616e2070726576696f757360448201526064016109a7565b50505b6040805160a081018252600f548152845460208083018290526001600160a01b03851683850181905260608401879052600160808501819052600093845260128352858420855181549283018255908552838520909101558754808452858420549184526011835285842090845290915292902091909155613f7c613f66613413565b600d8601546001600160a01b031690308661429a565b835460009081526013602090815260408083204290558351835260108252808320845181559184015160018301558301516002820180546001600160a01b0319166001600160a01b039092169190911790556060830151600382015560808301516004909101805460ff1916911515919091179055600f805491613fff83614d3e565b90915550508354815160408051928352602083019190915281018490526001600160a01b03831660608201527f212de920a843943385be4d0be6f5375802a6c0eb13258959f94184f8599aa1f19060800160405180910390a150505050565b60008052600e6020528051614097906009907fe710864318d4a32f37d6ce54cb3fadbef648dd12d8dbdf53973564d56b7f881c90614140565b60016000908152600e6020908152825160e0840151516001600160a01b03168352600a90915260409091206140ed917fa7c5ba7114a813b50159add3a36832908dc83db71d0b9a24c2ad0f83be95820790614140565b60026000908152600e60209081528251610100840151516001600160a01b03168352600b909152604090912061375d917f9adb202b1492743bc00c81d33cdc6423fa8c79109027eb6a845391e8fc1f0481905b8254600090849061415390600190614cfb565b8154811061417157634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910154848352908590526040808320805483855291842082905592859052600019909255855490925082908690839081106141c757634e487b7160e01b600052603260045260246000fd5b9060005260206000200181905550848054806141f357634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590555050505050565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526000906001600160a01b038316906301ffc9a7906175309060240160206040518083038187803b15801561425d57600080fd5b5086fa9350505050801561428e575060408051601f3d908101601f1916820190925261428b91810190614809565b60015b61094d57506000919050565b6040516001600160a01b03808516602483015283166044820152606481018290526142d29085906323b872dd60e01b906084016133d7565b50505050565b600061432d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166143cd9092919063ffffffff16565b80519091501561340e578080602001905181019061434b9190614809565b61340e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109a7565b806143b3575050565b6002546138d4906001600160a01b038481169116836133ab565b60606143dc84846000856143e4565b949350505050565b6060824710156144455760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109a7565b843b6144935760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109a7565b600080866001600160a01b031685876040516144af9190614974565b60006040518083038185875af1925050503d80600081146144ec576040519150601f19603f3d011682016040523d82523d6000602084013e6144f1565b606091505b509150915061450182828661450c565b979650505050505050565b6060831561451b57508161360c565b82511561452b5782518084602001fd5b8160405162461bcd60e51b81526004016109a7919061499e565b6040518061014001604052806000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600015158152602001600081526020016145ba6040518060800160405280600081526020016000815260200160008152602001600081525090565b81526040805160808101825260008082526020808301829052828401829052606083018290528085019290925282518084018452818152918201529101908152602001614631604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b905290565b80356001600160a01b03811681146133a657600080fd5b60006020828403121561465e578081fd5b61360c82614636565b6000806000806080858703121561467c578283fd5b61468585614636565b935061469360208601614636565b925060408501359150606085013567ffffffffffffffff808211156146b6578283fd5b818701915087601f8301126146c9578283fd5b8135818111156146db576146db614d6f565b604051601f8201601f19908116603f0116810190838211818310171561470357614703614d6f565b816040528281528a602084870101111561471b578586fd5b82602086016020830137918201602001949094529598949750929550505050565b6000806040838503121561474e578182fd5b61475783614636565b946020939093013593505050565b600080600060608486031215614779578283fd5b61478284614636565b92506020840135915061479760408501614636565b90509250925092565b600080600080600080600080610100898b0312156147bc578384fd5b6147c589614636565b975060208901359650604089013595506147e160608a01614636565b979a969950949760808101359660a0820135965060c0820135955060e0909101359350915050565b60006020828403121561481a578081fd5b8151801515811461360c578182fd5b60006020828403121561483a578081fd5b813561360c81614d85565b600080600060608486031215614859578283fd5b833561486481614d85565b925061487260208501614636565b9150604084013590509250925092565b60008060408385031215614894578182fd5b823561475781614d85565b6000602082840312156148b0578081fd5b5035919050565b6000602082840312156148c8578081fd5b5051919050565b600080604083850312156148e1578182fd5b50508035926020909101359150565b6002811061490e57634e487b7160e01b600052602160045260246000fd5b9052565b80516001600160a01b0316825260208082015190614932908401826148f0565b5060408181015190830152606090810151910152565b80516001600160a01b031682526020808201519083015260408082015190830152606090810151910152565b60008251614986818460208701614d12565b9190910192915050565b6020810161094d82846148f0565b60208152600082518060208401526149bd816040850160208701614d12565b601f01601f19169190910160400192915050565b6020808252600e908201526d5450533a2054696d65204c6f636b60901b604082015260600190565b602080825260149082015273151414ce88141bdcda5d1a5bdb8818db1bdcd95960621b604082015260600190565b6020808252601590820152745450533a2057726f6e672075696e742076616c756560581b604082015260600190565b6020808252601890820152775450533a2057726f6e6720616464726573732076616c756560401b604082015260600190565b6020808252600d908201526c151414ce8815dc9bdb99c81251609a1b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252600e908201526d2a28299d102737ba1037bbb732b960911b604082015260600190565b81518152602080830151610280830191614b32908401826001600160a01b03169052565b506040830151614b4d60408401826001600160a01b03169052565b50606083015160608301526080830151614b6b608084018215159052565b5060a083015160a083015260c0830151614ba960c0840182805182526020810151602083015260408101516040830152606081015160608301525050565b5060e0830151614bbd610140840182614912565b5061010083015180516001600160a01b03166101c0840152602001516101e0830152610120830151614bf3610200840182614948565b5092915050565b8a81526001600160a01b038a811660208301528916604082015260608101889052861515608082015260a081018690526102808101614c5d60c0830187805182526020810151602083015260408101516040830152606081015160608301525050565b614c6b610140830186614912565b83516001600160a01b03166101c083015260208401516101e0830152614c95610200830184614948565b9b9a5050505050505050505050565b60008219821115614cb757614cb7614d59565b500190565b600082614cd757634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615614cf657614cf6614d59565b500290565b600082821015614d0d57614d0d614d59565b500390565b60005b83811015614d2d578181015183820152602001614d15565b838111156142d25750506000910152565b6000600019821415614d5257614d52614d59565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6005811061375d57600080fdfea2646970667358221220111f21b9ad4c5156f31d658ebe7827862cab39774a33135d45fcf2a313e693b764736f6c63430008040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000bbbbb8c4364ec2ce52c59d2ed3e56f307e529a94000000000000000000000000b8ba82f19a9be6cbf6daf9bf4fbcc5bdfcf8bee6000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000bbbbb8c4364ec2ce52c59d2ed3e56f307e529a94
-----Decoded View---------------
Arg [0] : _owner (address): 0xbbbbb8C4364eC2ce52c59D2Ed3E56F307E529a94
Arg [1] : _depositToken (address): 0xb8bA82F19A9Be6CbF6DAF9BF4FBCC5bDfCF8bEe6
Arg [2] : _positionDepositAmount (uint256): 100000000000000000
Arg [3] : _feeRecipient (address): 0xbbbbb8C4364eC2ce52c59D2Ed3E56F307E529a94
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000bbbbb8c4364ec2ce52c59d2ed3e56f307e529a94
Arg [1] : 000000000000000000000000b8ba82f19a9be6cbf6daf9bf4fbcc5bdfcf8bee6
Arg [2] : 000000000000000000000000000000000000000000000000016345785d8a0000
Arg [3] : 000000000000000000000000bbbbb8c4364ec2ce52c59d2ed3e56f307e529a94
Loading...
Loading
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.