Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
AvatarsRental
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 800 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "./modules/Ownable/Ownable.sol";
import "./modules/Upgradeable/Upgradeable.sol";
import "./TransferHelper.sol";
import "./IAvatarsEscrow.sol";
import "./IAvatarsRental.sol";
import "./IAvatars_ERC721.sol";
import "./AvatarsRentalStorage.sol";
contract AvatarsRental is Context, ERC165, IAvatarsRental, Ownable, ReentrancyGuard, Upgradeable {
using SafeCast for uint;
// ======== Admin functions ========
constructor(address _paymentTokenAddress, IAvatarsEscrow _escrow) {
require(_paymentTokenAddress != address(0), "E0"); // E0: addr err
require(_escrow.supportsInterface(type(IAvatarsEscrow).interfaceId),"E0");
AvatarsRentalStorage.layout().paymentTokenAddress = _paymentTokenAddress;
AvatarsRentalStorage.layout().AvatarsEscrow = _escrow;
}
function setPaymentTokenAddress(address _paymentTokenAddress) external onlyOwner checkForUpgrade {
AvatarsRentalStorage.layout().paymentTokenAddress = _paymentTokenAddress;
}
function setAvatarsEscrow(IAvatarsEscrow _escrow) external onlyOwner checkForUpgrade {
AvatarsRentalStorage.layout().AvatarsEscrow = _escrow;
}
// ======== Public functions ========
// Can be used by tenant to initiate rent
// Can be used on a avatar where rental payment has expired
// paymentAlert is the number of seconds before an alert can be rentalPerDay
// payment unit in ether
function rentAvatar(uint _tokenId, uint32 _paymentAlert, uint32 _initialPayment) external nonReentrant checkForUpgrade {
IAvatarsEscrow.AvatarInfo memory avatarInfo_ = AvatarsRentalStorage.layout().AvatarsEscrow.getAvatarInfo(_tokenId);
AvatarRentInfo memory avatarRentInfo_ = AvatarsRentalStorage.layout().avatarRentInfo[_tokenId];
require(avatarInfo_.owner != address(0), "EN"); // EN: Not staked
require(uint(avatarInfo_.rentableUntil) >= block.timestamp + avatarInfo_.minRentDays * 86400, "EC"); // EC: Not available
if (avatarRentInfo_.tenant != address(0)) { // if previously rented
uint paidUntil = rentalPaidUntil(_tokenId);
require(paidUntil < block.timestamp, "EB"); // EB: Ongoing rent
avatarRentInfo_.rentalPaid = 0; // reset payment amount
}
// should pay at least deposit + 1 day of rent
require(uint(_initialPayment) >= uint(avatarInfo_.deposit + avatarInfo_.rentalPerDay), "ED"); // ED: Payment insufficient
// prevent the user from paying too much
// block.timestamp casts it into uint256 which is desired
// if the rentable time left is less than minRentDays then the tenant just has to pay up until the time limit
uint paymentAmount = Math.min((avatarInfo_.rentableUntil - block.timestamp) * avatarInfo_.rentalPerDay / 86400,
uint(_initialPayment));
avatarRentInfo_.tenant = _msgSender();
avatarRentInfo_.rentStartTime = block.timestamp.toUint32();
avatarRentInfo_.rentalPaid += paymentAmount.toUint32();
avatarRentInfo_.paymentAlert = _paymentAlert;
TransferHelper.safeTransferFrom(AvatarsRentalStorage.layout().paymentTokenAddress, _msgSender(), avatarInfo_.owner, paymentAmount * 1e18);
AvatarsRentalStorage.layout().avatarRentInfo[_tokenId] = avatarRentInfo_;
uint count = AvatarsRentalStorage.layout().rentCount[_msgSender()];
AvatarsRentalStorage.layout().rentedAvatars[_msgSender()][count] = _tokenId;
AvatarsRentalStorage.layout().rentedAvatarsIndex[_tokenId] = count;
AvatarsRentalStorage.layout().rentCount[_msgSender()] ++;
emit AvatarRented(_tokenId, _msgSender(), paymentAmount * 1e18);
}
// Used by tenant to pay rent in advance. As soon as the tenant defaults the renter can vacate the tenant
// The rental period can be extended as long as rent is prepaid, up to rentableUntil timestamp.
// payment unit in ether
function payRent(uint _tokenId, uint32 _payment) external nonReentrant checkForUpgrade {
IAvatarsEscrow.AvatarInfo memory avatarInfo_ = AvatarsRentalStorage.layout().AvatarsEscrow.getAvatarInfo(_tokenId);
AvatarRentInfo memory avatarRentInfo_ = AvatarsRentalStorage.layout().avatarRentInfo[_tokenId];
require(avatarRentInfo_.tenant == _msgSender(), "EE"); // EE: Not rented
// prevent the user from paying too much
uint paymentAmount = Math.min(uint(avatarInfo_.rentableUntil - avatarRentInfo_.rentStartTime) * avatarInfo_.rentalPerDay / 86400
- avatarRentInfo_.rentalPaid,
uint(_payment));
avatarRentInfo_.rentalPaid += paymentAmount.toUint32();
TransferHelper.safeTransferFrom(AvatarsRentalStorage.layout().paymentTokenAddress, _msgSender(), avatarInfo_.owner, paymentAmount * 1e18);
AvatarsRentalStorage.layout().avatarRentInfo[_tokenId] = avatarRentInfo_;
emit RentalPaid(_tokenId, _msgSender(), paymentAmount * 1e18);
}
// Used by renter to vacate tenant in case of default, or when rental period expires.
// If payment + deposit covers minRentDays then deposit can be used as rent. Otherwise rent has to be provided in addition to the deposit.
// If rental period is shorter than minRentDays then deposit will be forfeited.
function terminateRental(uint _tokenId) external checkForUpgrade {
require(AvatarsRentalStorage.layout().AvatarsEscrow.getAvatarInfo(_tokenId).owner == _msgSender(), "E9"); // E9: Not your avatar
uint paidUntil = rentalPaidUntil(_tokenId);
require(paidUntil < block.timestamp, "EB"); // EB: Ongoing rent
address tenant = AvatarsRentalStorage.layout().avatarRentInfo[_tokenId].tenant;
emit RentalTerminated(_tokenId, tenant);
AvatarsRentalStorage.layout().rentCount[tenant]--;
uint lastIndex = AvatarsRentalStorage.layout().rentCount[tenant];
uint tokenIndex = AvatarsRentalStorage.layout().rentedAvatarsIndex[_tokenId];
// swap and purge if not the last one
if (tokenIndex != lastIndex) {
uint lastTokenId = AvatarsRentalStorage.layout().rentedAvatars[tenant][lastIndex];
AvatarsRentalStorage.layout().rentedAvatars[tenant][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
AvatarsRentalStorage.layout().rentedAvatarsIndex[lastTokenId] = tokenIndex;
}
delete AvatarsRentalStorage.layout().rentedAvatarsIndex[_tokenId];
delete AvatarsRentalStorage.layout().rentedAvatars[tenant][tokenIndex];
AvatarsRentalStorage.layout().avatarRentInfo[_tokenId] = AvatarRentInfo(address(0),0,0,0);
}
// ======== View only functions ========
function isRentActive(uint _tokenId) public view override returns(bool) {
return AvatarsRentalStorage.layout().avatarRentInfo[_tokenId].tenant != address(0);
}
function getTenant(uint _tokenId) public view override returns(address) {
return AvatarsRentalStorage.layout().avatarRentInfo[_tokenId].tenant;
}
function rentedByIndex(address _tenant, uint _index) public view returns(uint) {
require(_index < AvatarsRentalStorage.layout().rentCount[_tenant], "EI"); // EI: index out of bounds
return AvatarsRentalStorage.layout().rentedAvatars[_tenant][_index];
}
function isRentable(uint _tokenId) external view returns(bool state) {
IAvatarsEscrow.AvatarInfo memory avatarInfo_ = AvatarsRentalStorage.layout().AvatarsEscrow.getAvatarInfo(_tokenId);
AvatarRentInfo memory avatarRentInfo_ = AvatarsRentalStorage.layout().avatarRentInfo[_tokenId];
state = (avatarInfo_.owner != address(0)) &&
(uint(avatarInfo_.rentableUntil) >= block.timestamp + avatarInfo_.minRentDays * 86400);
if (avatarRentInfo_.tenant != address(0)) { // if previously rented
uint paidUntil = rentalPaidUntil(_tokenId);
state = state && (paidUntil < block.timestamp);
}
}
function rentalPaidUntil(uint _tokenId) public view returns(uint paidUntil) {
IAvatarsEscrow.AvatarInfo memory avatarInfo_ = AvatarsRentalStorage.layout().AvatarsEscrow.getAvatarInfo(_tokenId);
AvatarRentInfo memory avatarRentInfo_ = AvatarsRentalStorage.layout().avatarRentInfo[_tokenId];
if (avatarInfo_.rentalPerDay == 0) {
paidUntil = avatarInfo_.rentableUntil;
}
else {
uint rentalPaidSeconds = uint(avatarRentInfo_.rentalPaid) * 86400 / avatarInfo_.rentalPerDay;
bool fundExceedsMin = rentalPaidSeconds >= Math.max(avatarInfo_.minRentDays * 86400, block.timestamp - avatarRentInfo_.rentStartTime);
paidUntil = uint(avatarRentInfo_.rentStartTime) + rentalPaidSeconds
- (fundExceedsMin ? 0 : uint(avatarInfo_.deposit) * 86400 / avatarInfo_.rentalPerDay);
}
}
function supportsInterface(bytes4 interfaceId) public view override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IAvatarsRental).interfaceId || super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// 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
// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128) {
require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
return int128(value);
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64) {
require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
return int64(value);
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32) {
require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
return int32(value);
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16) {
require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
return int16(value);
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8) {
require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
return int8(value);
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a / b + (a % b == 0 ? 0 : 1);
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/utils/Context.sol";
import "./OwnableStorage.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return OwnableStorage.layout().owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = OwnableStorage.layout().owner;
OwnableStorage.layout().owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
import "../Ownable/Ownable.sol";
import "./UpgradeableStorage.sol";
contract Upgradeable is Ownable {
function setUpgrade(bytes4 _sig, address _target) external onlyOwner {
UpgradeableStorage.layout().upgrades[_sig] = _target;
}
function hasUpgrade(bytes4 _sig) private view returns (bool) {
return UpgradeableStorage.layout().upgrades[_sig] != address(0);
}
function executeUpgrade(bytes4 _sig) private returns (bool) {
address target = UpgradeableStorage.layout().upgrades[_sig];
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), target, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {revert(0, returndatasize())}
default {return (0, returndatasize())}
}
}
modifier checkForUpgrade() {
if (hasUpgrade(msg.sig)) {
executeUpgrade(msg.sig);
} else {
_;
}
}
fallback() external payable {
require(hasUpgrade(msg.sig));
executeUpgrade(msg.sig);
}
receive() external payable {}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
/**
helper methods for interacting with ERC20 tokens that do not consistently return true/false
with the addition of a transfer function to send eth or an erc20 token
*/
library TransferHelper {
function safeTransfer(address _token, address _to, uint _value) internal {
(bool success, bytes memory data) = _token.call(abi.encodeWithSelector(0xa9059cbb, _to, _value));
require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper: TRANSFER_FAILED");
}
function safeTransferFrom(address _token, address _from, address _to, uint _value) internal {
(bool success, bytes memory data) = _token.call(abi.encodeWithSelector(0x23b872dd, _from, _to, _value));
require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper: TRANSFER_FROM_FAILED");
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
interface IAvatarsEscrow is IERC165, IERC721Receiver {
event WeightUpdated(address indexed user, bool increase, uint weight, uint timestamp);
event AvatarStaked(uint256 indexed tokenId, address indexed user);
event AvatarUnstaked(uint256 indexed tokenId, address indexed user);
event RewardsSet(uint32 start, uint32 end, uint256 rate);
event RewardsUpdated(uint32 start, uint32 end, uint256 rate);
event RewardsPerWeightUpdated(uint256 accumulated);
event UserRewardsUpdated(address user, uint256 userRewards, uint256 paidRewardPerWeight);
event RewardClaimed(address receiver, uint256 claimed);
struct AvatarInfo {
uint16 weight; // weight based on rarity
address owner; // staked to, otherwise owner == 0
uint16 deposit; // unit is ether, paid in WRLD. The deposit is deducted from the last payment(s) since the deposit is non-custodial
uint16 rentalPerDay; // unit is ether, paid in WRLD. Total is deposit + rentalPerDay * days
uint16 minRentDays; // must rent for at least min rent days, otherwise deposit is forfeited up to this amount
uint32 rentableUntil; // timestamp in unix epoch
}
struct RewardsPeriod {
uint32 start; // reward start time, in unix epoch
uint32 end; // reward end time, in unix epoch
}
struct RewardsPerWeight {
uint32 totalWeight;
uint96 accumulated;
uint32 lastUpdated;
uint96 rate;
}
struct UserRewards {
uint32 stakedWeight;
uint96 accumulated;
uint96 checkpoint;
}
// view functions
function getAvatarInfo(uint _tokenId) external view returns(AvatarInfo memory);
function checkUserRewards(address _user) external view returns(uint);
function rewardsPeriod() external view returns (IAvatarsEscrow.RewardsPeriod memory);
function rewardsPerWeight() external view returns(RewardsPerWeight memory);
function rewards(address _user) external view returns (UserRewards memory);
function userStakedAvatars(address _user) external view returns (uint256[] memory);
function onERC721Received(address, address, uint256, bytes calldata) external view override returns(bytes4);
// public functions
function initialStake(
uint[] calldata _tokenIds,
uint[] calldata _weights,
address _stakeTo,
uint16 _deposit,
uint16 _rentalPerDay,
uint16 _minRentDays,
uint32 _rentableUntil,
uint32 _maxTimestamp,
bytes calldata _signature
) external;
function stake(
uint[] calldata _tokenIds,
address _stakeTo,
uint16 _deposit,
uint16 _rentalPerDay,
uint16 _minRentDays,
uint32 _rentableUntil
) external;
function updateRent(
uint[] calldata _tokenIds,
uint16 _deposit,
uint16 _rentalPerDay,
uint16 _minRentDays,
uint32 _rentableUntil
) external;
function extendRentalPeriod(uint _tokenId, uint32 _rentableUntil) external;
function unstake(uint[] calldata _tokenIds, address unstakeTo) external;
function claim(address _to) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
interface IAvatarsRental is IERC165 {
event AvatarRented(uint256 indexed tokenId, address indexed tenant, uint256 payment);
event RentalPaid(uint256 indexed tokenId, address indexed tenant, uint256 payment);
event RentalTerminated(uint256 indexed tokenId, address indexed tenant);
struct AvatarRentInfo {
address tenant; // rented to, otherwise tenant == 0
uint32 rentStartTime; // timestamp in unix epoch
uint32 rentalPaid; // total rental paid since the beginning including the deposit
uint32 paymentAlert; // alert time before next rent payment in seconds (used by frontend only)
}
function isRentActive(uint _tokenId) external view returns(bool);
function getTenant(uint _tokenId) external view returns(address);
function rentedByIndex(address _tenant, uint _index) external view returns(uint);
function isRentable(uint _tokenId) external view returns(bool state);
function rentalPaidUntil(uint _tokenId) external view returns(uint paidUntil);
function rentAvatar(uint _tokenId, uint32 _paymentAlert, uint32 initialPayment) external;
function payRent(uint _tokenId, uint32 _payment) external;
function terminateRental(uint _tokenId) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
interface IAvatars_ERC721 is IERC721 {
function updateAvatar(
uint _tokenId,
string calldata _ipfsHash,
uint256 _nonce,
bytes calldata _updateApproverSignature
) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
import "./IAvatarsEscrow.sol";
import "./IAvatarsRental.sol";
library AvatarsRentalStorage {
bytes32 private constant STORAGE_SLOT = keccak256("slot.avatars.rental");
struct Layout {
address paymentTokenAddress;
IAvatarsEscrow AvatarsEscrow;
IAvatarsRental.AvatarRentInfo[10001] avatarRentInfo; // Avatars tokenId is in N [1,10000]
mapping (address => uint) rentCount; // count of rented avatars per tenant
mapping (address => mapping(uint => uint)) rentedAvatars; // enumerate rented avatars per tenant
mapping (uint => uint) rentedAvatarsIndex; // tokenId to index in _rentedAvatars[tenant]
}
function layout() internal pure returns (Layout storage _layout) {
bytes32 slot = STORAGE_SLOT;
assembly {
_layout.slot := slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
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.18;
library OwnableStorage {
bytes32 private constant STORAGE_SLOT = keccak256("gg.topia.worlds.Ownable");
struct Layout {
address owner;
}
function layout() internal pure returns (Layout storage _layout) {
bytes32 slot = STORAGE_SLOT;
assembly {
_layout.slot := slot
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
library UpgradeableStorage {
bytes32 private constant STORAGE_SLOT = keccak256("gg.topia.worlds.Upgradeable");
struct Layout {
mapping(bytes4 => address) upgrades;
}
function layout() internal pure returns (Layout storage _layout) {
bytes32 slot = STORAGE_SLOT;
assembly {
_layout.slot := slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)
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
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/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;
}{
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"hardhat/=node_modules/hardhat/",
"@create3-factory/=lib/create3-factory/src/",
"src/=src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 800
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_paymentTokenAddress","type":"address"},{"internalType":"contract IAvatarsEscrow","name":"_escrow","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tenant","type":"address"},{"indexed":false,"internalType":"uint256","name":"payment","type":"uint256"}],"name":"AvatarRented","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tenant","type":"address"},{"indexed":false,"internalType":"uint256","name":"payment","type":"uint256"}],"name":"RentalPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tenant","type":"address"}],"name":"RentalTerminated","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getTenant","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"isRentActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"isRentable","outputs":[{"internalType":"bool","name":"state","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint32","name":"_payment","type":"uint32"}],"name":"payRent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint32","name":"_paymentAlert","type":"uint32"},{"internalType":"uint32","name":"_initialPayment","type":"uint32"}],"name":"rentAvatar","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"rentalPaidUntil","outputs":[{"internalType":"uint256","name":"paidUntil","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tenant","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"rentedByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IAvatarsEscrow","name":"_escrow","type":"address"}],"name":"setAvatarsEscrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_paymentTokenAddress","type":"address"}],"name":"setPaymentTokenAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_sig","type":"bytes4"},{"internalType":"address","name":"_target","type":"address"}],"name":"setUpgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"terminateRental","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60806040523480156200001157600080fd5b506040516200221538038062002215833981016040819052620000349162000290565b6200003f33620001a7565b60016000556001600160a01b038216620000855760405162461bcd60e51b8152602060048201526002602482015261045360f41b60448201526064015b60405180910390fd5b6040516301ffc9a760e01b8152633141c18f60e01b60048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa158015620000d1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000f79190620002cf565b6200012a5760405162461bcd60e51b8152602060048201526002602482015261045360f41b60448201526064016200007c565b81620001406200022f60201b620017cb1760201c565b60000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806200017d6200022f60201b620017cb1760201c565b60010180546001600160a01b0319166001600160a01b039290921691909117905550620002fa9050565b6000620001be6200025360201b620017dd1760201c565b546001600160a01b0316905081620001e162000253602090811b620017dd17901c565b80546001600160a01b0319166001600160a01b03928316179055604051838216918316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddb31890565b7f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc690565b6001600160a01b03811681146200028d57600080fd5b50565b60008060408385031215620002a457600080fd5b8251620002b18162000277565b6020840151909250620002c48162000277565b809150509250929050565b600060208284031215620002e257600080fd5b81518015158114620002f357600080fd5b9392505050565b611f0b806200030a6000396000f3fe6080604052600436106100ec5760003560e01c80638da5cb5b1161008a578063dcb98f7e11610059578063dcb98f7e14610302578063ea447eb314610322578063f2fde38b14610342578063f921741914610362576100f3565b80638da5cb5b14610265578063b326f59a146102a2578063c392598d146102c2578063d043a006146102e2576100f3565b806366734526116100c657806366734526146101f0578063683b22ec14610210578063715018a61461023057806381d8787414610245576100f3565b806301ffc9a71461015557806355fd83e51461018a5780635dac9bb9146101c2576100f3565b366100f357005b600080356001600160e01b03191681527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260409020546001600160a01b031661013e57600080fd5b6101536000356001600160e01b031916610382565b005b34801561016157600080fd5b50610175610170366004611aef565b6103e7565b60405190151581526020015b60405180910390f35b34801561019657600080fd5b506101aa6101a5366004611b0a565b61041e565b6040516001600160a01b039091168152602001610181565b3480156101ce57600080fd5b506101e26101dd366004611b38565b610452565b604051908152602001610181565b3480156101fc57600080fd5b5061017561020b366004611b0a565b61050a565b34801561021c57600080fd5b5061015361022b366004611b64565b610541565b34801561023c57600080fd5b506101536105a2565b34801561025157600080fd5b50610153610260366004611b9b565b6105b6565b34801561027157600080fd5b507f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc6546001600160a01b03166101aa565b3480156102ae57600080fd5b506101536102bd366004611bca565b61065c565b3480156102ce57600080fd5b506101756102dd366004611b0a565b610a06565b3480156102ee57600080fd5b506101e26102fd366004611b0a565b610b79565b34801561030e57600080fd5b5061015361031d366004611b9b565b610d62565b34801561032e57600080fd5b5061015361033d366004611bef565b610df5565b34801561034e57600080fd5b5061015361035d366004611b9b565b611327565b34801561036e57600080fd5b5061015361037d366004611b0a565b6113b4565b6001600160e01b0319811660009081527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260408120546001600160a01b031636828037600080366000845af43d6000803e8080156103e2573d6000f35b3d6000fd5b60006001600160e01b0319821663ddb05bc160e01b148061041857506301ffc9a760e01b6001600160e01b03198316145b92915050565b6000600080516020611eb683398151915282612711811061044157610441611c31565b01546001600160a01b031692915050565b6001600160a01b03821660009081527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2b602052604081205482106104c25760405162461bcd60e51b8152602060048201526002602482015261454960f01b60448201526064015b60405180910390fd5b506001600160a01b039190911660009081527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2c60209081526040808320938352929052205490565b600080600080516020611eb683398151915283612711811061052e5761052e611c31565b01546001600160a01b0316141592915050565b610549611801565b6001600160e01b03199190911660009081527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d6020526040902080546001600160a01b0319166001600160a01b03909216919091179055565b6105aa611801565b6105b46000611889565b565b6105be611801565b600080356001600160e01b03191681527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260409020546001600160a01b03161561061e5761061a6000356001600160e01b031916610382565b5050565b7f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddb31980546001600160a01b0319166001600160a01b0383161790555b50565b6002600054036106ae5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016104b9565b600260009081556001600160e01b031981351681527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260409020546001600160a01b0316156107155761070f6000356001600160e01b031916610382565b506109fd565b6000600080516020611e96833981519152600101546040516310ea4bc960e21b8152600481018590526001600160a01b03909116906343a92f249060240160c060405180830381865afa158015610770573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107949190611c6f565b90506000600080516020611eb68339815191528461271181106107b9576107b9611c31565b6040805160808101825292909101546001600160a01b038116835263ffffffff600160a01b820481166020850152600160c01b8204811692840192909252600160e01b9004166060820152905061080d3390565b6001600160a01b031681600001516001600160a01b0316146108565760405162461bcd60e51b8152602060048201526002602482015261454560f01b60448201526064016104b9565b60006108b7826040015163ffffffff1662015180856060015161ffff1685602001518760a001516108879190611d32565b63ffffffff166108979190611d56565b6108a19190611d6d565b6108ab9190611d8f565b8563ffffffff166118fa565b90506108c281611912565b826040018181516108d39190611da2565b63ffffffff16905250610916600080516020611e968339815191525b546001600160a01b031633602086015161091185670de0b6b3a7640000611d56565b611992565b81600080516020611eb683398151915286612711811061093857610938611c31565b825191018054602084015160408501516060909501516001600160a01b039094166001600160c01b031990921691909117600160a01b63ffffffff92831602176001600160c01b0316600160c01b948216949094026001600160e01b031693909317600160e01b9390921692909202179055336001600160a01b0316857f4d7281212f84ddb5b45fa8c98cceaca247d2a9ca33497d7feb95df1d3d047b086109e884670de0b6b3a7640000611d56565b60405190815260200160405180910390a35050505b50506001600055565b600080600080516020611e96833981519152600101546040516310ea4bc960e21b8152600481018590526001600160a01b03909116906343a92f249060240160c060405180830381865afa158015610a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a869190611c6f565b90506000600080516020611eb6833981519152846127118110610aab57610aab611c31565b6040805160808101825292909101546001600160a01b03808216845263ffffffff600160a01b83048116602080870191909152600160c01b8404821694860194909452600160e01b9092049091166060840152908401519192501615801590610b4257506080820151610b259061ffff1662015180611dbf565b610b349062ffffff1642611de6565b8260a0015163ffffffff1610155b81519093506001600160a01b031615610b72576000610b6085610b79565b9050838015610b6e57504281105b9350505b5050919050565b600080600080516020611e96833981519152600101546040516310ea4bc960e21b8152600481018590526001600160a01b03909116906343a92f249060240160c060405180830381865afa158015610bd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf99190611c6f565b90506000600080516020611eb6833981519152846127118110610c1e57610c1e611c31565b6040805160808101825292909101546001600160a01b038116835263ffffffff600160a01b820481166020850152600160c01b8204811692840192909252600160e01b90041660608083019190915283015190915061ffff16600003610c90578160a0015163ffffffff169250610b72565b6000826060015161ffff16826040015163ffffffff1662015180610cb49190611d56565b610cbe9190611d6d565b90506000610cfc846080015161ffff1662015180610cdc9190611dbf565b62ffffff16846020015163ffffffff1642610cf79190611d8f565b611ac2565b821015905080610d3557836060015161ffff16846040015161ffff1662015180610d269190611d56565b610d309190611d6d565b610d38565b60005b82846020015163ffffffff16610d4e9190611de6565b610d589190611d8f565b9695505050505050565b610d6a611801565b600080356001600160e01b03191681527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260409020546001600160a01b031615610dc65761061a6000356001600160e01b031916610382565b600080516020611e9683398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b600260005403610e475760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016104b9565b600260009081556001600160e01b031981351681527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260409020546001600160a01b031615610eae57610ea86000356001600160e01b031916610382565b5061131d565b6000600080516020611e96833981519152600101546040516310ea4bc960e21b8152600481018690526001600160a01b03909116906343a92f249060240160c060405180830381865afa158015610f09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2d9190611c6f565b90506000600080516020611eb6833981519152856127118110610f5257610f52611c31565b6040805160808101825292909101546001600160a01b03808216845263ffffffff600160a01b83048116602080870191909152600160c01b8404821694860194909452600160e01b90920490911660608401529084015191925016610fde5760405162461bcd60e51b815260206004820152600260248201526122a760f11b60448201526064016104b9565b6080820151610ff49061ffff1662015180611dbf565b6110039062ffffff1642611de6565b8260a0015163ffffffff1610156110415760405162461bcd60e51b8152602060048201526002602482015261454360f01b60448201526064016104b9565b80516001600160a01b03161561109b57600061105c86610b79565b90504281106110925760405162461bcd60e51b815260206004820152600260248201526122a160f11b60448201526064016104b9565b50600060408201525b816060015182604001516110af9190611df9565b61ffff168363ffffffff1610156110ed5760405162461bcd60e51b8152602060048201526002602482015261115160f21b60448201526064016104b9565b600061112962015180846060015161ffff16428660a0015163ffffffff166111159190611d8f565b61111f9190611d56565b6108ab9190611d6d565b338352905061113742611912565b63ffffffff16602083015261114b81611912565b8260400181815161115c9190611da2565b63ffffffff9081169091528616606084015250611186600080516020611e968339815191526108ef565b81600080516020611eb68339815191528761271181106111a8576111a8611c31565b8251910180546020808501516040808701516060909701516001600160a01b039096166001600160c01b031990941693909317600160a01b63ffffffff92831602176001600160c01b0316600160c01b968216969096026001600160e01b031695909517600160e01b95909416949094029290921790553360008181527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2b80855283822080547f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2c875285842081855287528584208d90558c84527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2d8752948320859055928252909352805491926112be83611e14565b91905055506112ca3390565b6001600160a01b0316877f353d96187ca8d55ed63c9c367b64e020ee11741e4a2532c04cbb1a211745c85961130785670de0b6b3a7640000611d56565b60405190815260200160405180910390a3505050505b5050600160005550565b61132f611801565b6001600160a01b0381166113ab5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016104b9565b61065981611889565b600080356001600160e01b03191681527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260409020546001600160a01b0316156114105761061a6000356001600160e01b031916610382565b336001600160a01b0316600080516020611e96833981519152600101546040516310ea4bc960e21b8152600481018490526001600160a01b03909116906343a92f249060240160c060405180830381865afa158015611473573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114979190611c6f565b602001516001600160a01b0316146114d65760405162461bcd60e51b8152602060048201526002602482015261453960f01b60448201526064016104b9565b60006114e182610b79565b90504281106115175760405162461bcd60e51b815260206004820152600260248201526122a160f11b60448201526064016104b9565b6000600080516020611eb683398151915283612711811061153a5761153a611c31565b01546040516001600160a01b039091169150819084907ff067387f7b23926de806389f49810aeacc5e1ce8c46e12eb17d20037dd0cfb9b90600090a36001600160a01b03811660009081527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2b602052604081208054916115b983611e2d565b919050555060006115d5600080516020611e9683398151915290565b6001600160a01b03831660009081526127139190910160209081526040808320548784527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2d909252909120549091508082146116a3576001600160a01b03831660009081527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2c6020908152604080832085845282528083205484845281842081905583527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2d90915290208190555b60008581527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2d602090815260408083208390556001600160a01b03861683527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2c82528083208484528252808320839055805160808101825283815291820183905281018290526060810191909152600080516020611eb683398151915286612711811061175257611752611c31565b825191018054602084015160408501516060909501516001600160a01b039094166001600160c01b031990921691909117600160a01b63ffffffff92831602176001600160c01b0316600160c01b948216949094026001600160e01b031693909317600160e01b93909216929092021790555050505050565b600080516020611e9683398151915290565b7f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc690565b336118337f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc6546001600160a01b031690565b6001600160a01b0316146105b45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104b9565b7f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000818310611909578161190b565b825b9392505050565b600063ffffffff82111561198e5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201527f322062697473000000000000000000000000000000000000000000000000000060648201526084016104b9565b5090565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916119f69190611e44565b6000604051808303816000865af19150503d8060008114611a33576040519150601f19603f3d011682016040523d82523d6000602084013e611a38565b606091505b5091509150818015611a62575080511580611a62575080806020019051810190611a629190611e73565b611aba5760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b60648201526084016104b9565b505050505050565b600081831015611909578161190b565b80356001600160e01b031981168114611aea57600080fd5b919050565b600060208284031215611b0157600080fd5b61190b82611ad2565b600060208284031215611b1c57600080fd5b5035919050565b6001600160a01b038116811461065957600080fd5b60008060408385031215611b4b57600080fd5b8235611b5681611b23565b946020939093013593505050565b60008060408385031215611b7757600080fd5b611b8083611ad2565b91506020830135611b9081611b23565b809150509250929050565b600060208284031215611bad57600080fd5b813561190b81611b23565b63ffffffff8116811461065957600080fd5b60008060408385031215611bdd57600080fd5b823591506020830135611b9081611bb8565b600080600060608486031215611c0457600080fd5b833592506020840135611c1681611bb8565b91506040840135611c2681611bb8565b809150509250925092565b634e487b7160e01b600052603260045260246000fd5b805161ffff81168114611aea57600080fd5b8051611aea81611b23565b8051611aea81611bb8565b600060c08284031215611c8157600080fd5b60405160c0810181811067ffffffffffffffff82111715611cb257634e487b7160e01b600052604160045260246000fd5b604052611cbe83611c47565b8152611ccc60208401611c59565b6020820152611cdd60408401611c47565b6040820152611cee60608401611c47565b6060820152611cff60808401611c47565b6080820152611d1060a08401611c64565b60a08201529392505050565b634e487b7160e01b600052601160045260246000fd5b63ffffffff828116828216039080821115611d4f57611d4f611d1c565b5092915050565b808202811582820484141761041857610418611d1c565b600082611d8a57634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111561041857610418611d1c565b63ffffffff818116838216019080821115611d4f57611d4f611d1c565b62ffffff818116838216028082169190828114611dde57611dde611d1c565b505092915050565b8082018082111561041857610418611d1c565b61ffff818116838216019080821115611d4f57611d4f611d1c565b600060018201611e2657611e26611d1c565b5060010190565b600081611e3c57611e3c611d1c565b506000190190565b6000825160005b81811015611e655760208186018101518583015201611e4b565b506000920191825250919050565b600060208284031215611e8557600080fd5b8151801515811461190b57600080fdfe90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddb31890efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddb31aa2646970667358221220d22c3f2b34d4cd7ca5f844a106be4e3e02191b9cee6f1e88b4e3695935b8fb8b64736f6c63430008120033000000000000000000000000ccccb68e1a848cbdb5b60a974e07aae143ed40c3000000000000000000000000f0e2c83bd68ae79900ab9892ac77c9311b278117
Deployed Bytecode
0x6080604052600436106100ec5760003560e01c80638da5cb5b1161008a578063dcb98f7e11610059578063dcb98f7e14610302578063ea447eb314610322578063f2fde38b14610342578063f921741914610362576100f3565b80638da5cb5b14610265578063b326f59a146102a2578063c392598d146102c2578063d043a006146102e2576100f3565b806366734526116100c657806366734526146101f0578063683b22ec14610210578063715018a61461023057806381d8787414610245576100f3565b806301ffc9a71461015557806355fd83e51461018a5780635dac9bb9146101c2576100f3565b366100f357005b600080356001600160e01b03191681527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260409020546001600160a01b031661013e57600080fd5b6101536000356001600160e01b031916610382565b005b34801561016157600080fd5b50610175610170366004611aef565b6103e7565b60405190151581526020015b60405180910390f35b34801561019657600080fd5b506101aa6101a5366004611b0a565b61041e565b6040516001600160a01b039091168152602001610181565b3480156101ce57600080fd5b506101e26101dd366004611b38565b610452565b604051908152602001610181565b3480156101fc57600080fd5b5061017561020b366004611b0a565b61050a565b34801561021c57600080fd5b5061015361022b366004611b64565b610541565b34801561023c57600080fd5b506101536105a2565b34801561025157600080fd5b50610153610260366004611b9b565b6105b6565b34801561027157600080fd5b507f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc6546001600160a01b03166101aa565b3480156102ae57600080fd5b506101536102bd366004611bca565b61065c565b3480156102ce57600080fd5b506101756102dd366004611b0a565b610a06565b3480156102ee57600080fd5b506101e26102fd366004611b0a565b610b79565b34801561030e57600080fd5b5061015361031d366004611b9b565b610d62565b34801561032e57600080fd5b5061015361033d366004611bef565b610df5565b34801561034e57600080fd5b5061015361035d366004611b9b565b611327565b34801561036e57600080fd5b5061015361037d366004611b0a565b6113b4565b6001600160e01b0319811660009081527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260408120546001600160a01b031636828037600080366000845af43d6000803e8080156103e2573d6000f35b3d6000fd5b60006001600160e01b0319821663ddb05bc160e01b148061041857506301ffc9a760e01b6001600160e01b03198316145b92915050565b6000600080516020611eb683398151915282612711811061044157610441611c31565b01546001600160a01b031692915050565b6001600160a01b03821660009081527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2b602052604081205482106104c25760405162461bcd60e51b8152602060048201526002602482015261454960f01b60448201526064015b60405180910390fd5b506001600160a01b039190911660009081527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2c60209081526040808320938352929052205490565b600080600080516020611eb683398151915283612711811061052e5761052e611c31565b01546001600160a01b0316141592915050565b610549611801565b6001600160e01b03199190911660009081527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d6020526040902080546001600160a01b0319166001600160a01b03909216919091179055565b6105aa611801565b6105b46000611889565b565b6105be611801565b600080356001600160e01b03191681527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260409020546001600160a01b03161561061e5761061a6000356001600160e01b031916610382565b5050565b7f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddb31980546001600160a01b0319166001600160a01b0383161790555b50565b6002600054036106ae5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016104b9565b600260009081556001600160e01b031981351681527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260409020546001600160a01b0316156107155761070f6000356001600160e01b031916610382565b506109fd565b6000600080516020611e96833981519152600101546040516310ea4bc960e21b8152600481018590526001600160a01b03909116906343a92f249060240160c060405180830381865afa158015610770573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107949190611c6f565b90506000600080516020611eb68339815191528461271181106107b9576107b9611c31565b6040805160808101825292909101546001600160a01b038116835263ffffffff600160a01b820481166020850152600160c01b8204811692840192909252600160e01b9004166060820152905061080d3390565b6001600160a01b031681600001516001600160a01b0316146108565760405162461bcd60e51b8152602060048201526002602482015261454560f01b60448201526064016104b9565b60006108b7826040015163ffffffff1662015180856060015161ffff1685602001518760a001516108879190611d32565b63ffffffff166108979190611d56565b6108a19190611d6d565b6108ab9190611d8f565b8563ffffffff166118fa565b90506108c281611912565b826040018181516108d39190611da2565b63ffffffff16905250610916600080516020611e968339815191525b546001600160a01b031633602086015161091185670de0b6b3a7640000611d56565b611992565b81600080516020611eb683398151915286612711811061093857610938611c31565b825191018054602084015160408501516060909501516001600160a01b039094166001600160c01b031990921691909117600160a01b63ffffffff92831602176001600160c01b0316600160c01b948216949094026001600160e01b031693909317600160e01b9390921692909202179055336001600160a01b0316857f4d7281212f84ddb5b45fa8c98cceaca247d2a9ca33497d7feb95df1d3d047b086109e884670de0b6b3a7640000611d56565b60405190815260200160405180910390a35050505b50506001600055565b600080600080516020611e96833981519152600101546040516310ea4bc960e21b8152600481018590526001600160a01b03909116906343a92f249060240160c060405180830381865afa158015610a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a869190611c6f565b90506000600080516020611eb6833981519152846127118110610aab57610aab611c31565b6040805160808101825292909101546001600160a01b03808216845263ffffffff600160a01b83048116602080870191909152600160c01b8404821694860194909452600160e01b9092049091166060840152908401519192501615801590610b4257506080820151610b259061ffff1662015180611dbf565b610b349062ffffff1642611de6565b8260a0015163ffffffff1610155b81519093506001600160a01b031615610b72576000610b6085610b79565b9050838015610b6e57504281105b9350505b5050919050565b600080600080516020611e96833981519152600101546040516310ea4bc960e21b8152600481018590526001600160a01b03909116906343a92f249060240160c060405180830381865afa158015610bd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf99190611c6f565b90506000600080516020611eb6833981519152846127118110610c1e57610c1e611c31565b6040805160808101825292909101546001600160a01b038116835263ffffffff600160a01b820481166020850152600160c01b8204811692840192909252600160e01b90041660608083019190915283015190915061ffff16600003610c90578160a0015163ffffffff169250610b72565b6000826060015161ffff16826040015163ffffffff1662015180610cb49190611d56565b610cbe9190611d6d565b90506000610cfc846080015161ffff1662015180610cdc9190611dbf565b62ffffff16846020015163ffffffff1642610cf79190611d8f565b611ac2565b821015905080610d3557836060015161ffff16846040015161ffff1662015180610d269190611d56565b610d309190611d6d565b610d38565b60005b82846020015163ffffffff16610d4e9190611de6565b610d589190611d8f565b9695505050505050565b610d6a611801565b600080356001600160e01b03191681527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260409020546001600160a01b031615610dc65761061a6000356001600160e01b031916610382565b600080516020611e9683398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b600260005403610e475760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016104b9565b600260009081556001600160e01b031981351681527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260409020546001600160a01b031615610eae57610ea86000356001600160e01b031916610382565b5061131d565b6000600080516020611e96833981519152600101546040516310ea4bc960e21b8152600481018690526001600160a01b03909116906343a92f249060240160c060405180830381865afa158015610f09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2d9190611c6f565b90506000600080516020611eb6833981519152856127118110610f5257610f52611c31565b6040805160808101825292909101546001600160a01b03808216845263ffffffff600160a01b83048116602080870191909152600160c01b8404821694860194909452600160e01b90920490911660608401529084015191925016610fde5760405162461bcd60e51b815260206004820152600260248201526122a760f11b60448201526064016104b9565b6080820151610ff49061ffff1662015180611dbf565b6110039062ffffff1642611de6565b8260a0015163ffffffff1610156110415760405162461bcd60e51b8152602060048201526002602482015261454360f01b60448201526064016104b9565b80516001600160a01b03161561109b57600061105c86610b79565b90504281106110925760405162461bcd60e51b815260206004820152600260248201526122a160f11b60448201526064016104b9565b50600060408201525b816060015182604001516110af9190611df9565b61ffff168363ffffffff1610156110ed5760405162461bcd60e51b8152602060048201526002602482015261115160f21b60448201526064016104b9565b600061112962015180846060015161ffff16428660a0015163ffffffff166111159190611d8f565b61111f9190611d56565b6108ab9190611d6d565b338352905061113742611912565b63ffffffff16602083015261114b81611912565b8260400181815161115c9190611da2565b63ffffffff9081169091528616606084015250611186600080516020611e968339815191526108ef565b81600080516020611eb68339815191528761271181106111a8576111a8611c31565b8251910180546020808501516040808701516060909701516001600160a01b039096166001600160c01b031990941693909317600160a01b63ffffffff92831602176001600160c01b0316600160c01b968216969096026001600160e01b031695909517600160e01b95909416949094029290921790553360008181527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2b80855283822080547f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2c875285842081855287528584208d90558c84527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2d8752948320859055928252909352805491926112be83611e14565b91905055506112ca3390565b6001600160a01b0316877f353d96187ca8d55ed63c9c367b64e020ee11741e4a2532c04cbb1a211745c85961130785670de0b6b3a7640000611d56565b60405190815260200160405180910390a3505050505b5050600160005550565b61132f611801565b6001600160a01b0381166113ab5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016104b9565b61065981611889565b600080356001600160e01b03191681527f465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80d60205260409020546001600160a01b0316156114105761061a6000356001600160e01b031916610382565b336001600160a01b0316600080516020611e96833981519152600101546040516310ea4bc960e21b8152600481018490526001600160a01b03909116906343a92f249060240160c060405180830381865afa158015611473573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114979190611c6f565b602001516001600160a01b0316146114d65760405162461bcd60e51b8152602060048201526002602482015261453960f01b60448201526064016104b9565b60006114e182610b79565b90504281106115175760405162461bcd60e51b815260206004820152600260248201526122a160f11b60448201526064016104b9565b6000600080516020611eb683398151915283612711811061153a5761153a611c31565b01546040516001600160a01b039091169150819084907ff067387f7b23926de806389f49810aeacc5e1ce8c46e12eb17d20037dd0cfb9b90600090a36001600160a01b03811660009081527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2b602052604081208054916115b983611e2d565b919050555060006115d5600080516020611e9683398151915290565b6001600160a01b03831660009081526127139190910160209081526040808320548784527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2d909252909120549091508082146116a3576001600160a01b03831660009081527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2c6020908152604080832085845282528083205484845281842081905583527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2d90915290208190555b60008581527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2d602090815260408083208390556001600160a01b03861683527f90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddda2c82528083208484528252808320839055805160808101825283815291820183905281018290526060810191909152600080516020611eb683398151915286612711811061175257611752611c31565b825191018054602084015160408501516060909501516001600160a01b039094166001600160c01b031990921691909117600160a01b63ffffffff92831602176001600160c01b0316600160c01b948216949094026001600160e01b031693909317600160e01b93909216929092021790555050505050565b600080516020611e9683398151915290565b7f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc690565b336118337f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc6546001600160a01b031690565b6001600160a01b0316146105b45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104b9565b7f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000818310611909578161190b565b825b9392505050565b600063ffffffff82111561198e5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201527f322062697473000000000000000000000000000000000000000000000000000060648201526084016104b9565b5090565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916119f69190611e44565b6000604051808303816000865af19150503d8060008114611a33576040519150601f19603f3d011682016040523d82523d6000602084013e611a38565b606091505b5091509150818015611a62575080511580611a62575080806020019051810190611a629190611e73565b611aba5760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b60648201526084016104b9565b505050505050565b600081831015611909578161190b565b80356001600160e01b031981168114611aea57600080fd5b919050565b600060208284031215611b0157600080fd5b61190b82611ad2565b600060208284031215611b1c57600080fd5b5035919050565b6001600160a01b038116811461065957600080fd5b60008060408385031215611b4b57600080fd5b8235611b5681611b23565b946020939093013593505050565b60008060408385031215611b7757600080fd5b611b8083611ad2565b91506020830135611b9081611b23565b809150509250929050565b600060208284031215611bad57600080fd5b813561190b81611b23565b63ffffffff8116811461065957600080fd5b60008060408385031215611bdd57600080fd5b823591506020830135611b9081611bb8565b600080600060608486031215611c0457600080fd5b833592506020840135611c1681611bb8565b91506040840135611c2681611bb8565b809150509250925092565b634e487b7160e01b600052603260045260246000fd5b805161ffff81168114611aea57600080fd5b8051611aea81611b23565b8051611aea81611bb8565b600060c08284031215611c8157600080fd5b60405160c0810181811067ffffffffffffffff82111715611cb257634e487b7160e01b600052604160045260246000fd5b604052611cbe83611c47565b8152611ccc60208401611c59565b6020820152611cdd60408401611c47565b6040820152611cee60608401611c47565b6060820152611cff60808401611c47565b6080820152611d1060a08401611c64565b60a08201529392505050565b634e487b7160e01b600052601160045260246000fd5b63ffffffff828116828216039080821115611d4f57611d4f611d1c565b5092915050565b808202811582820484141761041857610418611d1c565b600082611d8a57634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111561041857610418611d1c565b63ffffffff818116838216019080821115611d4f57611d4f611d1c565b62ffffff818116838216028082169190828114611dde57611dde611d1c565b505092915050565b8082018082111561041857610418611d1c565b61ffff818116838216019080821115611d4f57611d4f611d1c565b600060018201611e2657611e26611d1c565b5060010190565b600081611e3c57611e3c611d1c565b506000190190565b6000825160005b81811015611e655760208186018101518583015201611e4b565b506000920191825250919050565b600060208284031215611e8557600080fd5b8151801515811461190b57600080fdfe90efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddb31890efdc3da40051e1275cdc68e1fa2871bc5fd2c340e81db1c32a12983bddb31aa2646970667358221220d22c3f2b34d4cd7ca5f844a106be4e3e02191b9cee6f1e88b4e3695935b8fb8b64736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ccccb68e1a848cbdb5b60a974e07aae143ed40c3000000000000000000000000f0e2c83BD68Ae79900Ab9892ac77C9311b278117
-----Decoded View---------------
Arg [0] : _paymentTokenAddress (address): 0xcccCb68e1A848CBDB5b60a974E07aAE143ed40C3
Arg [1] : _escrow (address): 0xf0e2c83BD68Ae79900Ab9892ac77C9311b278117
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000ccccb68e1a848cbdb5b60a974e07aae143ed40c3
Arg [1] : 000000000000000000000000f0e2c83BD68Ae79900Ab9892ac77C9311b278117
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.