DIAParallelOracle

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

// File: @openzeppelin/contracts/utils/Context.sol


// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;


/**
 * @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);
    }
}

// File: contracts/DIAParallelOracle.sol


pragma solidity 0.8.29;


interface IRedeemer {
  function quoteRedemptionCurve(uint256 amount)
    external
    view
    returns (address[] memory tokens, uint256[] memory amounts);
}

interface IGetters {
  function getOracleValues(address collateral)
    external
    view
    returns (uint256 mint, uint256 burn, uint256 ratio, uint256 minRatio, uint256 redemption);
  function getTotalIssued() 
    external
    view
    returns (uint256 stablecoinsIssued);
}

interface IERC4626 {
    function convertToShares(uint256 assets) external view returns (uint256 shares);
}

contract DIAParallelOracle is Ownable(msg.sender) {
    address public getterAddress;
    address public redeemerAddress;
    address public susdpVaultAddress;

    uint256 public outputDecimals;
    uint256 public constant QUERY_DECIMALS = 18;

    string public USDP_QUERY_STRING;

    mapping (string => uint256) public values;
    event OracleUpdate(string key, uint128 value, uint128 timestamp);

    constructor(address _getterAddress, address _redeemerAddress, address _susdpVaultAddress, uint256 _outputDecimals) {
        require(_outputDecimals <= QUERY_DECIMALS, "Output decimals must be less or equal QUERY_DECIMALS.");
        getterAddress = _getterAddress;
        redeemerAddress = _redeemerAddress;
        susdpVaultAddress = _susdpVaultAddress;
        outputDecimals = _outputDecimals;
        USDP_QUERY_STRING = "USDp/USD";
    }

    function setGetterAddress(address _newGetterAddress) onlyOwner external {
        getterAddress = _newGetterAddress;
    }

    function setRedeemerAddress(address _newRedeemerAddress) onlyOwner external {
        redeemerAddress = _newRedeemerAddress;
    }

    function setSusdpVaultAddress(address _newSusdpVaultAddress) onlyOwner external {
        susdpVaultAddress = _newSusdpVaultAddress;
    }

    function setOutputDecimals(uint256 _newDecimals) onlyOwner external {
        require(outputDecimals <= QUERY_DECIMALS, "Output decimals must be less or equal QUERY_DECIMALS.");
        outputDecimals = _newDecimals;
    }

    function setUsdpQueryString(string memory newUsdpQueryString) onlyOwner external {
        USDP_QUERY_STRING = newUsdpQueryString;
    }

    function getChainSpecificUsdpPrice() external view returns (uint256) {
        IRedeemer redeemerInstance = IRedeemer(redeemerAddress);
        IGetters getterInstance = IGetters(getterAddress);

        (address[] memory collateralTokens, uint256[] memory redemptionValues) = 
            redeemerInstance.quoteRedemptionCurve(10 ** QUERY_DECIMALS);

        uint256 usdpPrice = 0;

        for (uint256 i = 0; i < collateralTokens.length; ++i) {
            address currToken = collateralTokens[i];
            uint256 currRedemptionValue = redemptionValues[i];

            (, , , , uint256 currOracleRedemptionPrice) = getterInstance.getOracleValues(currToken);
            uint256 redemptionValueUsd = currOracleRedemptionPrice * currRedemptionValue;

            usdpPrice += redemptionValueUsd;
        }

        uint256 decimalDelta = (QUERY_DECIMALS + 18) - outputDecimals;

        return usdpPrice / (10 ** decimalDelta);
    }

    function getChainSpecificUsdpIssued() external view returns (uint256) {
        IGetters getterInstance = IGetters(getterAddress);
        return getterInstance.getTotalIssued();
    }

    function getSusdpPrice() public view returns (uint256) {
        IERC4626 susdpVaultInstance = IERC4626(susdpVaultAddress);
        (uint128 usdpPrice,) = getValue(USDP_QUERY_STRING);
        uint256 susdpRate = susdpVaultInstance.convertToShares(10 ** QUERY_DECIMALS);

        return (susdpRate * usdpPrice) / (10 ** QUERY_DECIMALS);
    }

    function setValue(string memory key, uint128 value, uint128 timestamp) onlyOwner external {
        uint256 cValue = (((uint256)(value)) << 128) + timestamp;
        values[key] = cValue;
        emit OracleUpdate(key, value, timestamp);
    }

    function setMultipleValues(string[] memory keys, uint256[] memory compressedValues) onlyOwner external {
        require(keys.length == compressedValues.length);
        
        for (uint128 i = 0; i < keys.length; i++) {
            string memory currentKey = keys[i];
            uint256 currentCvalue = compressedValues[i];
            uint128 value = (uint128)(currentCvalue >> 128);
            uint128 timestamp = (uint128)(currentCvalue % 2**128);

            values[currentKey] = currentCvalue;
            emit OracleUpdate(currentKey, value, timestamp);
        }
    }

    function getValue(string memory key) public view returns (uint128, uint128) {
        if (compareStrings(key, "sUSDp/USD")) {
            return (uint128(getSusdpPrice()), uint128(block.timestamp));
        } else {
            uint256 cValue = values[key];
            uint128 timestamp = (uint128)(cValue % 2**128);
            uint128 value = (uint128)(cValue >> 128);
            return (value, timestamp);
        }
    }

    function compareStrings(string memory _a, string memory _b) internal pure returns(bool) {
        return keccak256(abi.encodePacked(_a)) == keccak256(abi.encodePacked(_b));
    }
}

Tags:
Multisig, Multi-Signature, Factory, Oracle|addr:0x2029b1f4865ffb1e6340c45e43a7be0732d8574a|verified:true|block:23545908|tx:0x68acd741c352d78cbe544b92ba8f355fc17425fce40b2350018193cdf9d34869|first_check:1760086923

Submitted on: 2025-10-10 11:02:03

Comments

Log in to comment.

No comments yet.