Source Code
Latest 25 from a total of 4,224 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Purchase | 14877048 | 356 days ago | IN | 0 ETH | 0.00000053 | ||||
| Purchase | 14870376 | 357 days ago | IN | 0 ETH | 0.00000099 | ||||
| Purchase | 14860337 | 357 days ago | IN | 0 ETH | 0.00000017 | ||||
| Purchase | 14855228 | 357 days ago | IN | 0 ETH | 0.00000515 | ||||
| Purchase | 14855210 | 357 days ago | IN | 0 ETH | 0.00000577 | ||||
| Purchase | 14854960 | 357 days ago | IN | 0 ETH | 0.00001686 | ||||
| Purchase | 14854525 | 357 days ago | IN | 0 ETH | 0.00000367 | ||||
| Purchase | 14854504 | 357 days ago | IN | 0 ETH | 0.00000327 | ||||
| Purchase | 14852761 | 357 days ago | IN | 0 ETH | 0.00000035 | ||||
| Purchase | 14852378 | 357 days ago | IN | 0 ETH | 0.00000023 | ||||
| Purchase | 14829225 | 358 days ago | IN | 0 ETH | 0.0000003 | ||||
| Purchase | 14826199 | 358 days ago | IN | 0 ETH | 0.00000011 | ||||
| Purchase | 14820486 | 358 days ago | IN | 0 ETH | 0.00000012 | ||||
| Purchase | 14813126 | 358 days ago | IN | 0 ETH | 0.00000012 | ||||
| Purchase | 14811277 | 358 days ago | IN | 0 ETH | 0.00000012 | ||||
| Purchase | 14808687 | 358 days ago | IN | 0 ETH | 0.00000012 | ||||
| Purchase | 14768685 | 359 days ago | IN | 0 ETH | 0.00000159 | ||||
| Purchase | 14768500 | 359 days ago | IN | 0 ETH | 0.00000122 | ||||
| Purchase | 14751597 | 359 days ago | IN | 0 ETH | 0.00000038 | ||||
| Purchase | 14751358 | 359 days ago | IN | 0 ETH | 0.00000032 | ||||
| Purchase | 14748477 | 359 days ago | IN | 0 ETH | 0.00000024 | ||||
| Purchase | 14748405 | 359 days ago | IN | 0 ETH | 0.00000023 | ||||
| Purchase | 14748200 | 359 days ago | IN | 0 ETH | 0.00000021 | ||||
| Purchase | 14746376 | 359 days ago | IN | 0 ETH | 0.00000017 | ||||
| Purchase | 14741691 | 360 days ago | IN | 0 ETH | 0.00000031 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
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:
CavePurchaseERC20
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
No with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
import "@pythnetwork/pyth-sdk-solidity/PythUtils.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
/**
* @title CavePurchaseERC20
* @notice Contract for purchasing items using ERC20 tokens, with price feeds from Pyth.
*/
contract CavePurchaseERC20 is AccessControl, ReentrancyGuard, Pausable {
using SafeERC20 for IERC20;
/**
@notice Current admin of the contract
@dev Admin can add acceptable tokens, set items min amount & price,
@dev the recipient address, the price feed expiry, pause & unpause the contract,
@dev and set the Pyth Network contract address.
*/
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
/**
@notice Pyth contract address
*/
IPyth public pyth;
/**
@notice Default maximum age of price returned from Pyth Network
*/
uint256 public priceFeedExpiry = 1 days;
/**
@notice The receiver of tokens from any purchase
*/
address public recipient;
/**
* @notice Mapping of a token address to associated pythOracleId.
* @dev pythOracleId is used to fetch the USD price of the token from Pyth Network.
*/
mapping(address => bytes32) public acceptableTokens;
/**
@notice Mapping of item ID to price per item in USD
@dev USD price should alwasy have 18 decimals
*/
mapping(uint256 => uint256) public pricePerItem;
/**
@notice Minimum allowable quantity of an item to be purchased
*/
mapping(uint256 => uint256) public minQuantity;
event TokenAdded(address indexed token, bytes32 indexed priceOracleId);
event TokenRemoved(address indexed token);
event ItemPriceSet(uint256 indexed itemId, uint256 price);
event MinQuantitySet(uint256 indexed itemId, uint256 quantity);
event RecipientSet(address indexed recipient);
event PriceFeedExpirySet(uint256 expiry);
event PythContractSet(address indexed pythContract);
event Purchased(
uint256 indexed itemId,
uint256 amount,
address indexed purchaser,
uint256 tokenAmount,
address token
);
/**
* @notice Constructor to initialize the contract with the Pyth contract address and recipient address.
* @param _pythContract Address of the Pyth contract.
* @param _recipient Address of the recipient who will receive the tokens.
* @param _admin Address of the admin who can add acceptable tokens and set prices.
* @param _superAdmin Address of the default admin.
*/
constructor(
address _pythContract,
address _recipient,
address _admin,
address _superAdmin
) {
require(_pythContract != address(0), "invalidPythContract");
require(_recipient != address(0), "invalidRecipient");
require(_admin != address(0), "invalidAdmin");
require(_superAdmin != address(0), "invalidSuperAdmin");
pyth = IPyth(_pythContract);
recipient = _recipient;
_grantRole(ADMIN_ROLE, _admin);
_grantRole(DEFAULT_ADMIN_ROLE, _superAdmin);
}
/**
* @notice Adds an acceptable token with its price oracle ID.
* @param _token Address of the token.
* @param _priceOracleId ID of the price oracle for the token.
*/
function addAcceptableToken(
address _token,
bytes32 _priceOracleId
) external onlyRole(ADMIN_ROLE) {
require(_token != address(0), "invalidToken");
require(_priceOracleId != 0, "invalidPriceOracleId");
require(
IERC20Metadata(_token).decimals() == 18,
"invalidTokenDecimals"
);
acceptableTokens[_token] = _priceOracleId;
emit TokenAdded(_token, _priceOracleId);
}
/**
* @notice Removes an acceptable token.
* @param _token Address of the token.
*/
function removeAcceptableToken(
address _token
) external onlyRole(ADMIN_ROLE) {
require(acceptableTokens[_token] != 0, "tokenUnacceptable");
delete acceptableTokens[_token];
emit TokenRemoved(_token);
}
/**
* @notice Sets the price for an item.
* @param _itemId ID of the item.
* @param _price Price of the item in USD with 18 decimals.
*/
function setItemPrice(
uint256 _itemId,
uint256 _price
) external onlyRole(ADMIN_ROLE) {
pricePerItem[_itemId] = _price;
emit ItemPriceSet(_itemId, _price);
}
/**
* @notice Sets the minimum quantity for an item to be purchased.
* @param _itemId ID of the item.
* @param _quantity Minimum quantity for the item.
*/
function setMinQuantity(
uint256 _itemId,
uint256 _quantity
) external onlyRole(ADMIN_ROLE) {
minQuantity[_itemId] = _quantity;
emit MinQuantitySet(_itemId, _quantity);
}
/**
* @notice Changes the recipient address.
* @param _recipient New recipient address.
*/
function setRecipient(address _recipient) external onlyRole(ADMIN_ROLE) {
recipient = _recipient;
emit RecipientSet(_recipient);
}
/**
* @notice Changes the price feed expiry duration.
* @param _expiry New price feed expiry duration.
*/
function setPriceFeedExpiry(uint256 _expiry) external onlyRole(ADMIN_ROLE) {
require(_expiry > 0, "invalidExpiry");
priceFeedExpiry = _expiry;
emit PriceFeedExpirySet(_expiry);
}
/**
* @notice Changes the Pyth contract address.
* @dev In case for any reason the Pyth contract needs to be updated.
* @param _pythContract New Pyth contract address.
*/
function setPythContract(
address _pythContract
) external onlyRole(ADMIN_ROLE) {
require(_pythContract != address(0), "invalidPythContract");
pyth = IPyth(_pythContract);
emit PythContractSet(_pythContract);
}
/**
* @notice Pauses the contract.
*/
function pause() external onlyRole(ADMIN_ROLE) {
_pause();
}
/**
* @notice Unpauses the contract.
*/
function unpause() external onlyRole(ADMIN_ROLE) {
_unpause();
}
/**
* @notice Purchases an item using a specified token.
* @param _itemId ID of the item to purchase.
* @param _amount Amount of the item to purchase.
* @param _token Address of the token to use for the purchase.
*/
function purchase(
uint256 _itemId,
uint256 _amount,
address _token
) external nonReentrant whenNotPaused {
uint256 _tokenAmount = getTotalPriceInternal(_itemId, _amount, _token);
IERC20(_token).safeTransferFrom(msg.sender, recipient, _tokenAmount);
emit Purchased(_itemId, _amount, msg.sender, _tokenAmount, _token);
}
/**
* @notice Returns a quoted token amount of an item purchase
* @param _itemId ID of the item to purchase.
* @param _amount Amount of the item to purchase.
* @param _token Address of the token to use for the purchase.
*/
function getTotalPrice(
uint256 _itemId,
uint256 _amount,
address _token
) external view returns (uint256) {
return getTotalPriceInternal(_itemId, _amount, _token);
}
/**
* @notice Returns a quoted token amount of an item purchase + does necessary safety checks for the purchase
* @param _itemId ID of the item to purchase.
* @param _amount Amount of the item to purchase.
* @param _token Address of the token to use for the purchase.
*/
function getTotalPriceInternal(
uint256 _itemId,
uint256 _amount,
address _token
) private view returns (uint256) {
uint256 _itemMinQuantity = minQuantity[_itemId];
bytes32 _tokenPriceId = acceptableTokens[_token];
require(_itemMinQuantity > 0, "invalidItemId");
require(_amount >= _itemMinQuantity, "insufficientQuantity");
require(_tokenPriceId != 0, "tokenUnacceptable");
PythStructs.Price memory price = pyth.getPriceUnsafe(_tokenPriceId);
require(
block.timestamp - price.publishTime <= priceFeedExpiry,
"priceFeedExpired"
);
uint256 _tokenPrice = PythUtils.convertToUint(
price.price,
price.expo,
18
);
require(_tokenPrice > 0, "invalidTokenPrice");
uint256 _tokenAmount = (1e18 * _amount * pricePerItem[_itemId]) /
_tokenPrice;
require(_tokenAmount > 0, "invalidTotalPrice");
return _tokenAmount;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @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);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @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 or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* 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.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @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`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @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;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./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);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @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
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
bool private _paused;
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @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;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "./PythStructs.sol";
import "./IPythEvents.sol";
/// @title Consume prices from the Pyth Network (https://pyth.network/).
/// @dev Please refer to the guidance at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how to consume prices safely.
/// @author Pyth Data Association
interface IPyth is IPythEvents {
/// @notice Returns the period (in seconds) that a price feed is considered valid since its publish time
function getValidTimePeriod() external view returns (uint validTimePeriod);
/// @notice Returns the price and confidence interval.
/// @dev Reverts if the price has not been updated within the last `getValidTimePeriod()` seconds.
/// @param id The Pyth Price Feed ID of which to fetch the price and confidence interval.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getPrice(
bytes32 id
) external view returns (PythStructs.Price memory price);
/// @notice Returns the exponentially-weighted moving average price and confidence interval.
/// @dev Reverts if the EMA price is not available.
/// @param id The Pyth Price Feed ID of which to fetch the EMA price and confidence interval.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getEmaPrice(
bytes32 id
) external view returns (PythStructs.Price memory price);
/// @notice Returns the price of a price feed without any sanity checks.
/// @dev This function returns the most recent price update in this contract without any recency checks.
/// This function is unsafe as the returned price update may be arbitrarily far in the past.
///
/// Users of this function should check the `publishTime` in the price to ensure that the returned price is
/// sufficiently recent for their application. If you are considering using this function, it may be
/// safer / easier to use either `getPrice` or `getPriceNoOlderThan`.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getPriceUnsafe(
bytes32 id
) external view returns (PythStructs.Price memory price);
/// @notice Returns the price that is no older than `age` seconds of the current time.
/// @dev This function is a sanity-checked version of `getPriceUnsafe` which is useful in
/// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently
/// recently.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getPriceNoOlderThan(
bytes32 id,
uint age
) external view returns (PythStructs.Price memory price);
/// @notice Returns the exponentially-weighted moving average price of a price feed without any sanity checks.
/// @dev This function returns the same price as `getEmaPrice` in the case where the price is available.
/// However, if the price is not recent this function returns the latest available price.
///
/// The returned price can be from arbitrarily far in the past; this function makes no guarantees that
/// the returned price is recent or useful for any particular application.
///
/// Users of this function should check the `publishTime` in the price to ensure that the returned price is
/// sufficiently recent for their application. If you are considering using this function, it may be
/// safer / easier to use either `getEmaPrice` or `getEmaPriceNoOlderThan`.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getEmaPriceUnsafe(
bytes32 id
) external view returns (PythStructs.Price memory price);
/// @notice Returns the exponentially-weighted moving average price that is no older than `age` seconds
/// of the current time.
/// @dev This function is a sanity-checked version of `getEmaPriceUnsafe` which is useful in
/// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently
/// recently.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getEmaPriceNoOlderThan(
bytes32 id,
uint age
) external view returns (PythStructs.Price memory price);
/// @notice Update price feeds with given update messages.
/// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
/// `getUpdateFee` with the length of the `updateData` array.
/// Prices will be updated if they are more recent than the current stored prices.
/// The call will succeed even if the update is not the most recent.
/// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid.
/// @param updateData Array of price update data.
function updatePriceFeeds(bytes[] calldata updateData) external payable;
/// @notice Wrapper around updatePriceFeeds that rejects fast if a price update is not necessary. A price update is
/// necessary if the current on-chain publishTime is older than the given publishTime. It relies solely on the
/// given `publishTimes` for the price feeds and does not read the actual price update publish time within `updateData`.
///
/// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
/// `getUpdateFee` with the length of the `updateData` array.
///
/// `priceIds` and `publishTimes` are two arrays with the same size that correspond to senders known publishTime
/// of each priceId when calling this method. If all of price feeds within `priceIds` have updated and have
/// a newer or equal publish time than the given publish time, it will reject the transaction to save gas.
/// Otherwise, it calls updatePriceFeeds method to update the prices.
///
/// @dev Reverts if update is not needed or the transferred fee is not sufficient or the updateData is invalid.
/// @param updateData Array of price update data.
/// @param priceIds Array of price ids.
/// @param publishTimes Array of publishTimes. `publishTimes[i]` corresponds to known `publishTime` of `priceIds[i]`
function updatePriceFeedsIfNecessary(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64[] calldata publishTimes
) external payable;
/// @notice Returns the required fee to update an array of price updates.
/// @param updateData Array of price update data.
/// @return feeAmount The required fee in Wei.
function getUpdateFee(
bytes[] calldata updateData
) external view returns (uint feeAmount);
/// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published
/// within `minPublishTime` and `maxPublishTime`.
///
/// You can use this method if you want to use a Pyth price at a fixed time and not the most recent price;
/// otherwise, please consider using `updatePriceFeeds`. This method may store the price updates on-chain, if they
/// are more recent than the current stored prices.
///
/// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
/// `getUpdateFee` with the length of the `updateData` array.
///
///
/// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is
/// no update for any of the given `priceIds` within the given time range.
/// @param updateData Array of price update data.
/// @param priceIds Array of price ids.
/// @param minPublishTime minimum acceptable publishTime for the given `priceIds`.
/// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`.
/// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).
function parsePriceFeedUpdates(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64 minPublishTime,
uint64 maxPublishTime
) external payable returns (PythStructs.PriceFeed[] memory priceFeeds);
/// @notice Similar to `parsePriceFeedUpdates` but ensures the updates returned are
/// the first updates published in minPublishTime. That is, if there are multiple updates for a given timestamp,
/// this method will return the first update. This method may store the price updates on-chain, if they
/// are more recent than the current stored prices.
///
///
/// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is
/// no update for any of the given `priceIds` within the given time range and uniqueness condition.
/// @param updateData Array of price update data.
/// @param priceIds Array of price ids.
/// @param minPublishTime minimum acceptable publishTime for the given `priceIds`.
/// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`.
/// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).
function parsePriceFeedUpdatesUnique(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64 minPublishTime,
uint64 maxPublishTime
) external payable returns (PythStructs.PriceFeed[] memory priceFeeds);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @title IPythEvents contains the events that Pyth contract emits.
/// @dev This interface can be used for listening to the updates for off-chain and testing purposes.
interface IPythEvents {
/// @dev Emitted when the price feed with `id` has received a fresh update.
/// @param id The Pyth Price Feed ID.
/// @param publishTime Publish time of the given price update.
/// @param price Price of the given price update.
/// @param conf Confidence interval of the given price update.
event PriceFeedUpdate(
bytes32 indexed id,
uint64 publishTime,
int64 price,
uint64 conf
);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
contract PythStructs {
// A price with a degree of uncertainty, represented as a price +- a confidence interval.
//
// The confidence interval roughly corresponds to the standard error of a normal distribution.
// Both the price and confidence are stored in a fixed-point numeric representation,
// `x * (10^expo)`, where `expo` is the exponent.
//
// Please refer to the documentation at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how
// to how this price safely.
struct Price {
// Price
int64 price;
// Confidence interval around the price
uint64 conf;
// Price exponent
int32 expo;
// Unix timestamp describing when the price was published
uint publishTime;
}
// PriceFeed represents a current aggregate price from pyth publisher feeds.
struct PriceFeed {
// The price ID.
bytes32 id;
// Latest available price
Price price;
// Latest available exponentially-weighted moving average price
Price emaPrice;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
library PythUtils {
/// @notice Converts a Pyth price to a uint256 with a target number of decimals
/// @param price The Pyth price
/// @param expo The Pyth price exponent
/// @param targetDecimals The target number of decimals
/// @return The price as a uint256
/// @dev Function will lose precision if targetDecimals is less than the Pyth price decimals.
/// This method will truncate any digits that cannot be represented by the targetDecimals.
/// e.g. If the price is 0.000123 and the targetDecimals is 2, the result will be 0
function convertToUint(
int64 price,
int32 expo,
uint8 targetDecimals
) public pure returns (uint256) {
if (price < 0 || expo > 0 || expo < -255) {
revert();
}
uint8 priceDecimals = uint8(uint32(-1 * expo));
if (targetDecimals >= priceDecimals) {
return
uint(uint64(price)) *
10 ** uint32(targetDecimals - priceDecimals);
} else {
return
uint(uint64(price)) /
10 ** uint32(priceDecimals - targetDecimals);
}
}
}{
"evmVersion": "paris",
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {
"@pythnetwork/pyth-sdk-solidity/PythUtils.sol": {
"PythUtils": "0x14e5bacb5f98778aeefdd4f79dc8e007dd1586cf"
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_pythContract","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_superAdmin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"itemId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"ItemPriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"itemId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"MinQuantitySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"expiry","type":"uint256"}],"name":"PriceFeedExpirySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"itemId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"purchaser","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"Purchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pythContract","type":"address"}],"name":"PythContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"RecipientSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"bytes32","name":"priceOracleId","type":"bytes32"}],"name":"TokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"TokenRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"acceptableTokens","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"bytes32","name":"_priceOracleId","type":"bytes32"}],"name":"addAcceptableToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"getTotalPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"minQuantity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeedExpiry","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pricePerItem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"purchase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pyth","outputs":[{"internalType":"contract IPyth","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"recipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"removeAcceptableToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemId","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"setItemPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemId","type":"uint256"},{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"setMinQuantity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_expiry","type":"uint256"}],"name":"setPriceFeedExpiry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pythContract","type":"address"}],"name":"setPythContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"}],"name":"setRecipient","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":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604052620151806003553480156200001857600080fd5b50604051620030233803806200302383398181016040528101906200003e9190620004dc565b600180819055506000600260006101000a81548160ff021916908315150217905550600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603620000d2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000c990620005af565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362000144576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200013b9062000621565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603620001b6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001ad9062000693565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160362000228576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200021f9062000705565b60405180910390fd5b83600260016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620002dc7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177583620002fd60201b60201c565b50620002f26000801b82620002fd60201b60201c565b505050505062000727565b60006200031183836200040060201b60201c565b620003f557600160008085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550620003916200046a60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050620003fa565b600090505b92915050565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600033905090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620004a48262000477565b9050919050565b620004b68162000497565b8114620004c257600080fd5b50565b600081519050620004d681620004ab565b92915050565b60008060008060808587031215620004f957620004f862000472565b5b60006200050987828801620004c5565b94505060206200051c87828801620004c5565b93505060406200052f87828801620004c5565b92505060606200054287828801620004c5565b91505092959194509250565b600082825260208201905092915050565b7f696e76616c696450797468436f6e747261637400000000000000000000000000600082015250565b6000620005976013836200054e565b9150620005a4826200055f565b602082019050919050565b60006020820190508181036000830152620005ca8162000588565b9050919050565b7f696e76616c6964526563697069656e7400000000000000000000000000000000600082015250565b6000620006096010836200054e565b91506200061682620005d1565b602082019050919050565b600060208201905081810360008301526200063c81620005fa565b9050919050565b7f696e76616c696441646d696e0000000000000000000000000000000000000000600082015250565b60006200067b600c836200054e565b9150620006888262000643565b602082019050919050565b60006020820190508181036000830152620006ae816200066c565b9050919050565b7f696e76616c6964537570657241646d696e000000000000000000000000000000600082015250565b6000620006ed6011836200054e565b9150620006fa82620006b5565b602082019050919050565b600060208201905081810360008301526200072081620006de565b9050919050565b6128ec80620007376000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c806366d003ac116100de578063a217fddf11610097578063d547741f11610071578063d547741f1461046d578063ea3bd5df14610489578063ea9ab8ba146104a5578063f98d06f0146104c15761018e565b8063a217fddf146103ef578063b202416c1461040d578063b8c7c62b1461043d5761018e565b806366d003ac1461033f57806375b238fc1461035d5780637c1030781461037b5780638456cb591461039957806391d14854146103a3578063994f26ad146103d35761018e565b806336568abe1161014b5780633f4ba83a116101255780633f4ba83a146102df5780633f5a7ce0146102e95780634229c35e146103055780635c975abb146103215761018e565b806336568abe1461028b5780633bbed4a0146102a75780633ef3af4c146102c35761018e565b806301ffc9a71461019357806306e07944146101c3578063248a9ca3146101f357806327063d85146102235780632f2ff15d1461025357806333fbeb621461026f575b600080fd5b6101ad60048036038101906101a89190611aa5565b6104df565b6040516101ba9190611aed565b60405180910390f35b6101dd60048036038101906101d89190611b3e565b610559565b6040516101ea9190611b7a565b60405180910390f35b61020d60048036038101906102089190611bcb565b610571565b60405161021a9190611c07565b60405180910390f35b61023d60048036038101906102389190611c80565b610590565b60405161024a9190611b7a565b60405180910390f35b61026d60048036038101906102689190611cd3565b6105a6565b005b61028960048036038101906102849190611d13565b6105c8565b005b6102a560048036038101906102a09190611cd3565b6106e9565b005b6102c160048036038101906102bc9190611d13565b610764565b005b6102dd60048036038101906102d89190611b3e565b610816565b005b6102e76108c5565b005b61030360048036038101906102fe9190611d40565b6108fa565b005b61031f600480360381019061031a9190611d40565b610979565b005b6103296109f8565b6040516103369190611aed565b60405180910390f35b610347610a0f565b6040516103549190611d8f565b60405180910390f35b610365610a35565b6040516103729190611c07565b60405180910390f35b610383610a59565b6040516103909190611b7a565b60405180910390f35b6103a1610a5f565b005b6103bd60048036038101906103b89190611cd3565b610a94565b6040516103ca9190611aed565b60405180910390f35b6103ed60048036038101906103e89190611daa565b610afe565b005b6103f7610d1d565b6040516104049190611c07565b60405180910390f35b61042760048036038101906104229190611d13565b610d24565b6040516104349190611c07565b60405180910390f35b61045760048036038101906104529190611b3e565b610d3c565b6040516104649190611b7a565b60405180910390f35b61048760048036038101906104829190611cd3565b610d54565b005b6104a3600480360381019061049e9190611c80565b610d76565b005b6104bf60048036038101906104ba9190611d13565b610e45565b005b6104c9610f7d565b6040516104d69190611e49565b60405180910390f35b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610552575061055182610fa3565b5b9050919050565b60076020528060005260406000206000915090505481565b6000806000838152602001908152602001600020600101549050919050565b600061059d84848461100d565b90509392505050565b6105af82610571565b6105b881611388565b6105c2838361139c565b50505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756105f281611388565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610661576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065890611ec1565b60405180910390fd5b81600260016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167fb44cac8346035a97687cc6084879f7d9bd139771dfc3bf31a5301bedf0bdf70660405160405180910390a25050565b6106f161148d565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610755576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61075f8282611495565b505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177561078e81611388565b81600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167f9d900d71c28433348acb1bec780a061608a96b149370abce77fd54ba2d47940160405160405180910390a25050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177561084081611388565b60008211610883576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087a90611f2d565b60405180910390fd5b816003819055507f5d69959d28f91d396c7300d76c5ed3854a4bb332291e7e72e0e9093b8e1364c0826040516108b99190611b7a565b60405180910390a15050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756108ef81611388565b6108f7611587565b50565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177561092481611388565b816007600085815260200190815260200160002081905550827f059e6c5fb94276005f6011c02ffe594be180083486bae272a6f84f4c39667fe18360405161096c9190611b7a565b60405180910390a2505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756109a381611388565b816006600085815260200190815260200160002081905550827f53973a0aa9eb26609e2a6bb41f5235722e699b14e88f6eb24fc85c51167529d8836040516109eb9190611b7a565b60405180910390a2505050565b6000600260009054906101000a900460ff16905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b60035481565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610a8981611388565b610a916115ea565b50565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610b2881611388565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610b97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b8e90611f99565b60405180910390fd5b6000801b8203610bdc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bd390612005565b60405180910390fd5b60128373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4d919061205e565b60ff1614610c90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c87906120d7565b60405180910390fd5b81600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550818373ffffffffffffffffffffffffffffffffffffffff167fe6f2c806df4d61ecb96304200f584c14ad8572a4d28873ae7c636faf01645fdb60405160405180910390a3505050565b6000801b81565b60056020528060005260406000206000915090505481565b60066020528060005260406000206000915090505481565b610d5d82610571565b610d6681611388565b610d708383611495565b50505050565b610d7e61164d565b610d86611693565b6000610d9384848461100d565b9050610de433600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16838573ffffffffffffffffffffffffffffffffffffffff166116d4909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff16847f51bdb8be6d43e725856fe4b463037c16a6ddd72b1ac6cf1ea3763bb752aa7068858486604051610e2f939291906120f7565b60405180910390a350610e40611756565b505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610e6f81611388565b6000801b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403610ef3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eea9061217a565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090558173ffffffffffffffffffffffffffffffffffffffff167f4c910b69fe65a61f7531b9c5042b2329ca7179c77290aa7e2eb3afa3c8511fd360405160405180910390a25050565b600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600080600760008681526020019081526020016000205490506000600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600082116110ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a4906121e6565b60405180910390fd5b818510156110f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110e790612252565b60405180910390fd5b6000801b8103611135576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161112c9061217a565b60405180910390fd5b6000600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166396834ad3836040518263ffffffff1660e01b81526004016111929190611c07565b608060405180830381865afa1580156111af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d39190612442565b90506003548160600151426111e8919061249e565b1115611229576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112209061251e565b60405180910390fd5b60007314e5bacb5f98778aeefdd4f79dc8e007dd1586cf63b55522b28360000151846040015160126040518463ffffffff1660e01b815260040161126f93929190612597565b602060405180830381865af415801561128c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b091906125ce565b9050600081116112f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ec90612647565b60405180910390fd5b600081600660008b81526020019081526020016000205489670de0b6b3a76400006113209190612667565b61132a9190612667565b61133491906126d8565b905060008111611379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137090612755565b60405180910390fd5b80955050505050509392505050565b6113998161139461148d565b61175f565b50565b60006113a88383610a94565b61148257600160008085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555061141f61148d565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611487565b600090505b92915050565b600033905090565b60006114a18383610a94565b1561157c57600080600085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555061151961148d565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611581565b600090505b92915050565b61158f6117b0565b6000600260006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6115d361148d565b6040516115e09190611d8f565b60405180910390a1565b6115f2611693565b6001600260006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861163661148d565b6040516116439190611d8f565b60405180910390a1565b600260015403611689576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600181905550565b61169b6109f8565b156116d2576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b611750848573ffffffffffffffffffffffffffffffffffffffff166323b872dd86868660405160240161170993929190612775565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506117f0565b50505050565b60018081905550565b6117698282610a94565b6117ac5780826040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016117a39291906127ac565b60405180910390fd5b5050565b6117b86109f8565b6117ee576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b600061181b828473ffffffffffffffffffffffffffffffffffffffff1661188790919063ffffffff16565b9050600081511415801561184057508080602001905181019061183e9190612801565b155b1561188257826040517f5274afe70000000000000000000000000000000000000000000000000000000081526004016118799190611d8f565b60405180910390fd5b505050565b60606118958383600061189d565b905092915050565b6060814710156118e457306040517fcd7860590000000000000000000000000000000000000000000000000000000081526004016118db9190611d8f565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16848660405161190d919061289f565b60006040518083038185875af1925050503d806000811461194a576040519150601f19603f3d011682016040523d82523d6000602084013e61194f565b606091505b509150915061195f86838361196a565b925050509392505050565b60608261197f5761197a826119f9565b6119f1565b600082511480156119a7575060008473ffffffffffffffffffffffffffffffffffffffff163b145b156119e957836040517f9996b3150000000000000000000000000000000000000000000000000000000081526004016119e09190611d8f565b60405180910390fd5b8190506119f2565b5b9392505050565b600081511115611a0c5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000604051905090565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611a8281611a4d565b8114611a8d57600080fd5b50565b600081359050611a9f81611a79565b92915050565b600060208284031215611abb57611aba611a48565b5b6000611ac984828501611a90565b91505092915050565b60008115159050919050565b611ae781611ad2565b82525050565b6000602082019050611b026000830184611ade565b92915050565b6000819050919050565b611b1b81611b08565b8114611b2657600080fd5b50565b600081359050611b3881611b12565b92915050565b600060208284031215611b5457611b53611a48565b5b6000611b6284828501611b29565b91505092915050565b611b7481611b08565b82525050565b6000602082019050611b8f6000830184611b6b565b92915050565b6000819050919050565b611ba881611b95565b8114611bb357600080fd5b50565b600081359050611bc581611b9f565b92915050565b600060208284031215611be157611be0611a48565b5b6000611bef84828501611bb6565b91505092915050565b611c0181611b95565b82525050565b6000602082019050611c1c6000830184611bf8565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611c4d82611c22565b9050919050565b611c5d81611c42565b8114611c6857600080fd5b50565b600081359050611c7a81611c54565b92915050565b600080600060608486031215611c9957611c98611a48565b5b6000611ca786828701611b29565b9350506020611cb886828701611b29565b9250506040611cc986828701611c6b565b9150509250925092565b60008060408385031215611cea57611ce9611a48565b5b6000611cf885828601611bb6565b9250506020611d0985828601611c6b565b9150509250929050565b600060208284031215611d2957611d28611a48565b5b6000611d3784828501611c6b565b91505092915050565b60008060408385031215611d5757611d56611a48565b5b6000611d6585828601611b29565b9250506020611d7685828601611b29565b9150509250929050565b611d8981611c42565b82525050565b6000602082019050611da46000830184611d80565b92915050565b60008060408385031215611dc157611dc0611a48565b5b6000611dcf85828601611c6b565b9250506020611de085828601611bb6565b9150509250929050565b6000819050919050565b6000611e0f611e0a611e0584611c22565b611dea565b611c22565b9050919050565b6000611e2182611df4565b9050919050565b6000611e3382611e16565b9050919050565b611e4381611e28565b82525050565b6000602082019050611e5e6000830184611e3a565b92915050565b600082825260208201905092915050565b7f696e76616c696450797468436f6e747261637400000000000000000000000000600082015250565b6000611eab601383611e64565b9150611eb682611e75565b602082019050919050565b60006020820190508181036000830152611eda81611e9e565b9050919050565b7f696e76616c696445787069727900000000000000000000000000000000000000600082015250565b6000611f17600d83611e64565b9150611f2282611ee1565b602082019050919050565b60006020820190508181036000830152611f4681611f0a565b9050919050565b7f696e76616c6964546f6b656e0000000000000000000000000000000000000000600082015250565b6000611f83600c83611e64565b9150611f8e82611f4d565b602082019050919050565b60006020820190508181036000830152611fb281611f76565b9050919050565b7f696e76616c696450726963654f7261636c654964000000000000000000000000600082015250565b6000611fef601483611e64565b9150611ffa82611fb9565b602082019050919050565b6000602082019050818103600083015261201e81611fe2565b9050919050565b600060ff82169050919050565b61203b81612025565b811461204657600080fd5b50565b60008151905061205881612032565b92915050565b60006020828403121561207457612073611a48565b5b600061208284828501612049565b91505092915050565b7f696e76616c6964546f6b656e446563696d616c73000000000000000000000000600082015250565b60006120c1601483611e64565b91506120cc8261208b565b602082019050919050565b600060208201905081810360008301526120f0816120b4565b9050919050565b600060608201905061210c6000830186611b6b565b6121196020830185611b6b565b6121266040830184611d80565b949350505050565b7f746f6b656e556e61636365707461626c65000000000000000000000000000000600082015250565b6000612164601183611e64565b915061216f8261212e565b602082019050919050565b6000602082019050818103600083015261219381612157565b9050919050565b7f696e76616c69644974656d496400000000000000000000000000000000000000600082015250565b60006121d0600d83611e64565b91506121db8261219a565b602082019050919050565b600060208201905081810360008301526121ff816121c3565b9050919050565b7f696e73756666696369656e745175616e74697479000000000000000000000000600082015250565b600061223c601483611e64565b915061224782612206565b602082019050919050565b6000602082019050818103600083015261226b8161222f565b9050919050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6122c082612277565b810181811067ffffffffffffffff821117156122df576122de612288565b5b80604052505050565b60006122f2611a3e565b90506122fe82826122b7565b919050565b60008160070b9050919050565b61231981612303565b811461232457600080fd5b50565b60008151905061233681612310565b92915050565b600067ffffffffffffffff82169050919050565b6123598161233c565b811461236457600080fd5b50565b60008151905061237681612350565b92915050565b60008160030b9050919050565b6123928161237c565b811461239d57600080fd5b50565b6000815190506123af81612389565b92915050565b6000815190506123c481611b12565b92915050565b6000608082840312156123e0576123df612272565b5b6123ea60806122e8565b905060006123fa84828501612327565b600083015250602061240e84828501612367565b6020830152506040612422848285016123a0565b6040830152506060612436848285016123b5565b60608301525092915050565b60006080828403121561245857612457611a48565b5b6000612466848285016123ca565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006124a982611b08565b91506124b483611b08565b92508282039050818111156124cc576124cb61246f565b5b92915050565b7f7072696365466565644578706972656400000000000000000000000000000000600082015250565b6000612508601083611e64565b9150612513826124d2565b602082019050919050565b60006020820190508181036000830152612537816124fb565b9050919050565b61254781612303565b82525050565b6125568161237c565b82525050565b6000819050919050565b600061258161257c6125778461255c565b611dea565b612025565b9050919050565b61259181612566565b82525050565b60006060820190506125ac600083018661253e565b6125b9602083018561254d565b6125c66040830184612588565b949350505050565b6000602082840312156125e4576125e3611a48565b5b60006125f2848285016123b5565b91505092915050565b7f696e76616c6964546f6b656e5072696365000000000000000000000000000000600082015250565b6000612631601183611e64565b915061263c826125fb565b602082019050919050565b6000602082019050818103600083015261266081612624565b9050919050565b600061267282611b08565b915061267d83611b08565b925082820261268b81611b08565b915082820484148315176126a2576126a161246f565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006126e382611b08565b91506126ee83611b08565b9250826126fe576126fd6126a9565b5b828204905092915050565b7f696e76616c6964546f74616c5072696365000000000000000000000000000000600082015250565b600061273f601183611e64565b915061274a82612709565b602082019050919050565b6000602082019050818103600083015261276e81612732565b9050919050565b600060608201905061278a6000830186611d80565b6127976020830185611d80565b6127a46040830184611b6b565b949350505050565b60006040820190506127c16000830185611d80565b6127ce6020830184611bf8565b9392505050565b6127de81611ad2565b81146127e957600080fd5b50565b6000815190506127fb816127d5565b92915050565b60006020828403121561281757612816611a48565b5b6000612825848285016127ec565b91505092915050565b600081519050919050565b600081905092915050565b60005b83811015612862578082015181840152602081019050612847565b60008484015250505050565b60006128798261282e565b6128838185612839565b9350612893818560208601612844565b80840191505092915050565b60006128ab828461286e565b91508190509291505056fea2646970667358221220bd7d031d74d7b31576e112912ef75f998e486a8cef62aa0a41ab4e3c7708c85c64736f6c63430008180033000000000000000000000000a2aa501b19aff244d90cc15a4cf739d2725b57290000000000000000000000002a83c210de4fb8beff00b032ab952d5b72ec8e1f0000000000000000000000008b50b3b19c3d8f66293339f7cfe473c76174612b0000000000000000000000008b50b3b19c3d8f66293339f7cfe473c76174612b
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061018e5760003560e01c806366d003ac116100de578063a217fddf11610097578063d547741f11610071578063d547741f1461046d578063ea3bd5df14610489578063ea9ab8ba146104a5578063f98d06f0146104c15761018e565b8063a217fddf146103ef578063b202416c1461040d578063b8c7c62b1461043d5761018e565b806366d003ac1461033f57806375b238fc1461035d5780637c1030781461037b5780638456cb591461039957806391d14854146103a3578063994f26ad146103d35761018e565b806336568abe1161014b5780633f4ba83a116101255780633f4ba83a146102df5780633f5a7ce0146102e95780634229c35e146103055780635c975abb146103215761018e565b806336568abe1461028b5780633bbed4a0146102a75780633ef3af4c146102c35761018e565b806301ffc9a71461019357806306e07944146101c3578063248a9ca3146101f357806327063d85146102235780632f2ff15d1461025357806333fbeb621461026f575b600080fd5b6101ad60048036038101906101a89190611aa5565b6104df565b6040516101ba9190611aed565b60405180910390f35b6101dd60048036038101906101d89190611b3e565b610559565b6040516101ea9190611b7a565b60405180910390f35b61020d60048036038101906102089190611bcb565b610571565b60405161021a9190611c07565b60405180910390f35b61023d60048036038101906102389190611c80565b610590565b60405161024a9190611b7a565b60405180910390f35b61026d60048036038101906102689190611cd3565b6105a6565b005b61028960048036038101906102849190611d13565b6105c8565b005b6102a560048036038101906102a09190611cd3565b6106e9565b005b6102c160048036038101906102bc9190611d13565b610764565b005b6102dd60048036038101906102d89190611b3e565b610816565b005b6102e76108c5565b005b61030360048036038101906102fe9190611d40565b6108fa565b005b61031f600480360381019061031a9190611d40565b610979565b005b6103296109f8565b6040516103369190611aed565b60405180910390f35b610347610a0f565b6040516103549190611d8f565b60405180910390f35b610365610a35565b6040516103729190611c07565b60405180910390f35b610383610a59565b6040516103909190611b7a565b60405180910390f35b6103a1610a5f565b005b6103bd60048036038101906103b89190611cd3565b610a94565b6040516103ca9190611aed565b60405180910390f35b6103ed60048036038101906103e89190611daa565b610afe565b005b6103f7610d1d565b6040516104049190611c07565b60405180910390f35b61042760048036038101906104229190611d13565b610d24565b6040516104349190611c07565b60405180910390f35b61045760048036038101906104529190611b3e565b610d3c565b6040516104649190611b7a565b60405180910390f35b61048760048036038101906104829190611cd3565b610d54565b005b6104a3600480360381019061049e9190611c80565b610d76565b005b6104bf60048036038101906104ba9190611d13565b610e45565b005b6104c9610f7d565b6040516104d69190611e49565b60405180910390f35b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610552575061055182610fa3565b5b9050919050565b60076020528060005260406000206000915090505481565b6000806000838152602001908152602001600020600101549050919050565b600061059d84848461100d565b90509392505050565b6105af82610571565b6105b881611388565b6105c2838361139c565b50505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756105f281611388565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610661576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065890611ec1565b60405180910390fd5b81600260016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167fb44cac8346035a97687cc6084879f7d9bd139771dfc3bf31a5301bedf0bdf70660405160405180910390a25050565b6106f161148d565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610755576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61075f8282611495565b505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177561078e81611388565b81600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167f9d900d71c28433348acb1bec780a061608a96b149370abce77fd54ba2d47940160405160405180910390a25050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177561084081611388565b60008211610883576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087a90611f2d565b60405180910390fd5b816003819055507f5d69959d28f91d396c7300d76c5ed3854a4bb332291e7e72e0e9093b8e1364c0826040516108b99190611b7a565b60405180910390a15050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756108ef81611388565b6108f7611587565b50565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177561092481611388565b816007600085815260200190815260200160002081905550827f059e6c5fb94276005f6011c02ffe594be180083486bae272a6f84f4c39667fe18360405161096c9190611b7a565b60405180910390a2505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756109a381611388565b816006600085815260200190815260200160002081905550827f53973a0aa9eb26609e2a6bb41f5235722e699b14e88f6eb24fc85c51167529d8836040516109eb9190611b7a565b60405180910390a2505050565b6000600260009054906101000a900460ff16905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b60035481565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610a8981611388565b610a916115ea565b50565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610b2881611388565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610b97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b8e90611f99565b60405180910390fd5b6000801b8203610bdc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bd390612005565b60405180910390fd5b60128373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4d919061205e565b60ff1614610c90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c87906120d7565b60405180910390fd5b81600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550818373ffffffffffffffffffffffffffffffffffffffff167fe6f2c806df4d61ecb96304200f584c14ad8572a4d28873ae7c636faf01645fdb60405160405180910390a3505050565b6000801b81565b60056020528060005260406000206000915090505481565b60066020528060005260406000206000915090505481565b610d5d82610571565b610d6681611388565b610d708383611495565b50505050565b610d7e61164d565b610d86611693565b6000610d9384848461100d565b9050610de433600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16838573ffffffffffffffffffffffffffffffffffffffff166116d4909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff16847f51bdb8be6d43e725856fe4b463037c16a6ddd72b1ac6cf1ea3763bb752aa7068858486604051610e2f939291906120f7565b60405180910390a350610e40611756565b505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610e6f81611388565b6000801b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403610ef3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eea9061217a565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090558173ffffffffffffffffffffffffffffffffffffffff167f4c910b69fe65a61f7531b9c5042b2329ca7179c77290aa7e2eb3afa3c8511fd360405160405180910390a25050565b600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600080600760008681526020019081526020016000205490506000600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600082116110ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a4906121e6565b60405180910390fd5b818510156110f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110e790612252565b60405180910390fd5b6000801b8103611135576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161112c9061217a565b60405180910390fd5b6000600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166396834ad3836040518263ffffffff1660e01b81526004016111929190611c07565b608060405180830381865afa1580156111af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d39190612442565b90506003548160600151426111e8919061249e565b1115611229576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112209061251e565b60405180910390fd5b60007314e5bacb5f98778aeefdd4f79dc8e007dd1586cf63b55522b28360000151846040015160126040518463ffffffff1660e01b815260040161126f93929190612597565b602060405180830381865af415801561128c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b091906125ce565b9050600081116112f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ec90612647565b60405180910390fd5b600081600660008b81526020019081526020016000205489670de0b6b3a76400006113209190612667565b61132a9190612667565b61133491906126d8565b905060008111611379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137090612755565b60405180910390fd5b80955050505050509392505050565b6113998161139461148d565b61175f565b50565b60006113a88383610a94565b61148257600160008085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555061141f61148d565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611487565b600090505b92915050565b600033905090565b60006114a18383610a94565b1561157c57600080600085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555061151961148d565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611581565b600090505b92915050565b61158f6117b0565b6000600260006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6115d361148d565b6040516115e09190611d8f565b60405180910390a1565b6115f2611693565b6001600260006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861163661148d565b6040516116439190611d8f565b60405180910390a1565b600260015403611689576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600181905550565b61169b6109f8565b156116d2576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b611750848573ffffffffffffffffffffffffffffffffffffffff166323b872dd86868660405160240161170993929190612775565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506117f0565b50505050565b60018081905550565b6117698282610a94565b6117ac5780826040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016117a39291906127ac565b60405180910390fd5b5050565b6117b86109f8565b6117ee576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b600061181b828473ffffffffffffffffffffffffffffffffffffffff1661188790919063ffffffff16565b9050600081511415801561184057508080602001905181019061183e9190612801565b155b1561188257826040517f5274afe70000000000000000000000000000000000000000000000000000000081526004016118799190611d8f565b60405180910390fd5b505050565b60606118958383600061189d565b905092915050565b6060814710156118e457306040517fcd7860590000000000000000000000000000000000000000000000000000000081526004016118db9190611d8f565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16848660405161190d919061289f565b60006040518083038185875af1925050503d806000811461194a576040519150601f19603f3d011682016040523d82523d6000602084013e61194f565b606091505b509150915061195f86838361196a565b925050509392505050565b60608261197f5761197a826119f9565b6119f1565b600082511480156119a7575060008473ffffffffffffffffffffffffffffffffffffffff163b145b156119e957836040517f9996b3150000000000000000000000000000000000000000000000000000000081526004016119e09190611d8f565b60405180910390fd5b8190506119f2565b5b9392505050565b600081511115611a0c5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000604051905090565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611a8281611a4d565b8114611a8d57600080fd5b50565b600081359050611a9f81611a79565b92915050565b600060208284031215611abb57611aba611a48565b5b6000611ac984828501611a90565b91505092915050565b60008115159050919050565b611ae781611ad2565b82525050565b6000602082019050611b026000830184611ade565b92915050565b6000819050919050565b611b1b81611b08565b8114611b2657600080fd5b50565b600081359050611b3881611b12565b92915050565b600060208284031215611b5457611b53611a48565b5b6000611b6284828501611b29565b91505092915050565b611b7481611b08565b82525050565b6000602082019050611b8f6000830184611b6b565b92915050565b6000819050919050565b611ba881611b95565b8114611bb357600080fd5b50565b600081359050611bc581611b9f565b92915050565b600060208284031215611be157611be0611a48565b5b6000611bef84828501611bb6565b91505092915050565b611c0181611b95565b82525050565b6000602082019050611c1c6000830184611bf8565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611c4d82611c22565b9050919050565b611c5d81611c42565b8114611c6857600080fd5b50565b600081359050611c7a81611c54565b92915050565b600080600060608486031215611c9957611c98611a48565b5b6000611ca786828701611b29565b9350506020611cb886828701611b29565b9250506040611cc986828701611c6b565b9150509250925092565b60008060408385031215611cea57611ce9611a48565b5b6000611cf885828601611bb6565b9250506020611d0985828601611c6b565b9150509250929050565b600060208284031215611d2957611d28611a48565b5b6000611d3784828501611c6b565b91505092915050565b60008060408385031215611d5757611d56611a48565b5b6000611d6585828601611b29565b9250506020611d7685828601611b29565b9150509250929050565b611d8981611c42565b82525050565b6000602082019050611da46000830184611d80565b92915050565b60008060408385031215611dc157611dc0611a48565b5b6000611dcf85828601611c6b565b9250506020611de085828601611bb6565b9150509250929050565b6000819050919050565b6000611e0f611e0a611e0584611c22565b611dea565b611c22565b9050919050565b6000611e2182611df4565b9050919050565b6000611e3382611e16565b9050919050565b611e4381611e28565b82525050565b6000602082019050611e5e6000830184611e3a565b92915050565b600082825260208201905092915050565b7f696e76616c696450797468436f6e747261637400000000000000000000000000600082015250565b6000611eab601383611e64565b9150611eb682611e75565b602082019050919050565b60006020820190508181036000830152611eda81611e9e565b9050919050565b7f696e76616c696445787069727900000000000000000000000000000000000000600082015250565b6000611f17600d83611e64565b9150611f2282611ee1565b602082019050919050565b60006020820190508181036000830152611f4681611f0a565b9050919050565b7f696e76616c6964546f6b656e0000000000000000000000000000000000000000600082015250565b6000611f83600c83611e64565b9150611f8e82611f4d565b602082019050919050565b60006020820190508181036000830152611fb281611f76565b9050919050565b7f696e76616c696450726963654f7261636c654964000000000000000000000000600082015250565b6000611fef601483611e64565b9150611ffa82611fb9565b602082019050919050565b6000602082019050818103600083015261201e81611fe2565b9050919050565b600060ff82169050919050565b61203b81612025565b811461204657600080fd5b50565b60008151905061205881612032565b92915050565b60006020828403121561207457612073611a48565b5b600061208284828501612049565b91505092915050565b7f696e76616c6964546f6b656e446563696d616c73000000000000000000000000600082015250565b60006120c1601483611e64565b91506120cc8261208b565b602082019050919050565b600060208201905081810360008301526120f0816120b4565b9050919050565b600060608201905061210c6000830186611b6b565b6121196020830185611b6b565b6121266040830184611d80565b949350505050565b7f746f6b656e556e61636365707461626c65000000000000000000000000000000600082015250565b6000612164601183611e64565b915061216f8261212e565b602082019050919050565b6000602082019050818103600083015261219381612157565b9050919050565b7f696e76616c69644974656d496400000000000000000000000000000000000000600082015250565b60006121d0600d83611e64565b91506121db8261219a565b602082019050919050565b600060208201905081810360008301526121ff816121c3565b9050919050565b7f696e73756666696369656e745175616e74697479000000000000000000000000600082015250565b600061223c601483611e64565b915061224782612206565b602082019050919050565b6000602082019050818103600083015261226b8161222f565b9050919050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6122c082612277565b810181811067ffffffffffffffff821117156122df576122de612288565b5b80604052505050565b60006122f2611a3e565b90506122fe82826122b7565b919050565b60008160070b9050919050565b61231981612303565b811461232457600080fd5b50565b60008151905061233681612310565b92915050565b600067ffffffffffffffff82169050919050565b6123598161233c565b811461236457600080fd5b50565b60008151905061237681612350565b92915050565b60008160030b9050919050565b6123928161237c565b811461239d57600080fd5b50565b6000815190506123af81612389565b92915050565b6000815190506123c481611b12565b92915050565b6000608082840312156123e0576123df612272565b5b6123ea60806122e8565b905060006123fa84828501612327565b600083015250602061240e84828501612367565b6020830152506040612422848285016123a0565b6040830152506060612436848285016123b5565b60608301525092915050565b60006080828403121561245857612457611a48565b5b6000612466848285016123ca565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006124a982611b08565b91506124b483611b08565b92508282039050818111156124cc576124cb61246f565b5b92915050565b7f7072696365466565644578706972656400000000000000000000000000000000600082015250565b6000612508601083611e64565b9150612513826124d2565b602082019050919050565b60006020820190508181036000830152612537816124fb565b9050919050565b61254781612303565b82525050565b6125568161237c565b82525050565b6000819050919050565b600061258161257c6125778461255c565b611dea565b612025565b9050919050565b61259181612566565b82525050565b60006060820190506125ac600083018661253e565b6125b9602083018561254d565b6125c66040830184612588565b949350505050565b6000602082840312156125e4576125e3611a48565b5b60006125f2848285016123b5565b91505092915050565b7f696e76616c6964546f6b656e5072696365000000000000000000000000000000600082015250565b6000612631601183611e64565b915061263c826125fb565b602082019050919050565b6000602082019050818103600083015261266081612624565b9050919050565b600061267282611b08565b915061267d83611b08565b925082820261268b81611b08565b915082820484148315176126a2576126a161246f565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006126e382611b08565b91506126ee83611b08565b9250826126fe576126fd6126a9565b5b828204905092915050565b7f696e76616c6964546f74616c5072696365000000000000000000000000000000600082015250565b600061273f601183611e64565b915061274a82612709565b602082019050919050565b6000602082019050818103600083015261276e81612732565b9050919050565b600060608201905061278a6000830186611d80565b6127976020830185611d80565b6127a46040830184611b6b565b949350505050565b60006040820190506127c16000830185611d80565b6127ce6020830184611bf8565b9392505050565b6127de81611ad2565b81146127e957600080fd5b50565b6000815190506127fb816127d5565b92915050565b60006020828403121561281757612816611a48565b5b6000612825848285016127ec565b91505092915050565b600081519050919050565b600081905092915050565b60005b83811015612862578082015181840152602081019050612847565b60008484015250505050565b60006128798261282e565b6128838185612839565b9350612893818560208601612844565b80840191505092915050565b60006128ab828461286e565b91508190509291505056fea2646970667358221220bd7d031d74d7b31576e112912ef75f998e486a8cef62aa0a41ab4e3c7708c85c64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000a2aa501b19aff244d90cc15a4cf739d2725b57290000000000000000000000002a83c210de4fb8beff00b032ab952d5b72ec8e1f0000000000000000000000008b50b3b19c3d8f66293339f7cfe473c76174612b0000000000000000000000008b50b3b19c3d8f66293339f7cfe473c76174612b
-----Decoded View---------------
Arg [0] : _pythContract (address): 0xA2aa501b19aff244D90cc15a4Cf739D2725B5729
Arg [1] : _recipient (address): 0x2a83C210De4Fb8BEff00b032AB952D5B72ec8E1F
Arg [2] : _admin (address): 0x8B50b3B19C3d8f66293339f7cfE473C76174612b
Arg [3] : _superAdmin (address): 0x8B50b3B19C3d8f66293339f7cfE473C76174612b
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000a2aa501b19aff244d90cc15a4cf739d2725b5729
Arg [1] : 0000000000000000000000002a83c210de4fb8beff00b032ab952d5b72ec8e1f
Arg [2] : 0000000000000000000000008b50b3b19c3d8f66293339f7cfe473c76174612b
Arg [3] : 0000000000000000000000008b50b3b19c3d8f66293339f7cfe473c76174612b
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.