编译器
0.8.23+commit.f704f362
文件 1 的 5:BatchUpdateRate.sol
pragma solidity 0.8.23;
import "FungifyPriceFeed.sol";
import "Ownable.sol";
contract BatchUpdateRate is Ownable {
mapping (address => uint) public wards;
function rely(address guy) external onlyOwner { wards[guy] = 1; }
function deny(address guy) external onlyOwner { wards[guy] = 0; }
modifier auth {
if (wards[msg.sender] == 0) {
revert Unauthorized();
}
_;
}
event FailedToUpdate(FungifyPriceFeed feed, int256 answer);
error UnequalParamLengths();
error Unauthorized();
constructor() Ownable(msg.sender) {}
function batchSetAnswer(FungifyPriceFeed[] memory priceFeeds, int256[] calldata newAnswers) external auth {
uint numFeeds = priceFeeds.length;
if (numFeeds != newAnswers.length) {
revert UnequalParamLengths();
}
for (uint i = 0; i < numFeeds;) {
try priceFeeds[i].updateRate(newAnswers[i]) {
} catch {
emit FailedToUpdate(priceFeeds[i], newAnswers[i]);
}
unchecked { i++; }
}
}
}
文件 2 的 5:Context.sol
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 5:FungifyPriceFeed.sol
pragma solidity 0.8.23;
import "Upgradeable.sol";
contract FungifyPriceFeed is Upgradeable {
event RateUpdated(int256 oldRate, int256 newRate, int256 inputRate);
error UnderTimeAndPriceDeviationMinimums();
error OverPriceDeviationMaximum();
error Unauthorized();
error AdditionOverflow();
error SubtractionOverflow();
error LessThanTwoPeriods();
mapping (address => uint256) public wards;
function rely(address guy) external onlyOwner { wards[guy] = 1; }
function deny(address guy) external onlyOwner { wards[guy] = 0; }
modifier auth {
if (wards[msg.sender] == 0) {
revert Unauthorized();
}
_;
}
int256 public constant ONE_IN_BIP = 10000;
uint8 public immutable _decimals;
int256 public latestAnswer;
uint256 public latestUpdateTime;
int256 public minPriceDeviationBip;
uint256 public stalePriceTime;
int256 public emaPeriods;
int public maxPriceDeviationBip;
constructor(uint8 decimals_) {
_decimals = decimals_;
}
function initialize(int256 startingRate_) external {
if (msg.sender != owner()) {
revert Unauthorized();
}
latestAnswer = startingRate_;
latestUpdateTime = block.timestamp;
stalePriceTime = 7200;
minPriceDeviationBip = 200;
maxPriceDeviationBip = 3500;
emaPeriods = 3;
emit RateUpdated(0, startingRate_, startingRate_);
}
function decimals() public view returns (uint8) {
return _decimals;
}
function latestRoundData()
public
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
) {
return (0, latestAnswer, 0, latestUpdateTime, 0);
}
function underMinPriceDeviation(int256 newRate, int256 oldRate) public view returns(bool) {
int256 allowedDeviation = oldRate * minPriceDeviationBip / ONE_IN_BIP;
if (newRate > oldRate + allowedDeviation || newRate < oldRate - allowedDeviation) {
return false;
} else {
return true;
}
}
function overMaxPriceDeviation(int256 newRate, int256 oldRate) public view returns(bool) {
int allowedDeviation = oldRate * maxPriceDeviationBip / ONE_IN_BIP;
if (newRate > oldRate + allowedDeviation || newRate < oldRate - allowedDeviation) {
return true;
} else {
return false;
}
}
function updateRate(int256 newRate_) public auth {
int256 oldEMA = latestAnswer;
if (overMaxPriceDeviation(newRate_, oldEMA)) {
revert OverPriceDeviationMaximum();
}
if (underMinPriceDeviation(newRate_, oldEMA) && block.timestamp < latestUpdateTime + stalePriceTime) {
revert UnderTimeAndPriceDeviationMinimums();
}
int256 newEMA = updateEMA(oldEMA, newRate_);
latestAnswer = newEMA;
latestUpdateTime = block.timestamp;
emit RateUpdated(oldEMA, newEMA, newRate_);
}
function updateEMA(int256 currentEMA, int256 newValue) internal view returns (int256) {
int256 emaPeriods_ = emaPeriods;
int256 newEMA =
sub(
add(
newValue * 2 / (emaPeriods_ + 1),
currentEMA
),
currentEMA * 2 / (emaPeriods_ + 1)
);
return newEMA;
}
function setStalePriceTime(uint _stalePriceTime) external onlyOwner {
stalePriceTime = _stalePriceTime;
}
function setMinPriceDeviationBip(int _minPriceDeviationBip) external onlyOwner {
minPriceDeviationBip = _minPriceDeviationBip;
}
function setMaxPriceDeviationBip(int _maxPriceDeviationBip) external onlyOwner {
maxPriceDeviationBip = _maxPriceDeviationBip;
}
function setEMAPeriods(int _emaPeriods) external onlyOwner {
if (_emaPeriods < 2) {
revert LessThanTwoPeriods();
}
emaPeriods = _emaPeriods;
}
function adminUpdateRate(int256 newRate_) external onlyOwner {
int256 oldRate = latestAnswer;
latestAnswer = newRate_;
latestUpdateTime = block.timestamp;
emit RateUpdated(oldRate, newRate_, newRate_);
}
function add(int256 a, int256 b) internal pure returns (int256) {
int256 c;
unchecked { c = a + b; }
if (!((b >= 0 && c >= a) || (b < 0 && c < a))) {
revert AdditionOverflow();
}
return c;
}
function sub(int256 a, int256 b) internal pure returns (int256) {
int256 c;
unchecked { c = a - b; }
if (!((b >= 0 && c <= a) || (b < 0 && c > a))) {
revert SubtractionOverflow();
}
return c;
}
}
文件 4 的 5:Ownable.sol
pragma solidity ^0.8.20;
import {Context} from "Context.sol";
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 5 的 5:Upgradeable.sol
pragma solidity 0.8.23;
import {Ownable} from "Ownable.sol";
contract Upgradeable is Ownable {
address public implementation;
constructor() Ownable(msg.sender) {}
}
{
"compilationTarget": {
"BatchUpdateRate.sol": "BatchUpdateRate"
},
"evmVersion": "shanghai",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnequalParamLengths","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract FungifyPriceFeed","name":"feed","type":"address"},{"indexed":false,"internalType":"int256","name":"answer","type":"int256"}],"name":"FailedToUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"contract FungifyPriceFeed[]","name":"priceFeeds","type":"address[]"},{"internalType":"int256[]","name":"newAnswers","type":"int256[]"}],"name":"batchSetAnswer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"deny","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"rely","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]