Contract 0x91069b93062c1Fdd6998741C9CA3C6eA57672956

Txn Hash Method
Block
From
To
Value [Txn Fee]
0xcd1bee98d99d34ac237f6990669048a83517376a493d2fdc390f2abfbf23772f0x608060409066312022-04-27 6:45:18285 days 22 hrs agoLido Staked Polkadot: Deployer IN  Create: Oracle0 GLMR0.1228654
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Oracle

Compiler Version
v0.8.10+commit.fc410830

Optimization Enabled:
Yes with 10 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 5 : Oracle.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "Types.sol";
import "ILedger.sol";
import "IOracleMaster.sol";

import "ReportUtils.sol";


contract Oracle {
    using ReportUtils for uint256;

    event Completed(uint256);

    // is already pushed flag
    bool public isPushed;

    // Current era report  hashes
    uint256[] internal currentReportVariants;

    // Current era reports
    Types.OracleData[] private currentReports;

    // Then oracle member push report, its bit is set
    uint256 internal currentReportBitmask;

    // oracle master contract address
    address public ORACLE_MASTER;

    // linked ledger contract address
    address public LEDGER;

    // Allows function calls only from OracleMaster
    modifier onlyOracleMaster() {
        require(msg.sender == ORACLE_MASTER);
        _;
    }

    /**
    * @notice Initialize oracle contract
    * @param _oracleMaster oracle master address
    * @param _ledger linked ledger address
    */
    function initialize(address _oracleMaster, address _ledger) external {
        require(ORACLE_MASTER == address(0), "ORACLE: ALREADY_INITIALIZED");
        ORACLE_MASTER = _oracleMaster;
        LEDGER = _ledger;
    }

    /**
    * @notice Returns true if member is already reported
    * @param _index oracle member index
    * @return is reported indicator
    */
    function isReported(uint256 _index) external view returns (bool) {
        return (currentReportBitmask & (1 << _index)) != 0;
    }

    /**
    * @notice Accept oracle report data, allowed to call only by oracle master contract
    * @param _index oracle member index
    * @param _quorum the minimum number of voted oracle members to accept a variant
    * @param _eraId current era id
    * @param _staking report data
    */
    function reportRelay(uint256 _index, uint256 _quorum, uint64 _eraId, Types.OracleData calldata _staking) external onlyOracleMaster {
        {
            uint256 mask = 1 << _index;
            uint256 reportBitmask = currentReportBitmask;
            require(reportBitmask & mask == 0, "ORACLE: ALREADY_SUBMITTED");
            currentReportBitmask = (reportBitmask | mask);
        }
        // return instantly if already got quorum and pushed data
        if (isPushed) {
            return;
        }

        // convert staking report into 31 byte hash. The last byte is used for vote counting
        uint256 variant = uint256(keccak256(abi.encode(_staking))) & ReportUtils.COUNT_OUTMASK;

        uint256 i = 0;
        uint256 _length = currentReportVariants.length;
        // iterate on all report variants we already have, limited by the oracle members maximum
        while (i < _length && currentReportVariants[i].isDifferent(variant)) ++i;
        if (i < _length) {
            if (currentReportVariants[i].getCount() + 1 >= _quorum) {
                _push(_eraId, _staking);
            } else {
                ++currentReportVariants[i];
                // increment variant counter, see ReportUtils for details
            }
        } else {
            if (_quorum == 1) {
                _push(_eraId, _staking);
            } else {
                currentReportVariants.push(variant + 1);
                currentReports.push(_staking);
            }
        }
    }

    /**
    * @notice Change quorum threshold, allowed to call only by oracle master contract
    * @dev Method can trigger to pushing data to ledger if quorum threshold decreased and
           now for contract already reached new threshold.
    * @param _quorum new quorum threshold
    * @param _eraId current era id
    */
    function softenQuorum(uint8 _quorum, uint64 _eraId) external onlyOracleMaster {
        (bool isQuorum, uint256 reportIndex) = _getQuorumReport(_quorum);
        if (isQuorum) {
            Types.OracleData memory report = _getStakeReport(reportIndex);
            _push(
                _eraId, report
            );
        }
    }

    /**
    * @notice Clear data about current reporting, allowed to call only by oracle master contract
    */
    function clearReporting() external onlyOracleMaster {
        _clearReporting();
    }

    /**
    * @notice Returns report by given index
    * @param _index oracle member index
    * @return staking report data
    */
    function _getStakeReport(uint256 _index) internal view returns (Types.OracleData storage staking) {
        assert(_index < currentReports.length);
        return currentReports[_index];
    }

    /**
    * @notice Clear data about current reporting
    */
    function _clearReporting() internal {
        currentReportBitmask = 0;
        isPushed = false;

        delete currentReportVariants;
        delete currentReports;
    }

    /**
    * @notice Push data to ledger
    */
    function _push(uint64 _eraId, Types.OracleData memory report) internal {
        ILedger(LEDGER).pushData(_eraId, report);
        isPushed = true;
    }

    /**
    * @notice Return whether the `_quorum` is reached and the final report can be pushed
    */
    function _getQuorumReport(uint256 _quorum) internal view returns (bool, uint256) {
        // check most frequent cases first: all reports are the same or no reports yet
        uint256 _length = currentReportVariants.length;
        if (_length == 1) {
            return (currentReportVariants[0].getCount() >= _quorum, 0);
        } else if (_length == 0) {
            return (false, type(uint256).max);
        }

        // if more than 2 kind of reports exist, choose the most frequent
        uint256 maxind = 0;
        uint256 repeat = 0;
        uint16 maxval = 0;
        uint16 cur = 0;
        for (uint256 i = 0; i < _length; ++i) {
            cur = currentReportVariants[i].getCount();
            if (cur >= maxval) {
                if (cur == maxval) {
                    ++repeat;
                } else {
                    maxind = i;
                    maxval = cur;
                    repeat = 0;
                }
            }
        }
        return (maxval >= _quorum && repeat == 0, maxind);
    }
}

