Skip to content

Commit

Permalink
feat: hardcode values in coinbase adapter
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Maldonado <pablo@umaproject.org>
  • Loading branch information
md0x committed Jun 17, 2024
1 parent b2d5cd8 commit 6fc7258
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 23 deletions.
30 changes: 12 additions & 18 deletions src/oracles/CoinbaseOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -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++;
Expand All @@ -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;
}
}
16 changes: 16 additions & 0 deletions test/mocks/MockCoinbaseOracle.sol
Original file line number Diff line number Diff line change
@@ -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;
}
}
10 changes: 7 additions & 3 deletions test/unit/CoinbaseOracle.sol
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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";
Expand All @@ -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";
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 3 additions & 2 deletions test/unit/CoinbaseSourceAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 6fc7258

Please sign in to comment.