Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0x67283c357053185F0eF0dF2F2a37f8191114Dfb7
Balance 0 ETH
Nonce 1
Code Size 1390 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

1390 bytes
0x608060405234801561000f575f80fd5b506004361061007a575f3560e01c80638da5cb5b116100585780638da5cb5b146100ae5780639c52a7f1146100cd578063bf353dbb146100e0578063f2fde38b1461010d575f80fd5b80634abf8e271461007e57806365fae35e14610093578063715018a6146100a6575b5f80fd5b61009161008c36600461041f565b610120565b005b6100916100a1366004610502565b61028a565b6100916102ae565b5f546040516001600160a01b0390911681526020015b60405180910390f35b6100916100db366004610502565b6102c1565b6100ff6100ee366004610502565b60016020525f908152604090205481565b6040519081526020016100c4565b61009161011b366004610502565b6102e2565b335f90815260016020526040812054900361014d576040516282b42960e81b815260040160405180910390fd5b825181811461016f57604051638c38e89d60e01b815260040160405180910390fd5b5f5b818110156102835784818151811061018b5761018b610524565b60200260200101516001600160a01b031663a08edce88585848181106101b3576101b3610524565b905060200201356040518263ffffffff1660e01b81526004016101d891815260200190565b5f604051808303815f87803b1580156101ef575f80fd5b505af1925050508015610200575060015b61027b577f8cc1621726ea8d418994e43b06ac780b61a086a253d7b4537443dbc33ded690d85828151811061023757610237610524565b602002602001015185858481811061025157610251610524565b604080516001600160a01b0390951685526020918202939093013590840152500160405180910390a15b600101610171565b5050505050565b610292610324565b6001600160a01b03165f90815260016020819052604090912055565b6102b6610324565b6102bf5f610350565b565b6102c9610324565b6001600160a01b03165f90815260016020526040812055565b6102ea610324565b6001600160a01b03811661031857604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61032181610350565b50565b5f546001600160a01b031633146102bf5760405163118cdaa760e01b815233600482015260240161030f565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b634e487b7160e01b5f52604160045260245ffd5b6001600160a01b0381168114610321575f80fd5b80356103d2816103b3565b919050565b5f8083601f8401126103e7575f80fd5b50813567ffffffffffffffff8111156103fe575f80fd5b6020830191508360208260051b8501011115610418575f80fd5b9250929050565b5f805f60408486031215610431575f80fd5b833567ffffffffffffffff80821115610448575f80fd5b818601915086601f83011261045b575f80fd5b813560208282111561046f5761046f61039f565b8160051b604051601f19603f830116810181811086821117156104945761049461039f565b6040529283528481018201928281018b8511156104af575f80fd5b958301955b848710156104d2576104c5876103c7565b81529583019583016104b4565b50975050870135925050808211156104e8575f80fd5b506104f5868287016103d7565b9497909650939450505050565b5f60208284031215610512575f80fd5b813561051d816103b3565b9392505050565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220552c0964a0af22828aba02b3e0c2141fdb7de61965c3e896ed87ee477dfc7f9664736f6c63430008170033

Verified Source Code Partial Match

Compiler: v0.8.23+commit.f704f362 EVM: shanghai Optimization: Yes (200 runs)
Context.sol 24 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
Ownable.sol 100 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
Upgradeable.sol 10 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.23;

import {Ownable} from "Ownable.sol";

contract Upgradeable is Ownable {
    address public implementation;

    constructor() Ownable(msg.sender) {}
}
BatchUpdateRate.sol 44 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.23;

import "FungifyPriceFeed.sol";
import "Ownable.sol";

// This is intended to reduce the number of transactions made.
contract BatchUpdateRate is Ownable {
    // --- Auth ---
    mapping (address => uint) public wards;
    function rely(address guy) external onlyOwner { wards[guy] = 1; }
    function deny(address guy) external onlyOwner { wards[guy] = 0; }
    modifier auth {
        if (wards[msg.sender] == 0) {
            revert Unauthorized();
        }
        _;
    }

    event FailedToUpdate(FungifyPriceFeed feed, int256 answer);

    error UnequalParamLengths();
    error Unauthorized();

    constructor() Ownable(msg.sender) {}

    // Sets the price answer to multiple price feeds at once
    function batchSetAnswer(FungifyPriceFeed[] memory priceFeeds, int256[] calldata newAnswers) external auth {
        uint numFeeds = priceFeeds.length;

        if (numFeeds != newAnswers.length) {
            revert UnequalParamLengths();
        }

        // Loops through all the provided feeds and attempts to set their answers
        for (uint i = 0; i < numFeeds;) {
            try priceFeeds[i].updateRate(newAnswers[i]) {
            } catch {
                emit FailedToUpdate(priceFeeds[i], newAnswers[i]);
            }
            unchecked { i++; }
        }
    }
}
FungifyPriceFeed.sol 184 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.23;

import "Upgradeable.sol";