File 2 of 5 : Types.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface Types {
    struct Fee{
        uint16 total;
        uint16 operators;
        uint16 developers;
        uint16 treasury;
    }

    struct Stash {
        bytes32 stashAccount;
        uint64  eraId;
    }

    enum LedgerStatus {
        // bonded but not participate in staking
        Idle,
        // participate as nominator
        Nominator,
        // participate as validator
        Validator,
        // not bonded not participate in staking
        None
    }

    struct UnlockingChunk {
        uint128 balance;
        uint64 era;
    }

    struct OracleData {
        bytes32 stashAccount;
        bytes32 controllerAccount;
        LedgerStatus stakeStatus;
        // active part of stash balance
        uint128 activeBalance;
        // locked for stake stash balance.
        uint128 totalBalance;
        // totalBalance = activeBalance + sum(unlocked.balance)
        UnlockingChunk[] unlocking;
        uint32[] claimedRewards;
        // stash account balance. It includes locked (totalBalance) balance assigned
        // to a controller.
        uint128 stashBalance;
        // slashing spans for ledger
        uint32 slashingSpans;
    }

    struct RelaySpec {
        uint16 maxValidatorsPerLedger;
        uint128 minNominatorBalance;
        uint128 ledgerMinimumActiveBalance;
        uint256 maxUnlockingChunks;
    }
}

File 3 of 5 : ILedger.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "Types.sol";

interface ILedger {
    function initialize(
        bytes32 _stashAccount,
        bytes32 controllerAccount,
        address vKSM,
        address controller,
        uint128 minNominatorBalance,
        address lido,
        uint128 _minimumBalance,
        uint256 _maxUnlockingChunks
    ) external;

    function pushData(uint64 eraId, Types.OracleData calldata staking) external;

    function nominate(bytes32[] calldata validators) external;

    function status() external view returns (Types.LedgerStatus);

    function isEmpty() external view returns (bool);

    function stashAccount() external view returns (bytes32);

    function totalBalance() external view returns (uint128);

    function setRelaySpecs(uint128 minNominatorBalance, uint128 minimumBalance, uint256 _maxUnlockingChunks) external;

    function cachedTotalBalance() external view returns (uint128);

    function transferDownwardBalance() external view returns (uint128);
}

File 4 of 5 : IOracleMaster.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IOracleMaster {
    function addLedger(address ledger) external;

    function removeLedger(address ledger) external;

    function getOracle(address ledger) view external returns (address);

    function eraId() view external returns (uint64);

    function setLido(address lido) external;
}

File 5 of 5 : ReportUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;


