ETH Price: $2,418.07 (-1.01%)

Transaction Decoder

Block:
11702535 at Jan-22-2021 01:56:50 AM +UTC
Transaction Fee:
0.047976042164909292 ETH $116.01
Gas Used:
133,638 Gas / 359.000001234 Gwei

Emitted Events:

255 MedianLINKUSD.LogMedianPrice( val=18393560000000000000, age=1611280610 )

Account State Difference:

  Address   Before After State Difference Code
0x41c0cCeC...1fa156f0B
0.551703874065 Eth
Nonce: 12965
0.503727831900090708 Eth
Nonce: 12966
0.047976042164909292
(F2Pool Old)
5,209.452062705190422366 Eth5,209.500038747355331658 Eth0.047976042164909292
0xbAd4212d...08963f17b

Execution Trace

MedianLINKUSD.poke( )
  • Null: 0x000...001.b4425067( )
  • Null: 0x000...001.754e203b( )
  • Null: 0x000...001.2018cab0( )
  • Null: 0x000...001.c24decfd( )
  • Null: 0x000...001.a35b3bfb( )
  • Null: 0x000...001.b303cb82( )
  • Null: 0x000...001.1034ac0f( )
  • Null: 0x000...001.9e5a69ed( )
  • Null: 0x000...001.3d0e8632( )
  • Null: 0x000...001.4948fb76( )
  • Null: 0x000...001.28409cbe( )
  • Null: 0x000...001.913abefa( )
  • Null: 0x000...001.31355e4d( )
    /// 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 MedianLINKUSD is Median {
        bytes32 public constant wat = "LINKUSD";
    
        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
            );
        }
    }