72 lines
54 KiB
JSON
72 lines
54 KiB
JSON
{
|
||
"language": "Solidity",
|
||
"sources": {
|
||
"@openzeppelin/contracts/access/Ownable.sol": {
|
||
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n"
|
||
},
|
||
"@openzeppelin/contracts/interfaces/draft-IERC6093.sol": {
|
||
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard ERC20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.\n */\ninterface IERC20Errors {\n /**\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param balance Current balance for the interacting account.\n * @param needed Minimum amount required to perform a transfer.\n */\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC20InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC20InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n * @param spender Address that may be allowed to operate on tokens without being their owner.\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\n * @param needed Minimum amount required to perform a transfer.\n */\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC20InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n * @param spender Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.\n */\ninterface IERC721Errors {\n /**\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.\n * Used in balance queries.\n * @param owner Address of the current owner of a token.\n */\n error ERC721InvalidOwner(address owner);\n\n /**\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\n * @param tokenId Identifier number of a token.\n */\n error ERC721NonexistentToken(uint256 tokenId);\n\n /**\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param tokenId Identifier number of a token.\n * @param owner Address of the current owner of a token.\n */\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC721InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC721InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n * @param tokenId Identifier number of a token.\n */\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC721InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.\n */\ninterface IERC1155Errors {\n /**\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param balance Current balance for the interacting account.\n * @param needed Minimum amount required to perform a transfer.\n * @param tokenId Identifier number of a token.\n */\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC1155InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC1155InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n * @param owner Address of the current owner of a token.\n */\n error ERC1155MissingApprovalForAll(address operator, address owner);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC1155InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC1155InvalidOperator(address operator);\n\n /**\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n * Used in batch transfers.\n * @param idsLength Length of the array of token identifiers\n * @param valuesLength Length of the array of token amounts\n */\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"
|
||
},
|
||
"@openzeppelin/contracts/token/ERC20/ERC20.sol": {
|
||
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC20Metadata} from \"./extensions/IERC20Metadata.sol\";\nimport {Context} from \"../../utils/Context.sol\";\nimport {IERC20Errors} from \"../../interfaces/draft-IERC6093.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n */\nabstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {\n mapping(address account => uint256) private _balances;\n\n mapping(address account => mapping(address spender => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `value`.\n */\n function transfer(address to, uint256 value) public virtual returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, value);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 value) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, value);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `value`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `value`.\n */\n function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, value);\n _transfer(from, to, value);\n return true;\n }\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead.\n */\n function _transfer(address from, address to, uint256 value) internal {\n if (from == address(0)) {\n revert ERC20InvalidSender(address(0));\n }\n if (to == address(0)) {\n revert ERC20InvalidReceiver(address(0));\n }\n _update(from, to, value);\n }\n\n /**\n * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\n * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\n * this function.\n *\n * Emits a {Transfer} event.\n */\n function _update(address from, address to, uint256 value) internal virtual {\n if (from == address(0)) {\n // Overflow check required: The rest of the code assumes that totalSupply never overflows\n _totalSupply += value;\n } else {\n uint256 fromBalance = _balances[from];\n if (fromBalance < value) {\n revert ERC20InsufficientBalance(from, fromBalance, value);\n }\n unchecked {\n // Overflow not possible: value <= fromBalance <= totalSupply.\n _balances[from] = fromBalance - value;\n }\n }\n\n if (to == address(0)) {\n unchecked {\n // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\n _totalSupply -= value;\n }\n } else {\n unchecked {\n // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\n _balances[to] += value;\n }\n }\n\n emit Transfer(from, to, value);\n }\n\n /**\n * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\n * Relies on the `_update` mechanism\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead.\n */\n function _mint(address account, uint256 value) internal {\n if (account == address(0)) {\n revert ERC20InvalidReceiver(address(0));\n }\n _update(address(0), account, value);\n }\n\n /**\n * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\n * Relies on the `_update` mechanism.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead\n */\n function _burn(address account, uint256 value) internal {\n if (account == address(0)) {\n revert ERC20InvalidSender(address(0));\n }\n _update(account, address(0), value);\n }\n\n /**\n * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n *\n * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n */\n function _approve(address owner, address spender, uint256 value) internal {\n _approve(owner, spender, value, true);\n }\n\n /**\n * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\n *\n * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\n * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any\n * `Approval` event during `transferFrom` operations.\n *\n * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to\n * true using the following override:\n * ```\n * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\n * super._approve(owner, spender, value, true);\n * }\n * ```\n *\n * Requirements are the same as {_approve}.\n */\n function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\n if (owner == address(0)) {\n revert ERC20InvalidApprover(address(0));\n }\n if (spender == address(0)) {\n revert ERC20InvalidSpender(address(0));\n }\n _allowances[owner][spender] = value;\n if (emitEvent) {\n emit Approval(owner, spender, value);\n }\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `value`.\n *\n * Does not update the allowance value in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Does not emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n if (currentAllowance < value) {\n revert ERC20InsufficientAllowance(spender, currentAllowance, value);\n }\n unchecked {\n _approve(owner, spender, currentAllowance - value, false);\n }\n }\n }\n}\n"
|
||
},
|
||
"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
|
||
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n"
|
||
},
|
||
"@openzeppelin/contracts/token/ERC20/IERC20.sol": {
|
||
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"
|
||
},
|
||
"@openzeppelin/contracts/utils/Context.sol": {
|
||
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n"
|
||
},
|
||
"contracts/00_Whitelist/SimpleOracle.sol": {
|
||
"content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ncontract SimpleOracle {\n /////////////////\n /// Errors //////\n /////////////////\n\n error OnlyOwner();\n\n //////////////////////\n /// State Variables //\n //////////////////////\n\n uint256 public price;\n uint256 public timestamp;\n address public owner;\n\n ////////////////\n /// Events /////\n ////////////////\n\n event PriceUpdated(uint256 newPrice);\n\n ///////////////////\n /// Constructor ///\n ///////////////////\n\n constructor(address _owner) {\n owner = _owner;\n }\n\n ///////////////////\n /// Modifiers /////\n ///////////////////\n\n /**\n * @notice Modifier to restrict function access to the contract owner\n * @dev Currently disabled to make it easy for you to impersonate the owner\n */\n modifier onlyOwner() {\n // Intentionally removing the owner requirement to make it easy for you to impersonate the owner\n // if (msg.sender != owner) revert OnlyOwner();\n _;\n }\n\n ///////////////////\n /// Functions /////\n ///////////////////\n\n /**\n * @notice Updates the oracle price with a new value (only contract owner)\n * @dev Sets the price and records the current block timestamp for freshness tracking.\n * Emits PriceUpdated event upon successful update.\n * @param _newPrice The new price value to set for this oracle\n */\n function setPrice(uint256 _newPrice) public onlyOwner {\n price = _newPrice;\n timestamp = block.timestamp;\n emit PriceUpdated(_newPrice);\n }\n\n /**\n * @notice Returns the current price and its timestamp\n * @dev Provides both the stored price value and when it was last updated.\n * Used by aggregators to determine price freshness.\n * @return price The current price stored in this oracle\n * @return timestamp The block timestamp when the price was last updated\n */\n function getPrice() public view returns (uint256, uint256) {\n return (price, timestamp);\n }\n}\n"
|
||
},
|
||
"contracts/00_Whitelist/WhitelistOracle.sol": {
|
||
"content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\nimport \"./SimpleOracle.sol\";\nimport { StatisticsUtils } from \"../utils/StatisticsUtils.sol\";\n\ncontract WhitelistOracle {\n using StatisticsUtils for uint256[];\n\n /////////////////\n /// Errors //////\n /////////////////\n\n error OnlyOwner();\n error IndexOutOfBounds();\n error NoOraclesAvailable();\n\n //////////////////////\n /// State Variables //\n //////////////////////\n\n address public owner;\n SimpleOracle[] public oracles;\n uint256 public constant STALE_DATA_WINDOW = 24 seconds;\n\n ////////////////\n /// Events /////\n ////////////////\n\n event OracleAdded(address oracleAddress, address oracleOwner);\n event OracleRemoved(address oracleAddress);\n\n ///////////////////\n /// Modifiers /////\n ///////////////////\n\n /**\n * @notice Modifier to restrict function access to the contract owner\n * @dev Currently disabled to make it easy for you to impersonate the owner\n */\n modifier onlyOwner() {\n // if (msg.sender != owner) revert OnlyOwner();\n _;\n }\n\n ///////////////////\n /// Constructor ///\n ///////////////////\n\n constructor() {\n owner = msg.sender;\n }\n\n ///////////////////\n /// Functions /////\n ///////////////////\n\n /**\n * @notice Adds a new oracle to the whitelist by deploying a SimpleOracle contract (only contract owner)\n * @dev Creates a new SimpleOracle instance and adds it to the oracles array.\n * @param _owner The address that will own the newly created oracle and can update its price\n */\n function addOracle(address _owner) public onlyOwner {}\n\n /**\n * @notice Removes an oracle from the whitelist by its array index (only contract owner)\n * @dev Uses swap-and-pop pattern for gas-efficient removal. Order is not preserved.\n * Reverts with IndexOutOfBounds, if the provided index is >= oracles.length.\n * @param index The index of the oracle to remove from the oracles array\n */\n function removeOracle(uint256 index) public onlyOwner {}\n\n /**\n * @notice Returns the aggregated price from all active oracles using median calculation\n * @dev Filters oracles with timestamps older than STALE_DATA_WINDOW, then calculates median\n * of remaining valid prices. Uses StatisticsUtils for sorting and median calculation.\n * @return The median price from all active oracles\n */\n function getPrice() public view returns (uint256) {}\n\n /**\n * @notice Returns the addresses of all oracles that have updated their price within the last STALE_DATA_WINDOW\n * @dev Iterates through all oracles and filters those with recent timestamps (within STALE_DATA_WINDOW).\n * Uses a temporary array to collect active nodes, then creates a right-sized return array\n * for gas optimization.\n * @return An array of addresses representing the currently active oracle contracts\n */\n function getActiveOracleNodes() public view returns (address[] memory) {}\n}\n"
|
||
},
|
||
"contracts/01_Staking/OracleToken.sol": {
|
||
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract ORA is ERC20, Ownable {\n //////////////////\n /// Constants ////\n //////////////////\n\n // 0.5 ETH = 100 ORA => 1 ETH = 200 ORA (18 decimals)\n uint256 public constant ORA_PER_ETH = 200;\n\n //////////////////////\n /// State Variables //\n //////////////////////\n\n ////////////////\n /// Events /////\n ////////////////\n\n event OraPurchased(address indexed buyer, uint256 ethIn, uint256 oraOut);\n event EthWithdrawn(address indexed to, uint256 amount);\n\n /////////////////\n /// Errors //////\n /////////////////\n\n error EthTransferFailed();\n\n constructor() ERC20(\"Oracle Token\", \"ORA\") Ownable(msg.sender) {\n // Mint initial supply to the contract deployer\n _mint(msg.sender, 1000000000000 ether);\n }\n\n function mint(address to, uint256 amount) public onlyOwner {\n _mint(to, amount);\n }\n\n function burn(uint256 amount) public {\n _burn(msg.sender, amount);\n }\n\n /**\n * @notice Buy ORA at a fixed rate by sending ETH. Mints directly to the buyer.\n */\n receive() external payable {\n _buy(msg.sender);\n }\n\n function buy() external payable {\n _buy(msg.sender);\n }\n\n function quoteOra(uint256 ethAmountWei) public pure returns (uint256) {\n return ethAmountWei * ORA_PER_ETH;\n }\n\n function _buy(address buyer) internal {\n uint256 oraOut = quoteOra(msg.value);\n _mint(buyer, oraOut);\n emit OraPurchased(buyer, msg.value, oraOut);\n }\n}\n"
|
||
},
|
||
"contracts/01_Staking/StakingOracle.sol": {
|
||
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\nimport { ORA } from \"./OracleToken.sol\";\nimport { StatisticsUtils } from \"../utils/StatisticsUtils.sol\";\n\ncontract StakingOracle {\n using StatisticsUtils for uint256[];\n\n /////////////////\n /// Errors //////\n /////////////////\n\n error NodeNotRegistered();\n error InsufficientStake();\n error NodeAlreadyRegistered();\n error NoRewardsAvailable();\n error OnlyPastBucketsAllowed();\n error NodeAlreadySlashed();\n error AlreadyReportedInCurrentBucket();\n error NotDeviated();\n error WaitingPeriodNotOver();\n error InvalidPrice();\n error IndexOutOfBounds();\n error NodeNotAtGivenIndex();\n error TransferFailed();\n error MedianNotRecorded();\n error BucketMedianAlreadyRecorded();\n error NodeDidNotReport();\n\n //////////////////////\n /// State Variables //\n //////////////////////\n\n ORA public oracleToken;\n\n struct OracleNode {\n uint256 stakedAmount;\n uint256 lastReportedBucket;\n uint256 reportCount;\n uint256 claimedReportCount;\n uint256 firstBucket; // block when node registered\n bool active;\n }\n\n struct BlockBucket {\n mapping(address => bool) slashedOffenses;\n address[] reporters;\n uint256[] prices;\n uint256 medianPrice;\n }\n\n mapping(address => OracleNode) public nodes;\n mapping(uint256 => BlockBucket) public blockBuckets; // one bucket per 24 blocks\n address[] public nodeAddresses;\n\n uint256 public constant MINIMUM_STAKE = 100 ether;\n uint256 public constant BUCKET_WINDOW = 24; // 24 blocks\n uint256 public constant SLASHER_REWARD_PERCENTAGE = 10;\n uint256 public constant REWARD_PER_REPORT = 1 ether; // ORA Token reward per report\n uint256 public constant INACTIVITY_PENALTY = 1 ether;\n uint256 public constant MISREPORT_PENALTY = 100 ether;\n uint256 public constant MAX_DEVIATION_BPS = 1000; // 10% default threshold\n uint256 public constant WAITING_PERIOD = 2; // 2 buckets after last report before exit allowed\n\n ////////////////\n /// Events /////\n ////////////////\n\n event NodeRegistered(address indexed node, uint256 stakedAmount);\n event PriceReported(address indexed node, uint256 price, uint256 bucketNumber);\n event BucketMedianRecorded(uint256 indexed bucketNumber, uint256 medianPrice);\n event NodeSlashed(address indexed node, uint256 amount);\n event NodeRewarded(address indexed node, uint256 amount);\n event StakeAdded(address indexed node, uint256 amount);\n event NodeExited(address indexed node, uint256 amount);\n\n ///////////////////\n /// Modifiers /////\n ///////////////////\n\n /**\n * @notice Modifier to restrict function access to registered oracle nodes\n * @dev Checks if the sender has a registered node in the mapping\n */\n modifier onlyNode() {\n if (nodes[msg.sender].active == false) revert NodeNotRegistered();\n _;\n }\n\n ///////////////////\n /// Constructor ///\n ///////////////////\n\n constructor(address oraTokenAddress) {\n oracleToken = ORA(payable(oraTokenAddress));\n }\n\n ///////////////////\n /// Functions /////\n ///////////////////\n\n /**\n * @notice Registers a new oracle node with initial ORA token stake\n * @dev Creates a new OracleNode struct and adds the sender to the nodeAddresses array.\n * Requires minimum stake amount and prevents duplicate registrations.\n */\n function registerNode(uint256 amount) public {}\n\n /**\n * @notice Updates the price reported by an oracle node (only registered nodes)\n * @dev Updates the node's lastReportedBucket and price in that bucket. Requires sufficient stake.\n * Enforces that previous report's bucket must have its median recorded before allowing new report.\n * This creates a chain of finalized buckets, ensuring all past reports are accountable.\n * @param price The new price value to report\n */\n function reportPrice(uint256 price) public onlyNode {}\n\n /**\n * @notice Allows active and inactive nodes to claim accumulated ORA token rewards\n * @dev Calculates rewards based on time elapsed since last claim.\n */\n function claimReward() public {}\n\n /**\n * @notice Allows a registered node to increase its ORA token stake\n */\n function addStake(uint256 amount) public onlyNode {}\n\n /**\n * @notice Records the median price for a bucket once sufficient reports are available\n * @dev Anyone who uses the oracle's price feed can call this function to record the median price for a bucket.\n * @param bucketNumber The bucket number to finalize\n */\n function recordBucketMedian(uint256 bucketNumber) public {}\n\n /**\n * @notice Slashes a node for giving a price that is deviated too far from the average\n * @param nodeToSlash The address of the node to slash\n * @param bucketNumber The bucket number to slash the node from\n * @param reportIndex The index of node in the prices and reporters arrays\n * @param nodeAddressesIndex The index of the node to slash in the nodeAddresses array\n */\n function slashNode(\n address nodeToSlash,\n uint256 bucketNumber,\n uint256 reportIndex,\n uint256 nodeAddressesIndex\n ) public {}\n\n /**\n * @notice Allows a registered node to exit the system and withdraw their stake\n * @dev Removes the node from the system and sends the stake to the node.\n * Requires that the the initial waiting period has passed to ensure the\n * node has been slashed if it reported a bad price before allowing it to exit.\n * @param index The index of the node to remove in nodeAddresses\n */\n function exitNode(uint256 index) public onlyNode {}\n\n ////////////////////////\n /// View Functions /////\n ////////////////////////\n\n /**\n * @notice Returns the current bucket number\n * @dev Returns the current bucket number based on the block number\n * @return The current bucket number\n */\n function getCurrentBucketNumber() public view returns (uint256) {\n return (block.number / BUCKET_WINDOW) + 1;\n }\n\n /**\n * @notice Returns the list of registered oracle node addresses\n * @return Array of registered oracle node addresses\n */\n function getNodeAddresses() public view returns (address[] memory) {}\n\n /**\n * @notice Returns the stored median price from the most recently completed bucket\n * @dev Requires that the median for the bucket be recorded via recordBucketMedian\n * @return The median price for the last finalized bucket\n */\n function getLatestPrice() public view returns (uint256) {}\n\n /**\n * @notice Returns the stored median price from a specified bucket\n * @param bucketNumber The bucket number to read the median price from\n * @return The median price stored for the bucket\n */\n function getPastPrice(uint256 bucketNumber) public view returns (uint256) {}\n\n /**\n * @notice Returns the price and slashed status of a node at a given bucket\n * @param nodeAddress The address of the node to get the data for\n * @param bucketNumber The bucket number to get the data from\n * @return price The price of the node at the specified bucket\n * @return slashed The slashed status of the node at the specified bucket\n */\n function getSlashedStatus(\n address nodeAddress,\n uint256 bucketNumber\n ) public view returns (uint256 price, bool slashed) {}\n\n /**\n * @notice Returns the effective stake accounting for inactivity penalties via missed buckets\n * @dev Effective stake = stakedAmount - (missedBuckets * INACTIVITY_PENALTY), floored at 0\n */\n function getEffectiveStake(address nodeAddress) public view returns (uint256) {}\n\n /**\n * @notice Returns the addresses of nodes in a bucket whose reported price deviates beyond the threshold\n * @param bucketNumber The bucket number to get the outliers from\n * @return Array of node addresses considered outliers\n */\n function getOutlierNodes(uint256 bucketNumber) public view returns (address[] memory) {}\n\n //////////////////////////\n /// Internal Functions ///\n //////////////////////////\n\n /**\n * @notice Removes a node from the nodeAddresses array\n * @param nodeAddress The address of the node to remove\n * @param index The index of the node to remove\n */\n function _removeNode(address nodeAddress, uint256 index) internal {}\n\n /**\n * @notice Checks if the price deviation is greater than the threshold\n * @param reportedPrice The price reported by the node\n * @param medianPrice The average price of the bucket\n * @return True if the price deviation is greater than the threshold, false otherwise\n */\n function _checkPriceDeviated(uint256 reportedPrice, uint256 medianPrice) internal pure returns (bool) {}\n}\n"
|
||
},
|
||
"contracts/02_Optimistic/Decider.sol": {
|
||
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ncontract Decider {\n address public owner;\n IOptimisticOracle public oracle;\n\n event DisputeSettled(uint256 indexed assertionId, bool resolvedValue);\n\n constructor(address _oracle) {\n owner = msg.sender;\n oracle = IOptimisticOracle(_oracle);\n }\n\n /**\n * @notice Settle a dispute by determining the true/false outcome\n * @param assertionId The ID of the assertion to settle\n * @param resolvedValue The true/false outcome determined by the decider\n */\n function settleDispute(uint256 assertionId, bool resolvedValue) external {\n require(assertionId >= 1, \"Invalid assertion ID\");\n\n // Call the oracle's settleAssertion function\n oracle.settleAssertion(assertionId, resolvedValue);\n\n emit DisputeSettled(assertionId, resolvedValue);\n }\n\n function setOracle(address newOracle) external {\n require(msg.sender == owner, \"Only owner can set oracle\");\n oracle = IOptimisticOracle(newOracle);\n }\n\n /**\n * @notice Allow the contract to receive ETH\n */\n receive() external payable {}\n}\n\ninterface IOptimisticOracle {\n function settleAssertion(uint256, bool) external;\n}\n"
|
||
},
|
||
"contracts/02_Optimistic/OptimisticOracle.sol": {
|
||
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ncontract OptimisticOracle {\n ////////////////\n /// Enums //////\n ////////////////\n\n enum State {\n Invalid,\n Asserted,\n Proposed,\n Disputed,\n Settled,\n Expired\n }\n\n /////////////////\n /// Errors //////\n /////////////////\n\n error AssertionNotFound();\n error AssertionProposed();\n error InvalidValue();\n error InvalidTime();\n error ProposalDisputed();\n error NotProposedAssertion();\n error AlreadyClaimed();\n error AlreadySettled();\n error AwaitingDecider();\n error NotDisputedAssertion();\n error OnlyDecider();\n error OnlyOwner();\n error TransferFailed();\n\n //////////////////////\n /// State Variables //\n //////////////////////\n\n struct EventAssertion {\n address asserter;\n address proposer;\n address disputer;\n bool proposedOutcome;\n bool resolvedOutcome;\n uint256 reward;\n uint256 bond;\n uint256 startTime;\n uint256 endTime;\n bool claimed;\n address winner;\n string description;\n }\n\n uint256 public constant MINIMUM_ASSERTION_WINDOW = 3 minutes;\n uint256 public constant DISPUTE_WINDOW = 3 minutes;\n address public decider;\n address public owner;\n uint256 public nextAssertionId = 1;\n mapping(uint256 => EventAssertion) public assertions;\n\n ////////////////\n /// Events /////\n ////////////////\n\n event EventAsserted(uint256 assertionId, address asserter, string description, uint256 reward);\n event OutcomeProposed(uint256 assertionId, address proposer, bool outcome);\n event OutcomeDisputed(uint256 assertionId, address disputer);\n event AssertionSettled(uint256 assertionId, bool outcome, address winner);\n event DeciderUpdated(address oldDecider, address newDecider);\n event RewardClaimed(uint256 assertionId, address winner, uint256 amount);\n event RefundClaimed(uint256 assertionId, address asserter, uint256 amount);\n\n ///////////////////\n /// Modifiers /////\n ///////////////////\n\n /**\n * @notice Modifier to restrict function access to the designated decider\n * @dev Ensures only the decider can settle disputed assertions\n */\n modifier onlyDecider() {\n if (msg.sender != decider) revert OnlyDecider();\n _;\n }\n\n /**\n * @notice Modifier to restrict function access to the contract owner\n * @dev Ensures only the owner can update critical contract parameters\n */\n modifier onlyOwner() {\n if (msg.sender != owner) revert OnlyOwner();\n _;\n }\n\n ///////////////////\n /// Constructor ///\n ///////////////////\n\n constructor(address _decider) {\n decider = _decider;\n owner = msg.sender;\n }\n\n ///////////////////\n /// Functions /////\n ///////////////////\n\n /**\n * @notice Updates the decider address (only contract owner)\n * @dev Changes the address authorized to settle disputed assertions.\n * Emits DeciderUpdated event with old and new addresses.\n * @param _decider The new address that will act as decider for disputed assertions\n */\n function setDecider(address _decider) external onlyOwner {\n address oldDecider = address(decider);\n decider = _decider;\n emit DeciderUpdated(oldDecider, _decider);\n }\n\n /**\n * @notice Returns the complete assertion details for a given assertion ID\n * @dev Provides access to all fields of the EventAssertion struct\n * @param assertionId The unique identifier of the assertion to retrieve\n * @return The complete EventAssertion struct containing all assertion data\n */\n function getAssertion(uint256 assertionId) external view returns (EventAssertion memory) {\n return assertions[assertionId];\n }\n\n /**\n * @notice Creates a new assertion about an event with a true/false outcome\n * @dev Requires ETH payment as reward for correct proposers. Bond requirement is 2x the reward.\n * Sets default timestamps if not provided. Validates timing requirements.\n * @param description Human-readable description of the event (e.g. \"Did X happen by time Y?\")\n * @param startTime When proposals can begin (0 for current block timestamp)\n * @param endTime When the assertion expires (0 for startTime + minimum window)\n * @return The unique assertion ID for the newly created assertion\n */\n function assertEvent(\n string memory description,\n uint256 startTime,\n uint256 endTime\n ) external payable returns (uint256) {}\n\n /**\n * @notice Proposes the outcome (true or false) for an asserted event\n * @dev Requires bonding ETH equal to 2x the original reward. Sets dispute window deadline.\n * Can only be called once per assertion and within the assertion time window.\n * @param assertionId The unique identifier of the assertion to propose an outcome for\n * @param outcome The proposed boolean outcome (true or false) for the event\n */\n function proposeOutcome(uint256 assertionId, bool outcome) external payable {}\n\n /**\n * @notice Disputes a proposed outcome by bonding ETH\n * @dev Requires bonding ETH equal to the bond amount. Can only dispute once per assertion\n * and must be within the dispute window after proposal.\n * @param assertionId The unique identifier of the assertion to dispute\n */\n function disputeOutcome(uint256 assertionId) external payable {}\n\n /**\n * @notice Claims reward for undisputed assertions after dispute window expires\n * @dev Anyone can trigger this function. Transfers reward + bond to the proposer.\n * Can only be called after dispute window has passed without disputes.\n * @param assertionId The unique identifier of the assertion to claim rewards for\n */\n function claimUndisputedReward(uint256 assertionId) external {}\n\n /**\n * @notice Claims reward for disputed assertions after decider settlement\n * @dev Anyone can trigger this function. Pays decider fee and transfers remaining rewards to winner.\n * Can only be called after decider has settled the dispute.\n * @param assertionId The unique identifier of the disputed assertion to claim rewards for\n */\n function claimDisputedReward(uint256 assertionId) external {}\n\n /**\n * @notice Claims refund for assertions that receive no proposals before deadline\n * @dev Anyone can trigger this function. Returns the original reward to the asserter.\n * Can only be called after assertion deadline has passed without any proposals.\n * @param assertionId The unique identifier of the expired assertion to claim refund for\n */\n function claimRefund(uint256 assertionId) external {}\n\n /**\n * @notice Resolves disputed assertions by determining the correct outcome (only decider)\n * @dev Sets the resolved outcome and determines winner based on proposal accuracy.\n * @param assertionId The unique identifier of the disputed assertion to settle\n * @param resolvedOutcome The decider's determination of the true outcome\n */\n function settleAssertion(uint256 assertionId, bool resolvedOutcome) external onlyDecider {}\n\n /**\n * @notice Returns the current state of an assertion based on its lifecycle stage\n * @dev Evaluates assertion progress through states: Invalid, Asserted, Proposed, Disputed, Settled, Expired\n * @param assertionId The unique identifier of the assertion to check state for\n * @return The current State enum value representing the assertion's status\n */\n function getState(uint256 assertionId) external view returns (State) {}\n\n /**\n * @notice Returns the final resolved outcome of a settled assertion\n * @dev For undisputed assertions, returns the proposed outcome after dispute window.\n * For disputed assertions, returns the decider's resolved outcome.\n * @param assertionId The unique identifier of the assertion to get resolution for\n * @return The final boolean outcome of the assertion\n */\n function getResolution(uint256 assertionId) external view returns (bool) {}\n}\n"
|
||
},
|
||
"contracts/utils/StatisticsUtils.sol": {
|
||
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\nlibrary StatisticsUtils {\n /////////////////\n /// Errors //////\n /////////////////\n\n error EmptyArray();\n\n ///////////////////\n /// Functions /////\n ///////////////////\n\n /**\n * @notice Sorts an array of uint256 values in ascending order using selection sort\n * @dev Uses selection sort algorithm which is not gas-efficient but acceptable for small arrays.\n * This implementation mimics the early MakerDAO Medianizer exactly.\n * Modifies the input array in-place.\n * @param arr The array of uint256 values to sort in ascending order\n */\n function sort(uint256[] memory arr) internal pure {\n uint256 n = arr.length;\n for (uint256 i = 0; i < n; i++) {\n uint256 minIndex = i;\n for (uint256 j = i + 1; j < n; j++) {\n if (arr[j] < arr[minIndex]) {\n minIndex = j;\n }\n }\n if (minIndex != i) {\n (arr[i], arr[minIndex]) = (arr[minIndex], arr[i]);\n }\n }\n }\n\n /**\n * @notice Calculates the median value from a sorted array of uint256 values\n * @dev For arrays with even length, returns the average of the two middle elements.\n * For arrays with odd length, returns the middle element.\n * Assumes the input array is already sorted in ascending order.\n * @param arr The sorted array of uint256 values to calculate median from\n * @return The median value as a uint256\n */\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\n uint256 length = arr.length;\n if (length == 0) revert EmptyArray();\n if (length % 2 == 0) {\n return (arr[length / 2 - 1] + arr[length / 2]) / 2;\n } else {\n return arr[length / 2];\n }\n }\n}\n"
|
||
}
|
||
},
|
||
"settings": {
|
||
"optimizer": {
|
||
"enabled": true,
|
||
"runs": 200
|
||
},
|
||
"evmVersion": "paris",
|
||
"outputSelection": {
|
||
"*": {
|
||
"*": [
|
||
"abi",
|
||
"evm.bytecode",
|
||
"evm.deployedBytecode",
|
||
"evm.methodIdentifiers",
|
||
"metadata",
|
||
"devdoc",
|
||
"userdoc",
|
||
"storageLayout",
|
||
"evm.gasEstimates"
|
||
],
|
||
"": [
|
||
"ast"
|
||
]
|
||
}
|
||
},
|
||
"metadata": {
|
||
"useLiteralContent": true
|
||
}
|
||
}
|
||
} |