library ReportUtils {
    // last bytes used to count votes
    uint256 constant internal COUNT_OUTMASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00;

    /// @notice Check if the given reports are different, not considering the counter of the first
    function isDifferent(uint256 value, uint256 that) internal pure returns (bool) {
        return (value & COUNT_OUTMASK) != that;
    }

    /// @notice Return the total number of votes recorded for the variant
    function getCount(uint256 value) internal pure returns (uint8) {
        return uint8(value);
    }
}

Settings
{
  "evmVersion": "istanbul",
  "optimizer": {
    "enabled": true,
    "runs": 10
  },
  "libraries": {
    "Oracle.sol": {}
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"Completed","type":"event"},{"inputs":[],"name":"LEDGER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_MASTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"clearReporting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_oracleMaster","type":"address"},{"internalType":"address","name":"_ledger","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isPushed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"isReported","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"uint256","name":"_quorum","type":"uint256"},{"internalType":"uint64","name":"_eraId","type":"uint64"},{"components":[{"internalType":"bytes32","name":"stashAccount","type":"bytes32"},{"internalType":"bytes32","name":"controllerAccount","type":"bytes32"},{"internalType":"enum Types.LedgerStatus","name":"stakeStatus","type":"uint8"},{"internalType":"uint128","name":"activeBalance","type":"uint128"},{"internalType":"uint128","name":"totalBalance","type":"uint128"},{"components":[{"internalType":"uint128","name":"balance","type":"uint128"},{"internalType":"uint64","name":"era","type":"uint64"}],"internalType":"struct Types.UnlockingChunk[]","name":"unlocking","type":"tuple[]"},{"internalType":"uint32[]","name":"claimedRewards","type":"uint32[]"},{"internalType":"uint128","name":"stashBalance","type":"uint128"},{"internalType":"uint32","name":"slashingSpans","type":"uint32"}],"internalType":"struct Types.OracleData","name":"_staking","type":"tuple"}],"name":"reportRelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_quorum","type":"uint8"},{"internalType":"uint64","name":"_eraId","type":"uint64"}],"name":"softenQuorum","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50611545806100206000396000f3fe608060405234801561001057600080fd5b50600436106100785760003560e01c806338151cde1461007d5780633fd2c16a1461009f578063485cc955146100ca5780634b660419146100df57806351506ed4146100f257806389b8036114610105578063b75b518c14610121578063cb35cf3114610129575b600080fd5b60005461008a9060ff1681565b60405190151581526020015b60405180910390f35b6004546100b2906001600160a01b031681565b6040516001600160a01b039091168152602001610096565b6100dd6100d83660046108f7565b61013c565b005b6005546100b2906001600160a01b031681565b6100dd61010036600461093f565b6101c6565b61008a6101133660046109a7565b600354600190911b16151590565b6100dd6103dc565b6100dd6101373660046109c0565b6103fd565b6004546001600160a01b0316156101985760405162461bcd60e51b815260206004820152601b60248201527a13d49050d3114e881053149150511657d253925512505312569151602a1b60448201526064015b60405180910390fd5b600480546001600160a01b039384166001600160a01b03199182161790915560058054929093169116179055565b6004546001600160a01b031633146101dd57600080fd5b6003546001851b90808216156102315760405162461bcd60e51b815260206004820152601960248201527813d49050d3114e881053149150511657d4d550935255151151603a1b604482015260640161018f565b1760035560005460ff1615610245576103d6565b600060ff198260405160200161025b9190610bd1565b60408051601f198184030181529190528051602090910120600154911691506000905b80821080156102b857506102b8836001848154811061029f5761029f610ccc565b90600052602060002001546105ee90919063ffffffff16565b156102cd576102c682610cf8565b915061027e565b8082101561035757856102fa600184815481106102ec576102ec610ccc565b906000526020600020015490565b610305906001610d13565b60ff16106103245761031f8561031a86610ef1565b6105fa565b6103d2565b6001828154811061033757610337610ccc565b906000526020600020016000815461034e90610cf8565b909155506103d2565b856001141561036d5761031f8561031a86610ef1565b60016103798482610fc8565b8154600181810184556000938452602084209091019190915560028054918201815590915284906007027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace016103cf82826112a5565b50505b5050505b50505050565b6004546001600160a01b031633146103f357600080fd5b6103fb61066e565b565b6004546001600160a01b0316331461041457600080fd5b6000806104238460ff16610695565b9150915081156103d657600061043882610774565b60408051610120810182528254815260018301546020820152600283015490929183019060ff16600381111561047057610470610a17565b600381111561048157610481610a17565b815260028201546001600160801b0361010090910481166020808401919091526003840154909116604080840191909152600484018054825181850281018501909352808352606090940193919290919060009084015b8282101561052757600084815260209081902060408051808201909152908401546001600160801b0381168252600160801b90046001600160401b0316818301528252600190920191016104d8565b505050508152602001600582018054806020026020016040519081016040528092919081815260200182805480156105aa57602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff168152602001906004019060208260030104928301926001038202915080841161056d5790505b5050509183525050600691909101546001600160801b0381166020830152600160801b900463ffffffff1660409091015290506105e784826105fa565b5050505050565b60ff1991909116141590565b6005546040516255983560e51b81526001600160a01b0390911690630ab306a09061062b9085908590600401611429565b600060405180830381600087803b15801561064557600080fd5b505af1158015610659573d6000803e3d6000fd5b50506000805460ff1916600117905550505050565b60006003819055805460ff19168155610689906001906107b0565b6103fb600260006107d1565b600180546000918291908114156106ce57836106be60016000815481106102ec576102ec610ccc565b60ff161015946000945092505050565b806106e157506000936000199350915050565b60008060008060005b8581101561075357610708600182815481106102ec576102ec610ccc565b60ff16915061ffff83168210610743578261ffff168261ffff1614156107385761073184610cf8565b9350610743565b809450819250600093505b61074c81610cf8565b90506106ea565b50878261ffff1610158015610766575082155b989397509295505050505050565b6002546000908210610788576107886114f9565b6002828154811061079b5761079b610ccc565b90600052602060002090600702019050919050565b50805460008255906000526020600020908101906107ce91906107f2565b50565b50805460008255600702906000526020600020908101906107ce919061080b565b5b8082111561080757600081556001016107f3565b5090565b80821115610807576000808255600182018190556002820180546001600160881b03191690556003820180546001600160801b03191690556108506004830182610879565b61085e600583016000610897565b506006810180546001600160a01b031916905560070161080b565b50805460008255906000526020600020908101906107ce91906108bc565b5080546000825560070160089004906000526020600020908101906107ce91906107f2565b5b808211156108075780546001600160c01b03191681556001016108bd565b80356001600160a01b03811681146108f257600080fd5b919050565b6000806040838503121561090a57600080fd5b610913836108db565b9150610921602084016108db565b90509250929050565b6001600160401b03811681146107ce57600080fd5b6000806000806080858703121561095557600080fd5b8435935060208501359250604085013561096e8161092a565b915060608501356001600160401b0381111561098957600080fd5b8501610120818803121561099c57600080fd5b939692955090935050565b6000602082840312156109b957600080fd5b5035919050565b600080604083850312156109d357600080fd5b823560ff811681146109e457600080fd5b915060208301356109f48161092a565b809150509250929050565b600481106107ce57600080fd5b80356108f2816109ff565b634e487b7160e01b600052602160045260246000fd5b60048110610a4b57634e487b7160e01b600052602160045260246000fd5b9052565b6001600160801b03811681146107ce57600080fd5b80356108f281610a4f565b6001600160801b03169052565b6000808335601e19843603018112610a9357600080fd5b83016020810192503590506001600160401b03811115610ab257600080fd5b8060061b3603831315610ac457600080fd5b9250929050565b8183526000602080850194508260005b85811015610b26578135610aee81610a4f565b6001600160801b0316875281830135610b068161092a565b6001600160401b0316878401526040968701969190910190600101610adb565b509495945050505050565b6000808335601e19843603018112610b4857600080fd5b83016020810192503590506001600160401b03811115610b6757600080fd5b8060051b3603831315610ac457600080fd5b63ffffffff811681146107ce57600080fd5b80356108f281610b79565b8183526000602080850194508260005b85811015610b26578135610bb981610b79565b63ffffffff1687529582019590820190600101610ba6565b6020815281356020820152602082013560408201526000610bf460408401610a0c565b610c016060840182610a2d565b50610c0e60608401610a64565b610c1b6080840182610a6f565b50610c2860808401610a64565b610c3560a0840182610a6f565b50610c4360a0840184610a7c565b6101208060c0860152610c5b61014086018385610acb565b9250610c6a60c0870187610b31565b868503601f190160e08801529250610c83848483610b96565b935050610c9260e08701610a64565b9150610100610ca381870184610a6f565b610cae818801610b8b565b925050610cc28186018363ffffffff169052565b5090949350505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415610d0c57610d0c610ce2565b5060010190565b600060ff821660ff84168060ff03821115610d3057610d30610ce2565b019392505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715610d7057610d70610d38565b60405290565b60405161012081016001600160401b0381118282101715610d7057610d70610d38565b604051601f8201601f191681016001600160401b0381118282101715610dc157610dc1610d38565b604052919050565b60006001600160401b03821115610de257610de2610d38565b5060051b60200190565b600082601f830112610dfd57600080fd5b81356020610e12610e0d83610dc9565b610d99565b82815260069290921b84018101918181019086841115610e3157600080fd5b8286015b84811015610e825760408189031215610e4e5760008081fd5b610e56610d4e565b8135610e6181610a4f565b815281850135610e708161092a565b81860152835291830191604001610e35565b509695505050505050565b600082601f830112610e9e57600080fd5b81356020610eae610e0d83610dc9565b82815260059290921b84018101918181019086841115610ecd57600080fd5b8286015b84811015610e82578035610ee481610b79565b8352918301918301610ed1565b60006101208236031215610f0457600080fd5b610f0c610d76565b8235815260208301356020820152610f2660408401610a0c565b6040820152610f3760608401610a64565b6060820152610f4860808401610a64565b608082015260a08301356001600160401b0380821115610f6757600080fd5b610f7336838701610dec565b60a084015260c0850135915080821115610f8c57600080fd5b50610f9936828601610e8d565b60c083015250610fab60e08401610a64565b60e0820152610100610fbe818501610b8b565b9082015292915050565b60008219821115610fdb57610fdb610ce2565b500190565b60008135610fed816109ff565b92915050565b6004821061101157634e487b7160e01b600052602160045260246000fd5b60ff1981541660ff831681178255505050565b60008135610fed81610a4f565b80546001600160801b0319166001600160801b0392909216919091179055565b6000808335601e1984360301811261106857600080fd5b8301803591506001600160401b0382111561108257600080fd5b6020019150600681901b3603821315610ac457600080fd5b81356110a581610a4f565b6110af8183611031565b5060208201356110be8161092a565b8154600160801b600160c01b03191660809190911b600160801b600160c01b031617905550565b600160401b8311156110f9576110f9610d38565b805483825580841015611130576000828152602081208581019083015b8082101561112c57828255600182019150611116565b5050505b5060008181526020812083915b858110156111625761114f838361109a565b604092909201916001918201910161113d565b505050505050565b6000808335601e1984360301811261118157600080fd5b8301803591506001600160401b0382111561119b57600080fd5b6020019150600581901b3603821315610ac457600080fd5b60008135610fed81610b79565b600160401b8311156111d4576111d4610d38565b80548382558084101561123b576000828152602081206007860160031c81016007840160031c82019150601c8760021b168015611222576000198083018054828460200360031b1c16815550505b505b8181101561123757828155600101611224565b5050505b506000818152602081208391805b868110156103d25761127d61125d856111b3565b845463ffffffff600386901b81811b801990931693909116901b16178455565b602084019350600482019150601c82111561129d57600091506001830192505b600101611249565b8135815560208201356001820155600281016112cc6112c660408501610fe0565b82610ff3565b6113016112db60608501611024565b828054610100600160881b03191660089290921b610100600160881b0316919091179055565b5061131a61131160808401611024565b60038301611031565b61132760a0830183611051565b6113358183600486016110e5565b505061134460c083018361116a565b6113528183600586016111c0565b50506006810161136d61136760e08501611024565b82611031565b6113a161137d61010085016111b3565b82805463ffffffff60801b191660809290921b63ffffffff60801b16919091179055565b505050565b600081518084526020808501945080840160005b83811015610b2657815180516001600160801b031688528301516001600160401b031683880152604090960195908201906001016113ba565b600081518084526020808501945080840160005b83811015610b2657815163ffffffff1687529582019590820190600101611407565b6001600160401b03831681526040602080830182905283518383015283015160608301528201516000906114606080840182610a2d565b50606083015161147360a0840182610a6f565b50608083015161148660c0840182610a6f565b5060a08301516101208060e08501526114a36101608501836113a6565b915060c0850151610100603f1986850301818701526114c284836113f3565b935060e087015191506114d783870183610a6f565b86015163ffffffff811661014087015291506114f09050565b50949350505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212204239672b17b63e869314787b4c466fe3878929ff0ffbe993fad2e0818738220264736f6c634300080a0033

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.