Contract
0x8c44c0ab9a15bacad7a4b663a89593c406c6b4ea
9
Contract Overview
My Name Tag:
Not Available
TokenTracker:
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
DpxBonds
Compiler Version
v0.8.16+commit.07a7930e
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../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: * * ``` * 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}: * * ``` * 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. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ 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 override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(uint160(account), 20), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @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 override 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 override 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 override 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 `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @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 Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @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. * * _Available since v3.1._ */ 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 `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ 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 v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _owners[tokenId]; require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _owners[tokenId] != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _balances[owner] -= 1; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "./IERC721Enumerable.sol"; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` cannot be the zero address. * - `to` cannot be the zero address. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library Counters { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
//SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; // Libraries import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {Counters} from "@openzeppelin/contracts/utils/Counters.sol"; // Interfaces import {IERC20Metadata as IERC20} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {IERC721Enumerable} from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol"; // Contracts import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import {ERC721Enumerable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import {Pausable} from "./helpers/Pausable.sol"; import {ContractWhitelist} from "./helpers/ContractWhitelist.sol"; contract DpxBonds is ERC721, ERC721Enumerable, Pausable, AccessControl, ReentrancyGuard, ContractWhitelist { using Counters for Counters.Counter; using SafeERC20 for IERC20; /// @dev Bond NFTs minted for deposits struct BondsNft { uint256 epoch; uint256 issued; uint256 maturityTime; bool redeemed; } struct Addresses { address usdc; address dpx; address dopexBridgoorNFT; } /// @dev Token ID counter for positions Counters.Counter private _tokenIdCounter; /// @dev Addresses of external contracts Addresses public addresses; /// @dev Current epoch uint256 public currentEpoch; /// @dev Maturity duration uint256 public maturityDuration = 7 days; /// @dev DPX precision uint256 public immutable dpxPrecision; /// @dev bond price for epoch mapping(uint256 => uint256) public epochBondPrice; /// @dev deposit amount for epoch mapping(uint256 => uint256) public epochDepositPerNft; /// @dev Discount for the each epoch mapping(uint256 => uint256) public maxDepositsPerEpoch; /// @dev Expiry for the each epoch mapping(uint256 => uint256) public epochExpiry; /// @dev total amount of usdc deposited for each epoch mapping(uint256 => uint256) public totalEpochDeposits; /// @dev Amount of usdc deposited per NFT id for each epoch mapping(uint256 => mapping(uint256 => uint256)) public depositsPerNftId; /// @dev Returns nftsState struct for nft id mapping(uint256 => BondsNft) public nftsState; // ========================================== EVENTS ========================================== event LogBootstrapped( uint256 bondPrice, uint256 depositPerNft, uint256 maxEpochDeposits, uint256 expiry, uint256 epoch ); event LogMint(uint256[] usableNfts, uint256 amount, address sender); event LogRedeem(uint256 epoch, uint256 dpxRedeemed, address sender); event LogSetMaturityDuration(uint256 maturityDuration); constructor( string memory _name, string memory _symbol, Addresses memory _addresses ) ERC721(_name, _symbol) { addresses = _addresses; dpxPrecision = 10**IERC20(_addresses.dpx).decimals(); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); } // ========================================== ADMIN FUNCTIONS ========================================== /// @notice Pauses the vault for emergency cases /// @dev Can only be called by the admin function pause() external onlyRole(DEFAULT_ADMIN_ROLE) { _pause(); } /// @notice Unpauses the vault /// @dev Can only be called by the admin function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) { _unpause(); } /// @notice Add a contract to the whitelist /// @dev Can only be called by the admin /// @param _contract Address of the contract that needs to be added to the whitelist function addToContractWhitelist(address _contract) external onlyRole(DEFAULT_ADMIN_ROLE) { _addToContractWhitelist(_contract); } /// @notice Remove a contract to the whitelist /// @dev Can only be called by the admin /// @param _contract Address of the contract that needs to be removed from the whitelist function removeFromContractWhitelist(address _contract) external onlyRole(DEFAULT_ADMIN_ROLE) { _removeFromContractWhitelist(_contract); } /// @notice Set the maturity duration of a bond /// @dev Can only be called by the admin /// @param _maturityDuration the maturity duration function setMaturityDuration(uint256 _maturityDuration) external onlyRole(DEFAULT_ADMIN_ROLE) { maturityDuration = _maturityDuration; emit LogSetMaturityDuration(_maturityDuration); } /** * @dev Bootstrap a new epoch with a certain price * @param bondPrice bond price for new epoch in 1e6 precision * @param depositPerNft usdc deposit amount per NFT * @param maxEpochDeposits max USDC allowed to deposit per epoch, must be (maxEpochDeposits * 10 ** 6); * @param expiry expiry time for the epoch */ function bootstrap( uint256 bondPrice, uint256 depositPerNft, uint256 maxEpochDeposits, uint256 expiry ) external onlyRole(DEFAULT_ADMIN_ROLE) { _whenNotPaused(); uint256 nextEpoch = currentEpoch + 1; _validate(epochExpiry[currentEpoch] <= block.timestamp, 2); _validate(expiry > block.timestamp, 3); _validate(bondPrice > 0, 4); _validate(maxEpochDeposits > 0, 5); _validate(depositPerNft > 0, 6); IERC20(addresses.dpx).safeTransferFrom( msg.sender, address(this), (maxEpochDeposits * dpxPrecision) / bondPrice ); epochExpiry[nextEpoch] = expiry; epochDepositPerNft[nextEpoch] = depositPerNft; maxDepositsPerEpoch[nextEpoch] = maxEpochDeposits; epochBondPrice[nextEpoch] = bondPrice; currentEpoch = nextEpoch; emit LogBootstrapped( bondPrice, depositPerNft, maxEpochDeposits, expiry, nextEpoch ); } /// @notice Withdraw token balances from the contract (also used to emergency withdraw) /// @dev only callable by the owner /// @param tokens ERC20 tokens to withdraw /// @param transferNative should transfer native token function withdraw(address[] calldata tokens, bool transferNative) external onlyRole(DEFAULT_ADMIN_ROLE) { if (transferNative) payable(msg.sender).transfer(address(this).balance); IERC20 token; for (uint256 i; i < tokens.length; ) { token = IERC20(tokens[i]); token.safeTransfer(msg.sender, token.balanceOf(address(this))); unchecked { ++i; } } } // ========================================== CORE ========================================== /** * @dev Allows anyone to deposit erc20(usdc) during the epoch * @param usableNfts Amount of nfts available for deposit */ function mint(uint256[] memory usableNfts) external nonReentrant { _isEligibleSender(); _whenNotPaused(); _validate(epochExpiry[currentEpoch] > block.timestamp, 1); uint256 amount = usableNfts.length * epochDepositPerNft[currentEpoch]; IERC20 usdc = IERC20(addresses.usdc); IERC721Enumerable dopexBridgoorNFT = IERC721Enumerable( addresses.dopexBridgoorNFT ); _validate(usableNfts.length > 0, 7); _validate( ((totalEpochDeposits[currentEpoch] + amount) <= maxDepositsPerEpoch[currentEpoch]), 9 ); for (uint256 i; i < usableNfts.length; ) { _validate(dopexBridgoorNFT.ownerOf(usableNfts[i]) == msg.sender, 7); _validate(depositsPerNftId[currentEpoch][usableNfts[i]] == 0, 8); depositsPerNftId[currentEpoch][usableNfts[i]] = epochDepositPerNft[ currentEpoch ]; uint256 mintedBondsNftId = _mint(msg.sender); nftsState[mintedBondsNftId] = BondsNft( currentEpoch, block.timestamp, (block.timestamp + maturityDuration), false ); unchecked { ++i; } } totalEpochDeposits[currentEpoch] += amount; usdc.safeTransferFrom(msg.sender, address(this), amount); emit LogMint(usableNfts, amount, msg.sender); } /** * @dev Mints bonds nft for deposit * @param to address to deposit on behalf of */ function _mint(address to) internal returns (uint256) { uint256 tokenId = _tokenIdCounter.current(); _tokenIdCounter.increment(); _safeMint(to, tokenId); return tokenId; } /** * @dev Redeems the bonds a user has * @param epoch epoch to redeem from */ function redeem(uint256 epoch) external nonReentrant { _isEligibleSender(); _whenNotPaused(); uint256[] memory redeemableBonds = getRedeemableBonds( msg.sender, epoch ); IERC20 dpx = IERC20(addresses.dpx); _validate(redeemableBonds.length > 0, 10); uint256 bondPrice = epochBondPrice[epoch]; // 1e6 precision uint256 dpxRedeemed; for (uint256 i; i < redeemableBonds.length; ) { nftsState[redeemableBonds[i]].redeemed = true; dpxRedeemed += (epochDepositPerNft[epoch] * dpxPrecision) / bondPrice; _burn(redeemableBonds[i]); unchecked { ++i; } } dpx.safeTransfer(msg.sender, dpxRedeemed); emit LogRedeem(epoch, dpxRedeemed, msg.sender); } // ========================================== VIEWS/GETTERS ========================================== /** * @dev Returns an array of bond ids that were not redeemed for a selected epoch. * @param user address of the user * @param epoch epoch * @return array of bonds NFT ids */ function getRedeemableBonds(address user, uint256 epoch) public view returns (uint256[] memory) { uint256 count; for (uint256 i; i < balanceOf(user); ) { uint256 nftId = tokenOfOwnerByIndex(user, i); if ( !nftsState[nftId].redeemed && nftsState[nftId].epoch == epoch && nftsState[nftId].maturityTime <= block.timestamp ) { count++; } unchecked { ++i; } } uint256[] memory withdrawableNftsForSelectedEpoch = new uint256[]( count ); count = 0; for (uint256 i = 0; i < balanceOf(user); ) { uint256 nftId = tokenOfOwnerByIndex(user, i); if ( !nftsState[nftId].redeemed && nftsState[nftId].epoch == epoch && nftsState[nftId].maturityTime <= block.timestamp ) { withdrawableNftsForSelectedEpoch[count++] = nftId; } unchecked { i++; } } return withdrawableNftsForSelectedEpoch; } /** * @dev Returns an array of dopexBridgoorNFT ids that were not already used for deposits in the current epoch * @param user user address * @return usableNfts */ function getUsableNfts(address user) external view returns (uint256[] memory) { uint256 count; IERC721Enumerable dopexBridgoorNFT = IERC721Enumerable( addresses.dopexBridgoorNFT ); for (uint256 i; i < dopexBridgoorNFT.balanceOf(user); ) { if ( getDepositsPerNftIndex(user, i) < epochDepositPerNft[currentEpoch] ) { count++; } unchecked { ++i; } } uint256[] memory usableNfts = new uint256[](count); count = 0; for (uint256 i; i < dopexBridgoorNFT.balanceOf(user); ) { if ( getDepositsPerNftIndex(user, i) < epochDepositPerNft[currentEpoch] ) { usableNfts[count++] = dopexBridgoorNFT.tokenOfOwnerByIndex( user, i ); } unchecked { ++i; } } return usableNfts; } /** * @dev Checks how much USDC was deposited per NFT by the user * @param user address of the user * @param index index of the NFT * @return deposit usdc deposited for NFT in current epoch */ function getDepositsPerNftIndex(address user, uint256 index) public view returns (uint256) { return depositsPerNftId[currentEpoch][ IERC721Enumerable(addresses.dopexBridgoorNFT) .tokenOfOwnerByIndex(user, index) ]; } /// @notice Function override required by solidity function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal override(ERC721, ERC721Enumerable) { super._beforeTokenTransfer(from, to, tokenId); } /// @notice Function override required by solidity function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC721Enumerable, AccessControl) returns (bool) { return super.supportsInterface(interfaceId); } /** * @dev Function to validate a condition and revert with a custom error * @param condition error condition * @param errorId the error ID */ function _validate(bool condition, uint256 errorId) internal pure { if (!condition) { revert E(errorId); } } error E(uint256); } /* ERROS: 1: Epoch not expired 2: Cannot bootstrap before current epoch's expiry 3: Expiry must be in the future 4: Bond price cannot be zero 5: maxEpochDeposits can not be zero 6: Deposit per nft not set 7: Sender does not own NFT 8: NFT already used for this epoch 9: User doesn't have a deposit 10: User doesn't have eligible bonds */
//SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; /// @title ContractWhitelist /// @author witherblock /// @notice A helper contract that lets you add a list of whitelisted contracts that should be able to interact with restricited functions abstract contract ContractWhitelist { /// @dev contract => whitelisted or not mapping(address => bool) public whitelistedContracts; /*==== SETTERS ====*/ /// @dev add to the contract whitelist /// @param _contract the address of the contract to add to the contract whitelist function _addToContractWhitelist(address _contract) internal { require(isContract(_contract), "Address must be a contract"); require( !whitelistedContracts[_contract], "Contract already whitelisted" ); whitelistedContracts[_contract] = true; emit AddToContractWhitelist(_contract); } /// @dev remove from the contract whitelist /// @param _contract the address of the contract to remove from the contract whitelist function _removeFromContractWhitelist(address _contract) internal { require(whitelistedContracts[_contract], "Contract not whitelisted"); whitelistedContracts[_contract] = false; emit RemoveFromContractWhitelist(_contract); } // modifier is eligible sender modifier function _isEligibleSender() internal view { // the below condition checks whether the caller is a contract or not if (msg.sender != tx.origin) require( whitelistedContracts[msg.sender], "Contract must be whitelisted" ); } /*==== VIEWS ====*/ /// @dev checks for contract or eoa addresses /// @param addr the address to check /// @return bool whether the passed address is a contract address function isContract(address addr) public view returns (bool) { uint256 size; assembly { size := extcodesize(addr) } return size > 0; } /*==== EVENTS ====*/ event AddToContractWhitelist(address indexed _contract); event RemoveFromContractWhitelist(address indexed _contract); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; /// @title Lighter version of the Openzeppelin Pausable contract /// @author witherblock /// @notice Helps pause a contract to block the execution of selected functions /// @dev Difference from the Openzeppelin version is changing the modifiers to internal fns and requires to reverts abstract contract Pausable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Internal function to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ function _whenNotPaused() internal view { if (paused()) revert ContractPaused(); } /** * @dev Internal function to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ function _whenPaused() internal view { if (!paused()) revert ContractNotPaused(); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual { _whenNotPaused(); _paused = true; emit Paused(msg.sender); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual { _whenPaused(); _paused = false; emit Unpaused(msg.sender); } error ContractPaused(); error ContractNotPaused(); }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"components":[{"internalType":"address","name":"usdc","type":"address"},{"internalType":"address","name":"dpx","type":"address"},{"internalType":"address","name":"dopexBridgoorNFT","type":"address"}],"internalType":"struct DpxBonds.Addresses","name":"_addresses","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ContractNotPaused","type":"error"},{"inputs":[],"name":"ContractPaused","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"E","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_contract","type":"address"}],"name":"AddToContractWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"bondPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositPerNft","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxEpochDeposits","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expiry","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"LogBootstrapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"usableNfts","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"LogMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dpxRedeemed","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"LogRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maturityDuration","type":"uint256"}],"name":"LogSetMaturityDuration","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_contract","type":"address"}],"name":"RemoveFromContractWhitelist","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":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"}],"name":"addToContractWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"addresses","outputs":[{"internalType":"address","name":"usdc","type":"address"},{"internalType":"address","name":"dpx","type":"address"},{"internalType":"address","name":"dopexBridgoorNFT","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bondPrice","type":"uint256"},{"internalType":"uint256","name":"depositPerNft","type":"uint256"},{"internalType":"uint256","name":"maxEpochDeposits","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"name":"bootstrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"depositsPerNftId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dpxPrecision","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"epochBondPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"epochDepositPerNft","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"epochExpiry","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getDepositsPerNftIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"getRedeemableBonds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUsableNfts","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":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maturityDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"maxDepositsPerEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"usableNfts","type":"uint256[]"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nftsState","outputs":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"issued","type":"uint256"},{"internalType":"uint256","name":"maturityTime","type":"uint256"},{"internalType":"bool","name":"redeemed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"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":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"}],"name":"removeFromContractWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","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":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maturityDuration","type":"uint256"}],"name":"setMaturityDuration","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":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalEpochDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistedContracts","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"bool","name":"transferNative","type":"bool"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a060405262093a806013553480156200001857600080fd5b5060405162003d3038038062003d308339810160408190526200003b91620002f4565b828260006200004b838262000463565b5060016200005a828262000463565b5050600a805460ff19169055506001600c558051600f80546001600160a01b039283166001600160a01b03199182161790915560208084015160108054918516918416821790556040808601516011805491909616941693909317909355815163313ce56760e01b8152915163313ce5679260048082019392918290030181865afa158015620000ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200011491906200052f565b6200012190600a6200066e565b608052620001316000336200013a565b5050506200067f565b6200014682826200014a565b5050565b620001568282620001d4565b62000146576000828152600b602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620001903390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152600b602090815260408083206001600160a01b038516845290915290205460ff165b92915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171562000242576200024262000201565b604052919050565b600082601f8301126200025c57600080fd5b81516001600160401b0381111562000278576200027862000201565b60206200028e601f8301601f1916820162000217565b8281528582848701011115620002a357600080fd5b60005b83811015620002c3578581018301518282018401528201620002a6565b506000928101909101919091529392505050565b80516001600160a01b0381168114620002ef57600080fd5b919050565b600080600083850360a08112156200030b57600080fd5b84516001600160401b03808211156200032357600080fd5b62000331888389016200024a565b955060208701519150808211156200034857600080fd5b62000356888389016200024a565b94506060603f19840112156200036b57600080fd5b604051925060608301915082821081831117156200038d576200038d62000201565b508060405250620003a160408601620002d7565b8152620003b160608601620002d7565b6020820152620003c460808601620002d7565b6040820152809150509250925092565b600181811c90821680620003e957607f821691505b6020821081036200040a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200045e57600081815260208120601f850160051c81016020861015620004395750805b601f850160051c820191505b818110156200045a5782815560010162000445565b5050505b505050565b81516001600160401b038111156200047f576200047f62000201565b6200049781620004908454620003d4565b8462000410565b602080601f831160018114620004cf5760008415620004b65750858301515b600019600386901b1c1916600185901b1785556200045a565b600085815260208120601f198616915b828110156200050057888601518255948401946001909101908401620004df565b50858210156200051f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156200054257600080fd5b815160ff811681146200055457600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b80851115620005b25781600019048211156200059657620005966200055b565b80851615620005a457918102915b93841c939080029062000576565b509250929050565b600082620005cb57506001620001fb565b81620005da57506000620001fb565b8160018114620005f35760028114620005fe576200061e565b6001915050620001fb565b60ff8411156200061257620006126200055b565b50506001821b620001fb565b5060208310610133831016604e8410600b841016171562000643575081810a620001fb565b6200064f838362000571565b80600019048211156200066657620006666200055b565b029392505050565b60006200055460ff841683620005ba565b608051613687620006a9600039600081816105bc01528181611200015261143301526136876000f3fe608060405234801561001057600080fd5b50600436106102a05760003560e01c80637b08260311610167578063c6436314116100ce578063da0321cd11610087578063da0321cd1461064a578063db006a7514610694578063e985e9c5146106a7578063f40c7f73146106e3578063f8e93ef9146106f6578063fd77e5231461070957600080fd5b8063c6436314146105b7578063c87b56dd146105de578063cc8d8a16146105f1578063d547741f14610604578063d739ac2914610617578063d7e151311461062a57600080fd5b8063a217fddf11610120578063a217fddf14610543578063a22cb4651461054b578063acc3a0061461055e578063b88d4fde14610571578063b968685814610584578063c3d9ed39146105a457600080fd5b80637b082603146104cd5780638232e06e146104e05780638456cb591461050057806391d148541461050857806395d89b411461051b57806399a35e751461052357600080fd5b8063300bbf3a1161020b5780635c975abb116101c45780635c975abb146104555780636352211e14610460578063654256241461047357806370a082311461048657806376671808146104995780637af2c27a146104a257600080fd5b8063300bbf3a146103d157806336568abe146103f1578063391feebb146104045780633f4ba83a1461042757806342842e0e1461042f5780634f6ccce71461044257600080fd5b806318160ddd1161025d57806318160ddd1461034d5780632380d09c1461035557806323b872dd14610375578063248a9ca3146103885780632f2ff15d146103ab5780632f745c59146103be57600080fd5b806301ffc9a7146102a5578063063513b7146102cd57806306fdde03146102e4578063081812fc146102f9578063095ea7b3146103245780631627905514610339575b600080fd5b6102b86102b3366004612e37565b610763565b60405190151581526020015b60405180910390f35b6102d660135481565b6040519081526020016102c4565b6102ec610774565b6040516102c49190612ea4565b61030c610307366004612eb7565b610806565b6040516001600160a01b0390911681526020016102c4565b610337610332366004612ee5565b61082d565b005b6102b8610347366004612f11565b3b151590565b6008546102d6565b610368610363366004612f11565b610947565b6040516102c49190612f69565b610337610383366004612f7c565b610b92565b6102d6610396366004612eb7565b6000908152600b602052604090206001015490565b6103376103b9366004612fbd565b610bc3565b6102d66103cc366004612ee5565b610be8565b6102d66103df366004612eb7565b60156020526000908152604090205481565b6103376103ff366004612fbd565b610c7e565b6102b8610412366004612f11565b600d6020526000908152604090205460ff1681565b610337610cfc565b61033761043d366004612f7c565b610d12565b6102d6610450366004612eb7565b610d2d565b600a5460ff166102b8565b61030c61046e366004612eb7565b610dc0565b610337610481366004612ffb565b610e20565b6102d6610494366004612f11565b610f24565b6102d660125481565b6102d66104b0366004613081565b601960209081526000928352604080842090915290825290205481565b6102d66104db366004612ee5565b610faa565b6102d66104ee366004612eb7565b60176020526000908152604090205481565b610337611049565b6102b8610516366004612fbd565b61105c565b6102ec611087565b6102d6610531366004612eb7565b60146020526000908152604090205481565b6102d6600081565b6103376105593660046130a3565b611096565b61033761056c366004612f11565b6110a1565b61033761057f366004613118565b6110b5565b6102d6610592366004612eb7565b60166020526000908152604090205481565b6103376105b2366004612f11565b6110ed565b6102d67f000000000000000000000000000000000000000000000000000000000000000081565b6102ec6105ec366004612eb7565b611101565b6103376105ff3660046131dc565b611175565b610337610612366004612fbd565b6112cf565b610337610625366004612eb7565b6112f4565b6102d6610638366004612eb7565b60186020526000908152604090205481565b600f5460105460115461066a926001600160a01b03908116928116911683565b604080516001600160a01b03948516815292841660208401529216918101919091526060016102c4565b6103376106a2366004612eb7565b61133b565b6102b86106b536600461320e565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6103686106f1366004612ee5565b611510565b61033761070436600461323c565b611690565b610741610717366004612eb7565b601a6020526000908152604090208054600182015460028301546003909301549192909160ff1684565b60408051948552602085019390935291830152151560608201526080016102c4565b600061076e826119e9565b92915050565b606060008054610783906132e2565b80601f01602080910402602001604051908101604052809291908181526020018280546107af906132e2565b80156107fc5780601f106107d1576101008083540402835291602001916107fc565b820191906000526020600020905b8154815290600101906020018083116107df57829003601f168201915b5050505050905090565b600061081182611a0e565b506000908152600460205260409020546001600160a01b031690565b600061083882610dc0565b9050806001600160a01b0316836001600160a01b0316036108aa5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b03821614806108c657506108c681336106b5565b6109385760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c000060648201526084016108a1565b6109428383611a6d565b505050565b6011546060906000906001600160a01b0316815b6040516370a0823160e01b81526001600160a01b0386811660048301528316906370a0823190602401602060405180830381865afa1580156109a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c5919061331c565b811015610a04576012546000908152601560205260409020546109e88683610faa565b10156109fc57826109f88161334b565b9350505b60010161095b565b5060008267ffffffffffffffff811115610a2057610a206130d1565b604051908082528060200260200182016040528015610a49578160200160208202803683370190505b5090506000925060005b6040516370a0823160e01b81526001600160a01b0387811660048301528416906370a0823190602401602060405180830381865afa158015610a99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610abd919061331c565b811015610b8957601254600090815260156020526040902054610ae08783610faa565b1015610b8157604051632f745c5960e01b81526001600160a01b03878116600483015260248201839052841690632f745c5990604401602060405180830381865afa158015610b33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b57919061331c565b8285610b628161334b565b965081518110610b7457610b74613364565b6020026020010181815250505b600101610a53565b50949350505050565b610b9c3382611adb565b610bb85760405162461bcd60e51b81526004016108a19061337a565b610942838383611b5a565b6000828152600b6020526040902060010154610bde81611d01565b6109428383611d0b565b6000610bf383610f24565b8210610c555760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b60648201526084016108a1565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6001600160a01b0381163314610cee5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084016108a1565b610cf88282611d91565b5050565b6000610d0781611d01565b610d0f611df8565b50565b610942838383604051806020016040528060008152506110b5565b6000610d3860085490565b8210610d9b5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b60648201526084016108a1565b60088281548110610dae57610dae613364565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b03168061076e5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016108a1565b6000610e2b81611d01565b8115610e5f5760405133904780156108fc02916000818181858888f19350505050158015610e5d573d6000803e3d6000fd5b505b6000805b84811015610f1c57858582818110610e7d57610e7d613364565b9050602002016020810190610e929190612f11565b6040516370a0823160e01b8152306004820152909250610f149033906001600160a01b038516906370a0823190602401602060405180830381865afa158015610edf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f03919061331c565b6001600160a01b0385169190611e40565b600101610e63565b505050505050565b60006001600160a01b038216610f8e5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b60648201526084016108a1565b506001600160a01b031660009081526003602052604090205490565b6012546000908152601960205260408082206011549151632f745c5960e01b81526001600160a01b03868116600483015260248201869052919284921690632f745c5990604401602060405180830381865afa15801561100e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611032919061331c565b815260200190815260200160002054905092915050565b600061105481611d01565b610d0f611ea3565b6000918252600b602090815260408084206001600160a01b0393909316845291905290205460ff1690565b606060018054610783906132e2565b610cf8338383611ee8565b60006110ac81611d01565b610cf882611fb6565b6110bf3383611adb565b6110db5760405162461bcd60e51b81526004016108a19061337a565b6110e7848484846120b9565b50505050565b60006110f881611d01565b610cf8826120ec565b606061110c82611a0e565b600061112360408051602081019091526000815290565b90506000815111611143576040518060200160405280600081525061116e565b8061114d8461219d565b60405160200161115e9291906133c8565b6040516020818303038152906040525b9392505050565b600061118081611d01565b61118861229e565b6000601254600161119991906133f7565b90506111be4260176000601254815260200190815260200160002054111560026122c4565b6111cb42841160036122c4565b6111d96000871160046122c4565b6111e76000851160056122c4565b6111f56000861160066122c4565b6112433330886112257f00000000000000000000000000000000000000000000000000000000000000008961340a565b61122f919061343f565b6010546001600160a01b03169291906122e4565b6000818152601760209081526040808320869055601582528083208890556016825280832087905560148252918290208890556012839055815188815290810187905290810185905260608101849052608081018290527fbae130e979ed478c5981210da2b1fb7bf90ca88a46716ceab66d15ef6d9b67319060a00160405180910390a1505050505050565b6000828152600b60205260409020600101546112ea81611d01565b6109428383611d91565b60006112ff81611d01565b60138290556040518281527f77f960de7a0a610e49ac93d38dfea163236e5fd2ad5a59fcddab91dd5d052cba9060200160405180910390a15050565b6002600c540361138d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108a1565b6002600c5561139a61231c565b6113a261229e565b60006113ae3383611510565b60105481519192506001600160a01b0316906113cd901515600a6122c4565b60008381526014602052604081205490805b84518110156114b0576001601a600087848151811061140057611400613364565b6020026020010151815260200190815260200160002060030160006101000a81548160ff021916908315150217905550827f00000000000000000000000000000000000000000000000000000000000000006015600089815260200190815260200160002054611470919061340a565b61147a919061343f565b61148490836133f7565b91506114a885828151811061149b5761149b613364565b6020026020010151612382565b6001016113df565b506114c56001600160a01b0384163383611e40565b6040805186815260208101839052338183015290517f87e03f67a265696ffd6176c73a76eaaff97261987acf81e39d84849e1b46e2109181900360600190a150506001600c55505050565b60606000805b61151f85610f24565b81101561159d5760006115328683610be8565b6000818152601a602052604090206003015490915060ff1615801561156457506000818152601a602052604090205485145b801561158157506000818152601a60205260409020600201544210155b1561159457826115908161334b565b9350505b50600101611516565b5060008167ffffffffffffffff8111156115b9576115b96130d1565b6040519080825280602002602001820160405280156115e2578160200160208202803683370190505b5090506000915060005b6115f586610f24565b811015610b895760006116088783610be8565b6000818152601a602052604090206003015490915060ff1615801561163a57506000818152601a602052604090205486145b801561165757506000818152601a60205260409020600201544210155b15611687578083856116688161334b565b96508151811061167a5761167a613364565b6020026020010181815250505b506001016115ec565b6002600c54036116e25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108a1565b6002600c556116ef61231c565b6116f761229e565b60125460009081526017602052604090205461171690421060016122c4565b6012546000908152601560205260408120548251611734919061340a565b600f5460115484519293506001600160a01b039182169291169061175b90151560076122c4565b60125460009081526016602090815260408083205460189092529091205461179291906117899086906133f7565b111560096122c4565b60005b845181101561196657611844336001600160a01b0316836001600160a01b0316636352211e8885815181106117cc576117cc613364565b60200260200101516040518263ffffffff1660e01b81526004016117f291815260200190565b602060405180830381865afa15801561180f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118339190613453565b6001600160a01b03161460076122c4565b611891601960006012548152602001908152602001600020600087848151811061187057611870613364565b602002602001015181526020019081526020016000205460001460086122c4565b601254600090815260156020908152604080832054601990925282208751919290918890859081106118c5576118c5613364565b602002602001015181526020019081526020016000208190555060006118ea33612429565b9050604051806080016040528060125481526020014281526020016013544261191391906133f7565b815260006020918201819052928352601a815260409283902082518155908201516001808301919091559282015160028201556060909101516003909101805460ff191691151591909117905501611795565b50601254600090815260186020526040812080548592906119889084906133f7565b909155506119a390506001600160a01b0383163330866122e4565b7f5e28fcd61e0c36cb5b96cee8dd7b013059048ba6aa8e51b9c0b31ebda648d4698484336040516119d693929190613470565b60405180910390a150506001600c555050565b60006001600160e01b03198216637965db0b60e01b148061076e575061076e8261244f565b6000818152600260205260409020546001600160a01b0316610d0f5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016108a1565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190611aa282610dc0565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080611ae783610dc0565b9050806001600160a01b0316846001600160a01b03161480611b2e57506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b80611b525750836001600160a01b0316611b4784610806565b6001600160a01b0316145b949350505050565b826001600160a01b0316611b6d82610dc0565b6001600160a01b031614611bd15760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b60648201526084016108a1565b6001600160a01b038216611c335760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016108a1565b611c3e838383612474565b611c49600082611a6d565b6001600160a01b0383166000908152600360205260408120805460019290611c729084906134a3565b90915550506001600160a01b0382166000908152600360205260408120805460019290611ca09084906133f7565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b610d0f813361247f565b611d15828261105c565b610cf8576000828152600b602090815260408083206001600160a01b03851684529091529020805460ff19166001179055611d4d3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b611d9b828261105c565b15610cf8576000828152600b602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b611e006124e3565b600a805460ff191690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6040516001600160a01b03831660248201526044810182905261094290849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612506565b611eab61229e565b600a805460ff191660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001611e36565b816001600160a01b0316836001600160a01b031603611f495760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016108a1565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b803b6120045760405162461bcd60e51b815260206004820152601a60248201527f41646472657373206d757374206265206120636f6e747261637400000000000060448201526064016108a1565b6001600160a01b0381166000908152600d602052604090205460ff161561206d5760405162461bcd60e51b815260206004820152601c60248201527f436f6e747261637420616c72656164792077686974656c69737465640000000060448201526064016108a1565b6001600160a01b0381166000818152600d6020526040808220805460ff19166001179055517ffbd3cde7ff522a917e485c8ed2a6e87590887ab399f5ac312307903f498543079190a250565b6120c4848484611b5a565b6120d0848484846125d8565b6110e75760405162461bcd60e51b81526004016108a1906134b6565b6001600160a01b0381166000908152600d602052604090205460ff166121545760405162461bcd60e51b815260206004820152601860248201527f436f6e7472616374206e6f742077686974656c6973746564000000000000000060448201526064016108a1565b6001600160a01b0381166000818152600d6020526040808220805460ff19169055517f8e81447740597754af5db3e176253a36f7981a9549f48ace3f0cb233913f9d859190a250565b6060816000036121c45750506040805180820190915260018152600360fc1b602082015290565b8160005b81156121ee57806121d88161334b565b91506121e79050600a8361343f565b91506121c8565b60008167ffffffffffffffff811115612209576122096130d1565b6040519080825280601f01601f191660200182016040528015612233576020820181803683370190505b5090505b8415611b52576122486001836134a3565b9150612255600a86613508565b6122609060306133f7565b60f81b81838151811061227557612275613364565b60200101906001600160f81b031916908160001a905350612297600a8661343f565b9450612237565b600a5460ff16156122c25760405163ab35696f60e01b815260040160405180910390fd5b565b81610cf857604051622ff06760e01b8152600481018290526024016108a1565b6040516001600160a01b03808516602483015283166044820152606481018290526110e79085906323b872dd60e01b90608401611e6c565b3332146122c257336000908152600d602052604090205460ff166122c25760405162461bcd60e51b815260206004820152601c60248201527f436f6e7472616374206d7573742062652077686974656c69737465640000000060448201526064016108a1565b600061238d82610dc0565b905061239b81600084612474565b6123a6600083611a6d565b6001600160a01b03811660009081526003602052604081208054600192906123cf9084906134a3565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b600080612435600e5490565b9050612445600e80546001019055565b61076e83826126d9565b60006001600160e01b0319821663780e9d6360e01b148061076e575061076e826126f3565b610942838383612743565b612489828261105c565b610cf8576124a1816001600160a01b031660146127fb565b6124ac8360206127fb565b6040516020016124bd92919061351c565b60408051601f198184030181529082905262461bcd60e51b82526108a191600401612ea4565b600a5460ff166122c25760405163dcdde9dd60e01b815260040160405180910390fd5b600061255b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166129979092919063ffffffff16565b80519091501561094257808060200190518101906125799190613591565b6109425760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108a1565b60006001600160a01b0384163b156126ce57604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061261c9033908990889088906004016135ae565b6020604051808303816000875af1925050508015612657575060408051601f3d908101601f19168201909252612654918101906135eb565b60015b6126b4573d808015612685576040519150601f19603f3d011682016040523d82523d6000602084013e61268a565b606091505b5080516000036126ac5760405162461bcd60e51b81526004016108a1906134b6565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611b52565b506001949350505050565b610cf88282604051806020016040528060008152506129a6565b60006001600160e01b031982166380ac58cd60e01b148061272457506001600160e01b03198216635b5e139f60e01b145b8061076e57506301ffc9a760e01b6001600160e01b031983161461076e565b6001600160a01b03831661279e5761279981600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6127c1565b816001600160a01b0316836001600160a01b0316146127c1576127c183826129d9565b6001600160a01b0382166127d85761094281612a76565b826001600160a01b0316826001600160a01b031614610942576109428282612b25565b6060600061280a83600261340a565b6128159060026133f7565b67ffffffffffffffff81111561282d5761282d6130d1565b6040519080825280601f01601f191660200182016040528015612857576020820181803683370190505b509050600360fc1b8160008151811061287257612872613364565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106128a1576128a1613364565b60200101906001600160f81b031916908160001a90535060006128c584600261340a565b6128d09060016133f7565b90505b6001811115612948576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061290457612904613364565b1a60f81b82828151811061291a5761291a613364565b60200101906001600160f81b031916908160001a90535060049490941c9361294181613608565b90506128d3565b50831561116e5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016108a1565b6060611b528484600085612b69565b6129b08383612c9a565b6129bd60008484846125d8565b6109425760405162461bcd60e51b81526004016108a1906134b6565b600060016129e684610f24565b6129f091906134a3565b600083815260076020526040902054909150808214612a43576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090612a88906001906134a3565b60008381526009602052604081205460088054939450909284908110612ab057612ab0613364565b906000526020600020015490508060088381548110612ad157612ad1613364565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480612b0957612b0961361f565b6001900381819060005260206000200160009055905550505050565b6000612b3083610f24565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b606082471015612bca5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016108a1565b6001600160a01b0385163b612c215760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108a1565b600080866001600160a01b03168587604051612c3d9190613635565b60006040518083038185875af1925050503d8060008114612c7a576040519150601f19603f3d011682016040523d82523d6000602084013e612c7f565b606091505b5091509150612c8f828286612de8565b979650505050505050565b6001600160a01b038216612cf05760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016108a1565b6000818152600260205260409020546001600160a01b031615612d555760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016108a1565b612d6160008383612474565b6001600160a01b0382166000908152600360205260408120805460019290612d8a9084906133f7565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60608315612df757508161116e565b825115612e075782518084602001fd5b8160405162461bcd60e51b81526004016108a19190612ea4565b6001600160e01b031981168114610d0f57600080fd5b600060208284031215612e4957600080fd5b813561116e81612e21565b60005b83811015612e6f578181015183820152602001612e57565b50506000910152565b60008151808452612e90816020860160208601612e54565b601f01601f19169290920160200192915050565b60208152600061116e6020830184612e78565b600060208284031215612ec957600080fd5b5035919050565b6001600160a01b0381168114610d0f57600080fd5b60008060408385031215612ef857600080fd5b8235612f0381612ed0565b946020939093013593505050565b600060208284031215612f2357600080fd5b813561116e81612ed0565b600081518084526020808501945080840160005b83811015612f5e57815187529582019590820190600101612f42565b509495945050505050565b60208152600061116e6020830184612f2e565b600080600060608486031215612f9157600080fd5b8335612f9c81612ed0565b92506020840135612fac81612ed0565b929592945050506040919091013590565b60008060408385031215612fd057600080fd5b823591506020830135612fe281612ed0565b809150509250929050565b8015158114610d0f57600080fd5b60008060006040848603121561301057600080fd5b833567ffffffffffffffff8082111561302857600080fd5b818601915086601f83011261303c57600080fd5b81358181111561304b57600080fd5b8760208260051b850101111561306057600080fd5b6020928301955093505084013561307681612fed565b809150509250925092565b6000806040838503121561309457600080fd5b50508035926020909101359150565b600080604083850312156130b657600080fd5b82356130c181612ed0565b91506020830135612fe281612fed565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613110576131106130d1565b604052919050565b6000806000806080858703121561312e57600080fd5b843561313981612ed0565b935060208581013561314a81612ed0565b935060408601359250606086013567ffffffffffffffff8082111561316e57600080fd5b818801915088601f83011261318257600080fd5b813581811115613194576131946130d1565b6131a6601f8201601f191685016130e7565b915080825289848285010111156131bc57600080fd5b808484018584013760008482840101525080935050505092959194509250565b600080600080608085870312156131f257600080fd5b5050823594602084013594506040840135936060013592509050565b6000806040838503121561322157600080fd5b823561322c81612ed0565b91506020830135612fe281612ed0565b6000602080838503121561324f57600080fd5b823567ffffffffffffffff8082111561326757600080fd5b818501915085601f83011261327b57600080fd5b81358181111561328d5761328d6130d1565b8060051b915061329e8483016130e7565b81815291830184019184810190888411156132b857600080fd5b938501935b838510156132d6578435825293850193908501906132bd565b98975050505050505050565b600181811c908216806132f657607f821691505b60208210810361331657634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561332e57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60006001820161335d5761335d613335565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b600083516133da818460208801612e54565b8351908301906133ee818360208801612e54565b01949350505050565b8082018082111561076e5761076e613335565b600081600019048311821515161561342457613424613335565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261344e5761344e613429565b500490565b60006020828403121561346557600080fd5b815161116e81612ed0565b6060815260006134836060830186612f2e565b6020830194909452506001600160a01b0391909116604090910152919050565b8181038181111561076e5761076e613335565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60008261351757613517613429565b500690565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351613554816017850160208801612e54565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351613585816028840160208801612e54565b01602801949350505050565b6000602082840312156135a357600080fd5b815161116e81612fed565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906135e190830184612e78565b9695505050505050565b6000602082840312156135fd57600080fd5b815161116e81612e21565b60008161361757613617613335565b506000190190565b634e487b7160e01b600052603160045260246000fd5b60008251613647818460208701612e54565b919091019291505056fea26469706673582212206138b132eacd7e5300f482ab3d805bcbefae7b46ba8f7f41c2acf99c2f6b8bde64736f6c6343000810003300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc80000000000000000000000006c2c06790b3e3e3c38e12ee22f8183b37a13ee550000000000000000000000004ee9fe9500e7c4fe849add9b14beec5ec5b7d955000000000000000000000000000000000000000000000000000000000000000944505820424f4e4453000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000094450582d424f4e44530000000000000000000000000000000000000000000000
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc80000000000000000000000006c2c06790b3e3e3c38e12ee22f8183b37a13ee550000000000000000000000004ee9fe9500e7c4fe849add9b14beec5ec5b7d955000000000000000000000000000000000000000000000000000000000000000944505820424f4e4453000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000094450582d424f4e44530000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): DPX BONDS
Arg [1] : _symbol (string): DPX-BONDS
Arg [2] : _addresses (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc8
Arg [3] : 0000000000000000000000006c2c06790b3e3e3c38e12ee22f8183b37a13ee55
Arg [4] : 0000000000000000000000004ee9fe9500e7c4fe849add9b14beec5ec5b7d955
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [6] : 44505820424f4e44530000000000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [8] : 4450582d424f4e44530000000000000000000000000000000000000000000000
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.