ETH Price: $2,486.76 (-0.99%)
Gas: 0.85 Gwei

Transaction Decoder

Block:
18350852 at Oct-14-2023 07:57:47 PM +UTC
Transaction Fee:
0.000799462421597048 ETH $1.99
Gas Used:
139,966 Gas / 5.711833028 Gwei

Emitted Events:

250 MedianRETHUSD.LogMedianPrice( val=1691201488504145000000, age=1697313467 )

Account State Difference:

  Address   Before After State Difference Code
(Titan Builder)
10.174548841632953769 Eth10.174550241292953769 Eth0.00000139966
0xDBF07B87...eBc78c8D4
2.406933203400218952 Eth
Nonce: 60861
2.406133740978621904 Eth
Nonce: 60862
0.000799462421597048
0xF86360f0...1C692b3D1

Execution Trace

MedianRETHUSD.poke( )
  • Null: 0x000...001.18446af4( )
  • Null: 0x000...001.30fc2144( )
  • Null: 0x000...001.088382e2( )
  • Null: 0x000...001.9dad912c( )
  • Null: 0x000...001.ee8f583e( )
  • Null: 0x000...001.09512b67( )
  • Null: 0x000...001.9183b0cd( )
  • Null: 0x000...001.197e8285( )
  • Null: 0x000...001.06ef9e61( )
  • Null: 0x000...001.bacbb824( )
  • Null: 0x000...001.85e8478e( )
  • Null: 0x000...001.9ab0c412( )
  • Null: 0x000...001.c4b81eed( )
    /// median.sol
    
    // Copyright (C) 2017-2020 Maker Ecosystem Growth Holdings, INC.
    
    // This program is free software: you can redistribute it and/or modify
    // it under the terms of the GNU Affero General Public License as published by
    // the Free Software Foundation, either version 3 of the License, or
    // (at your option) any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU Affero General Public License for more details.
    //
    // You should have received a copy of the GNU Affero General Public License
    // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    
    pragma solidity >=0.5.10;
    
    contract LibNote {
        event LogNote(
            bytes4   indexed  sig,
            address  indexed  usr,
            bytes32  indexed  arg1,
            bytes32  indexed  arg2,
            bytes             data
        ) anonymous;
    
        modifier note {
            _;
            assembly {
                // log an 'anonymous' event with a constant 6 words of calldata
                // and four indexed topics: selector, caller, arg1 and arg2
                let mark := msize()                         // end of memory ensures zero
                mstore(0x40, add(mark, 288))              // update free memory pointer
                mstore(mark, 0x20)                        // bytes type data offset
                mstore(add(mark, 0x20), 224)              // bytes size (padded)
                calldatacopy(add(mark, 0x40), 0, 224)     // bytes payload
                log4(mark, 288,                           // calldata
                     shl(224, shr(224, calldataload(0))), // msg.sig
                     caller(),                              // msg.sender
                     calldataload(4),                     // arg1
                     calldataload(36)                     // arg2
                    )
            }
        }
    }
    
    contract Median is LibNote {
    
        // --- Auth ---
        mapping (address => uint) public wards;
        function rely(address usr) external note auth { wards[usr] = 1; }
        function deny(address usr) external note auth { wards[usr] = 0; }
        modifier auth {
            require(wards[msg.sender] == 1, "Median/not-authorized");
            _;
        }
    
        uint128        val;
        uint32  public age;
        bytes32 public constant wat = "ethusd"; // You want to change this every deploy
        uint256 public bar = 1;
    
        // Authorized oracles, set by an auth
        mapping (address => uint256) public orcl;
    
        // Whitelisted contracts, set by an auth
        mapping (address => uint256) public bud;
    
        // Mapping for at most 256 oracles
        mapping (uint8 => address) public slot;
    
        modifier toll { require(bud[msg.sender] == 1, "Median/contract-not-whitelisted"); _;}
    
        event LogMedianPrice(uint256 val, uint256 age);
    
        //Set type of Oracle
        constructor() public {
            wards[msg.sender] = 1;
        }
    
        function read() external view toll returns (uint256) {
            require(val > 0, "Median/invalid-price-feed");
            return val;
        }
    
        function peek() external view toll returns (uint256,bool) {
            return (val, val > 0);
        }
    
        function recover(uint256 val_, uint256 age_, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
            return ecrecover(
                keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encodePacked(val_, age_, wat)))),
                v, r, s
            );
        }
    
        function poke(
            uint256[] calldata val_, uint256[] calldata age_,
            uint8[] calldata v, bytes32[] calldata r, bytes32[] calldata s) external
        {
            require(val_.length == bar, "Median/bar-too-low");
    
            uint256 bloom = 0;
            uint256 last = 0;
            uint256 zzz = age;
    
            for (uint i = 0; i < val_.length; i++) {
                // Validate the values were signed by an authorized oracle
                address signer = recover(val_[i], age_[i], v[i], r[i], s[i]);
                // Check that signer is an oracle
                require(orcl[signer] == 1, "Median/invalid-oracle");
                // Price feed age greater than last medianizer age
                require(age_[i] > zzz, "Median/stale-message");
                // Check for ordered values
                require(val_[i] >= last, "Median/messages-not-in-order");
                last = val_[i];
                // Bloom filter for signer uniqueness
                uint8 sl = uint8(uint256(signer) >> 152);
                require((bloom >> sl) % 2 == 0, "Median/oracle-already-signed");
                bloom += uint256(2) ** sl;
            }
    
            val = uint128(val_[val_.length >> 1]);
            age = uint32(block.timestamp);
    
            emit LogMedianPrice(val, age);
        }
    
        function lift(address[] calldata a) external note auth {
            for (uint i = 0; i < a.length; i++) {
                require(a[i] != address(0), "Median/no-oracle-0");
                uint8 s = uint8(uint256(a[i]) >> 152);
                require(slot[s] == address(0), "Median/signer-already-exists");
                orcl[a[i]] = 1;
                slot[s] = a[i];
            }
        }
    
        function drop(address[] calldata a) external note auth {
           for (uint i = 0; i < a.length; i++) {
                orcl[a[i]] = 0;
                slot[uint8(uint256(a[i]) >> 152)] = address(0);
           }
        }
    
        function setBar(uint256 bar_) external note auth {
            require(bar_ > 0, "Median/quorum-is-zero");
            require(bar_ % 2 != 0, "Median/quorum-not-odd-number");
            bar = bar_;
        }
    
        function kiss(address a) external note auth {
            require(a != address(0), "Median/no-contract-0");
            bud[a] = 1;
        }
    
        function diss(address a) external note auth {
            bud[a] = 0;
        }
    
        function kiss(address[] calldata a) external note auth {
            for(uint i = 0; i < a.length; i++) {
                require(a[i] != address(0), "Median/no-contract-0");
                bud[a[i]] = 1;
            }
        }
    
        function diss(address[] calldata a) external note auth {
            for(uint i = 0; i < a.length; i++) {
                bud[a[i]] = 0;
            }
        }
    }
    
    contract MedianRETHUSD is Median {
        bytes32 public constant wat = "RETHUSD";
    
        function recover(uint256 val_, uint256 age_, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
            return ecrecover(
                keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encodePacked(val_, age_, wat)))),
                v, r, s
            );
        }
    }