From 6fc72586756e1ca42a675a5393b6fdfb9191ef40 Mon Sep 17 00:00:00 2001 From: Pablo Maldonado Date: Mon, 17 Jun 2024 18:22:11 +0100 Subject: [PATCH] feat: hardcode values in coinbase adapter Signed-off-by: Pablo Maldonado --- src/oracles/CoinbaseOracle.sol | 30 ++++++++++++----------------- test/mocks/MockCoinbaseOracle.sol | 16 +++++++++++++++ test/unit/CoinbaseOracle.sol | 10 +++++++--- test/unit/CoinbaseSourceAdapter.sol | 5 +++-- 4 files changed, 38 insertions(+), 23 deletions(-) create mode 100644 test/mocks/MockCoinbaseOracle.sol diff --git a/src/oracles/CoinbaseOracle.sol b/src/oracles/CoinbaseOracle.sol index ea708a4..a0b25d2 100644 --- a/src/oracles/CoinbaseOracle.sol +++ b/src/oracles/CoinbaseOracle.sol @@ -8,9 +8,7 @@ import {IAggregatorV3SourceCoinbase} from "../interfaces/coinbase/IAggregatorV3S * @notice A smart contract that serves as an oracle for price data reported by a designated reporter. */ contract CoinbaseOracle is IAggregatorV3SourceCoinbase { - address immutable reporter; - uint8 public immutable decimals; - string public dataKind; + uint8 public immutable decimals = 6; struct RoundData { int256 answer; @@ -22,22 +20,10 @@ contract CoinbaseOracle is IAggregatorV3SourceCoinbase { mapping(uint80 => RoundData) rounds; } - mapping(string => PriceData) private prices; + mapping(string => PriceData) internal prices; event PricePushed(string indexed ticker, uint80 indexed roundId, int256 price, uint256 timestamp); - /** - * @notice Constructor to initialize the CoinbaseOracle contract. - * @param _decimals The number of decimals in the reported price. - * @param _dataKind The kind of data that the oracle will report, expected to be "prices" but open for changes. - * @param _reporter The address of the reporter allowed to push price data. - */ - constructor(uint8 _decimals, string memory _dataKind, address _reporter) { - decimals = _decimals; - reporter = _reporter; - dataKind = _dataKind; - } - /** * @notice Returns the latest round data for a given ticker. * @param ticker The ticker symbol to retrieve the data for. @@ -91,13 +77,13 @@ contract CoinbaseOracle is IAggregatorV3SourceCoinbase { uint256 price // 6 decimals ) = abi.decode(priceData, (string, uint256, string, uint256)); - require(keccak256(abi.encodePacked(kind)) == keccak256(abi.encodePacked(dataKind)), "Invalid kind."); + require(keccak256(abi.encodePacked(kind)) == keccak256(abi.encodePacked("prices")), "Invalid kind."); PriceData storage priceDataStruct = prices[ticker]; uint256 latestTimestamp = priceDataStruct.rounds[priceDataStruct.lastRoundId].timestamp; require(timestamp > latestTimestamp, "Invalid timestamp."); - require(recoverSigner(priceData, signature) == reporter, "Invalid signature."); + require(recoverSigner(priceData, signature) == reporter(), "Invalid signature."); require(price <= uint256(type(int256).max), "Price exceeds max value."); priceDataStruct.lastRoundId++; @@ -117,4 +103,12 @@ contract CoinbaseOracle is IAggregatorV3SourceCoinbase { bytes32 hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(message))); return ecrecover(hash, v, r, s); } + + /** + * @notice Returns the address of the reporter. + * @return The address of the reporter. + */ + function reporter() public view virtual returns (address) { + return 0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC; + } } diff --git a/test/mocks/MockCoinbaseOracle.sol b/test/mocks/MockCoinbaseOracle.sol new file mode 100644 index 0000000..d712d6a --- /dev/null +++ b/test/mocks/MockCoinbaseOracle.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.17; + +import {CoinbaseOracle} from "../../src/oracles/CoinbaseOracle.sol"; + +contract MockCoinbaseOracle is CoinbaseOracle { + address public customReporter; + + constructor(address _customReporter) { + customReporter = _customReporter; + } + + function reporter() public view override returns (address) { + return customReporter; + } +} diff --git a/test/unit/CoinbaseOracle.sol b/test/unit/CoinbaseOracle.sol index 91854ca..36b7fb8 100644 --- a/test/unit/CoinbaseOracle.sol +++ b/test/unit/CoinbaseOracle.sol @@ -1,6 +1,7 @@ import {CommonTest} from "../Common.sol"; import {IAggregatorV3} from "src/interfaces/chainlink/IAggregatorV3.sol"; import {CoinbaseOracle} from "src/oracles/CoinbaseOracle.sol"; +import {MockCoinbaseOracle} from "../mocks/MockCoinbaseOracle.sol"; contract CoinbaseOracleTest is CommonTest { CoinbaseOracle public coinbaseOracle; @@ -12,7 +13,7 @@ contract CoinbaseOracleTest is CommonTest { string[] public tickers; function setUp() public { - coinbaseOracle = new CoinbaseOracle(6, "prices", coinbaseProdReporter); + coinbaseOracle = new CoinbaseOracle(); tickers = new string[](13); tickers[0] = "BTC"; tickers[1] = "ETH"; @@ -31,11 +32,11 @@ contract CoinbaseOracleTest is CommonTest { (address _reporter, uint256 _reporterPk) = makeAddrAndKey("reporter"); reporter = _reporter; reporterPk = _reporterPk; - coinbaseOracle = new CoinbaseOracle(6, "prices", reporter); + coinbaseOracle = new CoinbaseOracle(); } function testPushPricesProd() public { - coinbaseOracle = new CoinbaseOracle(6, "prices", coinbaseProdReporter); + coinbaseOracle = new CoinbaseOracle(); string[] memory fetchCommands = new string[](3); fetchCommands[0] = "node"; fetchCommands[1] = "--no-warnings"; @@ -80,14 +81,17 @@ contract CoinbaseOracleTest is CommonTest { } function testPushPriceETH() public { + coinbaseOracle = new MockCoinbaseOracle(reporter); _testPushPrice(tickers[1], 10e6); } function testPushPriceBTC() public { + coinbaseOracle = new MockCoinbaseOracle(reporter); _testPushPrice(tickers[0], 20e6); } function testPushPriceBothTickers() public { + coinbaseOracle = new MockCoinbaseOracle(reporter); _testPushPrice(tickers[1], 10e6); vm.warp(block.timestamp + 1); _testPushPrice(tickers[0], 20e6); diff --git a/test/unit/CoinbaseSourceAdapter.sol b/test/unit/CoinbaseSourceAdapter.sol index 842c5e7..815b154 100644 --- a/test/unit/CoinbaseSourceAdapter.sol +++ b/test/unit/CoinbaseSourceAdapter.sol @@ -8,6 +8,7 @@ import {CoinbaseSourceAdapter} from "../../src/adapters/source-adapters/Coinbase import {DecimalLib} from "../../src/adapters/lib/DecimalLib.sol"; import {IAggregatorV3SourceCoinbase} from "../../src/interfaces/coinbase/IAggregatorV3SourceCoinbase.sol"; import {CoinbaseOracle} from "../../src/oracles/CoinbaseOracle.sol"; +import {MockCoinbaseOracle} from "../mocks/MockCoinbaseOracle.sol"; contract TestedSourceAdapter is CoinbaseSourceAdapter, BaseController { constructor(IAggregatorV3SourceCoinbase source, string memory ticker) CoinbaseSourceAdapter(source, ticker) {} @@ -45,7 +46,7 @@ contract CoinbaseSourceAdapterTest is CommonTest { (address _reporter, uint256 _reporterPk) = makeAddrAndKey("reporter"); reporter = _reporter; reporterPk = _reporterPk; - coinbase = new CoinbaseOracle(6, "prices", reporter); + coinbase = new MockCoinbaseOracle(reporter); sourceAdapter = new TestedSourceAdapter(IAggregatorV3SourceCoinbase(address(coinbase)), ticker); // Push some prices to the oracle @@ -120,7 +121,7 @@ contract CoinbaseSourceAdapterTest is CommonTest { } function testNonHistoricalData() public { - coinbase = new CoinbaseOracle(6, "prices", reporter); + coinbase = new MockCoinbaseOracle(reporter); sourceAdapter = new TestedSourceAdapter(IAggregatorV3SourceCoinbase(address(coinbase)), ticker); // Push only one price to the oracle