Skip to content

Commit

Permalink
initial AstriaOracle and MockAggregator contract
Browse files Browse the repository at this point in the history
  • Loading branch information
noot committed Dec 12, 2024
1 parent 9da098e commit 0401aa1
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 107 deletions.
67 changes: 2 additions & 65 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,3 @@
## Foundry
# astria-oracle-contracts

**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.**

Foundry consists of:

- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools).
- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network.
- **Chisel**: Fast, utilitarian, and verbose solidity REPL.

## Documentation

https://book.getfoundry.sh/

## Usage

### Build

```shell
$ forge build
```

### Test

```shell
$ forge test
```

### Format

```shell
$ forge fmt
```

### Gas Snapshots

```shell
$ forge snapshot
```

### Anvil

```shell
$ anvil
```

### Deploy

```shell
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
```

### Cast

```shell
$ cast <subcommand>
```

### Help

```shell
$ forge --help
$ anvil --help
$ cast --help
```
Repository of contracts used for Astria's native oracle.
8 changes: 4 additions & 4 deletions script/Counter.s.sol → script/AstriaOracle.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
pragma solidity ^0.8.13;

import {Script, console} from "forge-std/Script.sol";
import {Counter} from "../src/Counter.sol";
import {AstriaOracle} from "../src/AstriaOracle.sol";

contract CounterScript is Script {
Counter public counter;
contract AstriaOracleScript is Script {
AstriaOracle public astriaOracle;

function setUp() public {}

function run() public {
vm.startBroadcast();

counter = new Counter();
astriaOracle = new AstriaOracle();

vm.stopBroadcast();
}
Expand Down
32 changes: 32 additions & 0 deletions src/AstriaOracle.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT or Apache-2.0
pragma solidity ^0.8.21;

// Core oracle contract for Astria's native oracle.
// This contract stores the price data for every currency pair supported by the oracle.
contract AstriaOracle {
// mapping of block number to mapping of hash of the currency pair string to its price data
mapping(uint256 => mapping(bytes32 => PriceData)) public priceData;

// mapping of hash of the currency pair string to the number of decimals the price is represented in
mapping(bytes32 => uint8) public decimals;

// block number of the latest price data update
uint256 public latestBlockNumber;

struct PriceData {
uint128 price;
uint256 timestamp;
}

function setDecimals(bytes32 _currencyPair, uint8 _decimals) public {
decimals[_currencyPair] = _decimals;
}

function updatePriceData(bytes32[] memory _currencyPairs, uint128[] memory _prices) public {
require(_currencyPairs.length == _prices.length, "currency pair and price length mismatch");
latestBlockNumber = block.number;
for (uint256 i = 0; i < _currencyPairs.length; i++) {
priceData[latestBlockNumber][_currencyPairs[i]] = PriceData(_prices[i], block.timestamp);
}
}
}
14 changes: 0 additions & 14 deletions src/Counter.sol

This file was deleted.

74 changes: 74 additions & 0 deletions src/MockAggregator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
pragma solidity ^0.8.21;

import {AggregatorV2V3Interface} from "./interfaces/AggregatorV2V3Interface.sol";
import {AstriaOracle} from "./AstriaOracle.sol";

// Mock currency pair aggregator contract for a single currency pair.
contract MockAggregator is AggregatorV2V3Interface {
// core oracle contract
AstriaOracle immutable public oracle;

// currency pair hash
bytes32 immutable public currencyPairHash;

constructor(AstriaOracle _oracle, bytes32 _currencyPairHash) {
oracle = _oracle;
currencyPairHash = _currencyPairHash;
}

/* v2 aggregator interface */

function latestAnswer() external view returns (int256) {
(uint128 price, ) = oracle.priceData(oracle.latestBlockNumber(), currencyPairHash);
return int256(uint256(price));
}

function latestTimestamp() external view returns (uint256) {
(, uint256 timestamp) = oracle.priceData(oracle.latestBlockNumber(), currencyPairHash);
return timestamp;
}

function latestRound() external view returns (uint256) {
return oracle.latestBlockNumber();
}

function getAnswer(uint256 roundId) external view returns (int256) {
(uint128 price, ) = oracle.priceData(roundId, currencyPairHash);
return int256(uint256(price));
}

function getTimestamp(uint256 roundId) external view returns (uint256) {
(, uint256 timestamp) = oracle.priceData(roundId, currencyPairHash);
return timestamp;
}

/* v3 aggregator interface */

function decimals() external view returns (uint8) {
return oracle.decimals(currencyPairHash);
}

function description() external pure returns (string memory) {
return "MockAggregator";
}

function version() external pure returns (uint256) {
return 0;
}

function getRoundData(
uint80 _roundId
) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) {
(uint128 price, uint256 timestamp) = oracle.priceData(_roundId, currencyPairHash);
return (_roundId, int256(uint256(price)), timestamp, timestamp, _roundId);
}

function latestRoundData()
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) {
roundId = uint80(oracle.latestBlockNumber());
(uint128 price, uint256 timestamp) = oracle.priceData(roundId, currencyPairHash);
return (roundId, int256(uint256(price)), timestamp, timestamp, roundId);
}
}
20 changes: 20 additions & 0 deletions src/interfaces/AggregatorInterface.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// https://github.com/smartcontractkit/chainlink/blob/dde17518ff7f3dd3fe1d53614f211357944516f0/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol
// solhint-disable-next-line interface-starts-with-i
interface AggregatorInterface {
function latestAnswer() external view returns (int256);

function latestTimestamp() external view returns (uint256);

function latestRound() external view returns (uint256);

function getAnswer(uint256 roundId) external view returns (int256);

function getTimestamp(uint256 roundId) external view returns (uint256);

event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);

event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
}
9 changes: 9 additions & 0 deletions src/interfaces/AggregatorV2V3Interface.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {AggregatorInterface} from "./AggregatorInterface.sol";
import {AggregatorV3Interface} from "./AggregatorV3Interface.sol";

// https://github.com/smartcontractkit/chainlink/blob/4eca0ec7a7fcf23fb31d0df1581cd7721deb7507/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol
// solhint-disable-next-line interface-starts-with-i
interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}
21 changes: 21 additions & 0 deletions src/interfaces/AggregatorV3Interface.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// https://github.com/smartcontractkit/chainlink/blob/dde17518ff7f3dd3fe1d53614f211357944516f0/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol
// solhint-disable-next-line interface-starts-with-i
interface AggregatorV3Interface {
function decimals() external view returns (uint8);

function description() external view returns (string memory);

function version() external view returns (uint256);

function getRoundData(
uint80 _roundId
) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);

function latestRoundData()
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}
24 changes: 0 additions & 24 deletions test/Counter.t.sol

This file was deleted.

0 comments on commit 0401aa1

Please sign in to comment.