Transaction Hash:
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 | ||
---|---|---|---|---|---|
0x4838B106...B0BAD5f97
Miner
| (Titan Builder) | 10.174548841632953769 Eth | 10.174550241292953769 Eth | 0.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( )
poke[Median (ln:99)]
recover[Median (ln:111)]
ecrecover[Median (ln:93)]
LogMedianPrice[Median (ln:128)]
/// 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 ); } }