contract FungifyPriceFeed is Upgradeable {
    event RateUpdated(int256 oldRate, int256 newRate, int256 inputRate);
    error UnderTimeAndPriceDeviationMinimums();
    error OverPriceDeviationMaximum();
    error Unauthorized();
    error AdditionOverflow();
    error SubtractionOverflow();
    error LessThanTwoPeriods();

    // --- Auth ---
    mapping (address => uint256) public wards;
    function rely(address guy) external onlyOwner { wards[guy] = 1; }
    function deny(address guy) external onlyOwner { wards[guy] = 0; }
    modifier auth {
        if (wards[msg.sender] == 0) {
            revert Unauthorized();
        }
        _;
    }

    int256 public constant ONE_IN_BIP = 10000;
    uint8 public immutable _decimals;

    int256 public latestAnswer;
    uint256 public latestUpdateTime;

    // Variables for price updating assertions
    int256 public minPriceDeviationBip; // Defined in basis points: 1 Bip = .01%
    uint256 public stalePriceTime;

    int256 public emaPeriods; // averaging periods for EMA calculation
    int public maxPriceDeviationBip; // Defined in basis points: 1 Bip = .01%

    constructor(uint8 decimals_) {
        _decimals = decimals_;
    }

    function initialize(int256 startingRate_) external {
        if (msg.sender != owner()) {
            revert Unauthorized();
        }

        latestAnswer = startingRate_;
        latestUpdateTime = block.timestamp;
        stalePriceTime = 7200;
        minPriceDeviationBip = 200;
        maxPriceDeviationBip = 3500;
        emaPeriods = 3;
        emit RateUpdated(0, startingRate_, startingRate_);
    }

    function decimals() public view returns (uint8) {
        return _decimals;
    }

    function latestRoundData()
        public
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        ) {
        return (0, latestAnswer, 0, latestUpdateTime, 0);
    }

    // Verifies if a newRate is within the priceDeviationBip of oldRate
    function underMinPriceDeviation(int256 newRate, int256 oldRate) public view returns(bool) {

        int256 allowedDeviation = oldRate * minPriceDeviationBip / ONE_IN_BIP;

        if (newRate > oldRate + allowedDeviation || newRate < oldRate - allowedDeviation) {
            return false;
        } else {
            return true;
        }
    }

    // Verifies that a newRate is within the maxPriceDeviationBip of oldRate
    function overMaxPriceDeviation(int256 newRate, int256 oldRate) public view returns(bool) {

        int allowedDeviation = oldRate * maxPriceDeviationBip / ONE_IN_BIP;

        if (newRate > oldRate + allowedDeviation || newRate < oldRate - allowedDeviation) {
            return true;
        } else {
            return false;
        }
    }

    function updateRate(int256 newRate_) public auth {

        int256 oldEMA = latestAnswer;

        if (overMaxPriceDeviation(newRate_, oldEMA)) {
            revert OverPriceDeviationMaximum();
        }
        
        // Performs Price Update Minimum Deviation Time and Price Checks
        if (underMinPriceDeviation(newRate_, oldEMA) && block.timestamp < latestUpdateTime + stalePriceTime) {
            revert UnderTimeAndPriceDeviationMinimums();
        }

        int256 newEMA = updateEMA(oldEMA, newRate_);

        latestAnswer = newEMA;
        latestUpdateTime = block.timestamp;
        emit RateUpdated(oldEMA, newEMA, newRate_);
    }

    function updateEMA(int256 currentEMA, int256 newValue) internal view returns (int256) {
        /*
            Multiplier: 2 / (emaPeriods + 1)
            EMA: (LastestValue - PreviousEMA) * Multiplier + PreviousEMA
        */

        int256 emaPeriods_ = emaPeriods;

        int256 newEMA =
            sub(
                add(
                    newValue * 2 / (emaPeriods_ + 1),
                    currentEMA
                ),
                currentEMA * 2 / (emaPeriods_ + 1)
            );

        return newEMA;
    }

    function setStalePriceTime(uint _stalePriceTime) external onlyOwner {
        stalePriceTime = _stalePriceTime;
    }

    // Defined in basis points: 1 Bip = .01%
    function setMinPriceDeviationBip(int _minPriceDeviationBip) external onlyOwner {
        minPriceDeviationBip = _minPriceDeviationBip;
    }

    // Defined in basis points: 1 Bip = .01%
    function setMaxPriceDeviationBip(int _maxPriceDeviationBip) external onlyOwner {
        maxPriceDeviationBip = _maxPriceDeviationBip;
    }

    function setEMAPeriods(int _emaPeriods) external onlyOwner {
        if (_emaPeriods < 2) {
            revert LessThanTwoPeriods();
        }
        emaPeriods = _emaPeriods;
    }

    function adminUpdateRate(int256 newRate_) external onlyOwner {
        int256 oldRate = latestAnswer;
        latestAnswer = newRate_;
        latestUpdateTime = block.timestamp;
        emit RateUpdated(oldRate, newRate_, newRate_);
    }

    function add(int256 a, int256 b) internal pure returns (int256) {
        int256 c;
        unchecked { c = a + b; }
        if (!((b >= 0 && c >= a) || (b < 0 && c < a))) {
            revert AdditionOverflow();
        }

        return c;
    }
    function sub(int256 a, int256 b) internal pure returns (int256) {
        int256 c;
        unchecked { c = a - b; }
        if (!((b >= 0 && c <= a) || (b < 0 && c > a))) {
            revert SubtractionOverflow();
        }

        return c;
    }
}

Read Contract

owner 0x8da5cb5b → address
wards 0xbf353dbb → uint256

Write Contract 5 functions

These functions modify contract state and require a wallet transaction to execute.

batchSetAnswer 0x4abf8e27
address[] priceFeeds
int256[] newAnswers
deny 0x9c52a7f1
address guy
rely 0x65fae35e
address guy
renounceOwnership 0x715018a6
No parameters
transferOwnership 0xf2fde38b
address newOwner

Recent Transactions

No transactions found for this address