Skip to content

Commit

Permalink
BCI-3349: Add latest_answer (#457)
Browse files Browse the repository at this point in the history
* initial

* format

* fix tests
  • Loading branch information
augustbleeds authored Jun 11, 2024
1 parent 2a874f6 commit fa64980
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 4 deletions.
7 changes: 7 additions & 0 deletions contracts/src/emergency/sequencer_uptime_feed.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,13 @@ mod SequencerUptimeFeed {
fn decimals(self: @ContractState) -> u8 {
0_u8
}

fn latest_answer(self: @ContractState) -> u128 {
self._require_read_access();
let latest_round_id = self._latest_round_id.read();
let round_transmission = self._round_transmissions.read(latest_round_id);
round_transmission.answer
}
}

#[constructor]
Expand Down
8 changes: 8 additions & 0 deletions contracts/src/ocr2/aggregator.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ trait IAggregator<TContractState> {
fn round_data(self: @TContractState, round_id: u128) -> Round;
fn description(self: @TContractState) -> felt252;
fn decimals(self: @TContractState) -> u8;
fn latest_answer(self: @TContractState) -> u128;
}

#[derive(Copy, Drop, Serde)]
Expand Down Expand Up @@ -374,6 +375,13 @@ mod Aggregator {
self._require_read_access();
self._decimals.read()
}

fn latest_answer(self: @ContractState) -> u128 {
self._require_read_access();
let latest_round_id = self._latest_aggregator_round_id.read();
let transmission = self._transmissions.read(latest_round_id);
transmission.answer
}
}

// ---
Expand Down
8 changes: 8 additions & 0 deletions contracts/src/ocr2/aggregator_proxy.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ trait IAggregatorProxy<TContractState> {
fn round_data(self: @TContractState, round_id: felt252) -> Round;
fn description(self: @TContractState) -> felt252;
fn decimals(self: @TContractState) -> u8;
fn latest_answer(self: @TContractState) -> u128;
}

#[starknet::interface]
Expand Down Expand Up @@ -152,6 +153,13 @@ mod AggregatorProxy {
let aggregator = IAggregatorDispatcher { contract_address: phase.aggregator };
aggregator.decimals()
}

fn latest_answer(self: @ContractState) -> u128 {
self._require_read_access();
let phase = self._current_phase.read();
let aggregator = IAggregatorDispatcher { contract_address: phase.aggregator };
aggregator.latest_answer()
}
}

#[abi(embed_v0)]
Expand Down
6 changes: 6 additions & 0 deletions contracts/src/ocr2/mocks/mock_aggregator.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,11 @@ mod MockAggregator {
fn description(self: @ContractState) -> felt252 {
'mock'
}

fn latest_answer(self: @ContractState) -> u128 {
let latest_round_id = self._latest_aggregator_round_id.read();
let transmission = self._transmissions.read(latest_round_id);
transmission.answer
}
}
}
20 changes: 20 additions & 0 deletions contracts/src/tests/test_aggregator_proxy.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ fn test_query_latest_round_data() {
assert(round.block_num == 1, 'block_num should be 1');
assert(round.started_at == 9, 'started_at should be 9');
assert(round.updated_at == 8, 'updated_at should be 8');

// latest_answer matches up with latest_round_data
let latest_answer = AggregatorProxyImpl::latest_answer(@state);
assert(latest_answer == 10, '(latest) answer should be 10');
}

#[test]
Expand All @@ -134,6 +138,22 @@ fn test_query_latest_round_data_without_access() {
AggregatorProxyImpl::latest_round_data(@state);
}

#[test]
#[should_panic(expected: ('user does not have read access',))]
fn test_query_latest_answer_without_access() {
let (owner, mockAggregatorAddr, mockAggregator, _, _) = setup();
let mut state = STATE();
// init aggregator proxy with mock aggregator
AggregatorProxy::constructor(ref state, owner, mockAggregatorAddr);
state.add_access(owner);
// insert round into mock aggregator
mockAggregator.set_latest_round_data(10, 1, 9, 8);
// set caller to non-owner address with no read access
set_caller_address(contract_address_const::<2>());
// query latest round
AggregatorProxyImpl::latest_answer(@state);
}

#[test]
fn test_propose_new_aggregator() {
let (owner, mockAggregatorAddr1, mockAggregator1, mockAggregatorAddr2, mockAggregator2) =
Expand Down
5 changes: 5 additions & 0 deletions contracts/src/tests/test_mock_aggregator.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,10 @@ fn test_set_latest_round() {
assert(
MockAggregator::Aggregator::latest_round_data(@state) == expected_round, 'round not equal'
);

assert(
MockAggregator::Aggregator::latest_answer(@state) == expected_round.answer,
'latest answer not equal'
);
}

30 changes: 26 additions & 4 deletions contracts/src/tests/test_sequencer_uptime_feed.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ use option::OptionTrait;
use core::result::ResultTrait;

use chainlink::emergency::sequencer_uptime_feed::SequencerUptimeFeed;
use chainlink::libraries::access_control::{
IAccessController, IAccessControllerDispatcher, IAccessControllerDispatcherTrait
};
use chainlink::ocr2::aggregator_proxy::{
IAggregatorProxy, IAggregatorProxyDispatcher, IAggregatorProxyDispatcherTrait
};
use chainlink::ocr2::aggregator_proxy::AggregatorProxy;
use chainlink::ocr2::aggregator_proxy::AggregatorProxy::AggregatorProxyImpl;
use chainlink::tests::test_ownable::should_implement_ownable;
Expand Down Expand Up @@ -88,20 +94,36 @@ fn test_latest_round_data_no_access() {

#[test]
#[should_panic(expected: ('user does not have read access',))]
fn test_aggregator_proxy_response() {
fn test_latest_answer_no_access() {
let (owner, sequencerFeedAddr, _) = setup();
let mut proxy = PROXY();
AggregatorProxy::constructor(ref proxy, owner, sequencerFeedAddr);
AggregatorProxyImpl::latest_answer(@proxy);
}

#[test]
fn test_aggregator_proxy_response() {
let (owner, sequencerFeedAddr, _) = setup();

set_contract_address(owner);
let contract = IAccessControllerDispatcher { contract_address: sequencerFeedAddr };
contract.add_access(owner);

let proxy = IAggregatorProxyDispatcher { contract_address: sequencerFeedAddr };

// latest round data
let latest_round_data = AggregatorProxyImpl::latest_round_data(@proxy);
let latest_round_data = proxy.latest_round_data();
assert(latest_round_data.answer == 0, 'latest_round_data should be 0');

// latest answer
let latest_answer = proxy.latest_answer();
assert(latest_answer == 0, 'latest_answer should be 0');

// description
let description = AggregatorProxyImpl::description(@proxy);
let description = proxy.description();
assert(description == 'L2 Sequencer Uptime Status Feed', 'description does not match');

// decimals
let decimals = AggregatorProxyImpl::decimals(@proxy);
let decimals = proxy.decimals();
assert(decimals == 0, 'decimals should be 0');
}

0 comments on commit fa64980

Please sign in to comment.