-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #82 from buttonwood-protocol/PROM-1247-button-wrap…
…pers-api-3-oracle-adapter PROM-1247 - button wrappers - api3 oracle adapter
- Loading branch information
Showing
25 changed files
with
668 additions
and
338 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
// Actual interface taken from https://arbiscan.io/address/0x1bEB65b15689cCAeb5dA191c9fd5F94513923Cab#code#F11 | ||
// This should be a useful reference but at time of writing it is unclear how the import resolves to source code: | ||
// https://github.com/api3dao/contracts/blob/main/contracts/v0.8/interfaces/IDapiProxy.sol | ||
interface IDapiProxy { | ||
function read() external view returns (int224 value, uint32 timestamp); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
pragma solidity ^0.8.4; | ||
|
||
import "../interfaces/IDapiProxy.sol"; | ||
|
||
/** | ||
* @title Mock DapiProxy | ||
* | ||
* @notice Provides a value onchain from an API3 oracle | ||
*/ | ||
contract MockDapiProxy is IDapiProxy { | ||
int224 public answer; | ||
uint32 public updatedAt; | ||
|
||
function read() external view override returns (int224 value, uint32 timestamp) { | ||
return (answer, updatedAt); | ||
} | ||
|
||
/** | ||
* Set the latest answer to be returned from now on | ||
*/ | ||
function setLatestAnswer(int224 _answer) public { | ||
answer = _answer; | ||
} | ||
|
||
/** | ||
* Set the latest answer to be returned from now on | ||
*/ | ||
function setUpdatedAt(uint32 _updatedAt) public { | ||
updatedAt = _updatedAt; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
pragma solidity 0.8.4; | ||
|
||
import {IOracle} from "../interfaces/IOracle.sol"; | ||
import {IDapiProxy} from "../interfaces/IDapiProxy.sol"; | ||
|
||
/** | ||
* @title API3 Oracle | ||
* | ||
* @notice Provides a value onchain from a API3 oracle | ||
*/ | ||
contract API3Oracle is IOracle { | ||
/// @dev Per the docs API3 values are always 18 decimal format: | ||
/// https://docs.api3.org/guides/dapis/read-a-dapi/#:~:text=the%20latest%20value%20with%2018%20decimals | ||
uint256 public constant PRICE_DECIMALS = 18; | ||
// The address of the API3 DapiProxy contract | ||
IDapiProxy public immutable oracle; | ||
uint256 public immutable stalenessThresholdSecs; | ||
|
||
constructor(address _oracle, uint256 _stalenessThresholdSecs) { | ||
oracle = IDapiProxy(_oracle); | ||
stalenessThresholdSecs = _stalenessThresholdSecs; | ||
} | ||
|
||
/** | ||
* @notice Fetches the decimal precision used in the market price from API3 | ||
* @return priceDecimals_: Number of decimals in the price | ||
*/ | ||
function priceDecimals() external pure override returns (uint256) { | ||
return PRICE_DECIMALS; | ||
} | ||
|
||
/** | ||
* @notice Fetches the latest market price from API3 | ||
* @return Value: Latest market price. | ||
* valid: Boolean indicating an value was fetched successfully. | ||
*/ | ||
function getData() external view override returns (uint256, bool) { | ||
(int224 value, uint32 timestamp) = oracle.read(); | ||
// Return invalid if value cannot be converted into a uint256 | ||
if (value < 0) { | ||
return (0, false); | ||
} | ||
uint256 diff = block.timestamp - uint256(timestamp); | ||
return (uint256(int256(value)), diff <= stalenessThresholdSecs); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { task, types } from 'hardhat/config' | ||
import { TaskArguments } from 'hardhat/types' | ||
|
||
task('deploy:API3Oracle') | ||
.addParam('dapiproxy', 'the address of the underlying DapiProxy contract') | ||
.addParam('stalenessthresholdsecs', 'the number of seconds before refresh') | ||
.setAction(async function (args: TaskArguments, hre) { | ||
const { dapiproxy, stalenessthresholdsecs } = args | ||
const API3Oracle = await hre.ethers.getContractFactory('API3Oracle') | ||
const oracle = await API3Oracle.deploy(dapiproxy, stalenessthresholdsecs) | ||
await oracle.deployed() | ||
const oracleAddress = oracle.address | ||
console.log(`Oracle deployed to ${oracleAddress}`) | ||
|
||
try { | ||
await hre.run('verify:API3Oracle', { | ||
address: oracleAddress, | ||
dapiproxy, | ||
stalenessthresholdsecs, | ||
}) | ||
} catch (e) { | ||
console.log('Unable to verify on etherscan', e) | ||
} | ||
}) | ||
|
||
task('verify:API3Oracle') | ||
.addParam('address', 'the contract address', undefined, types.string, false) | ||
.addParam('dapiproxy', 'the address of the underlying DapiProxy contract') | ||
.addParam('stalenessthresholdsecs', 'the number of seconds before refresh') | ||
.setAction(async function (args: TaskArguments, hre) { | ||
const { address, dapiproxy, stalenessthresholdsecs } = args | ||
|
||
await hre.run('verify:verify', { | ||
address, | ||
constructorArguments: [dapiproxy, stalenessthresholdsecs], | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { task, types } from 'hardhat/config' | ||
import { TaskArguments } from 'hardhat/types' | ||
|
||
task('deploy:ChainlinkOracle') | ||
.addParam('aggregator', 'the address of the backing chainlink aggregator') | ||
.addParam('stalenessthresholdsecs', 'the number of seconds before refresh') | ||
.setAction(async function (args: TaskArguments, hre) { | ||
const { aggregator, stalenessthresholdsecs } = args | ||
const ChainlinkOracle = await hre.ethers.getContractFactory( | ||
'ChainlinkOracle', | ||
) | ||
const oracle = await ChainlinkOracle.deploy( | ||
aggregator, | ||
stalenessthresholdsecs, | ||
) | ||
await oracle.deployed() | ||
const oracleAddress = oracle.address | ||
console.log(`Oracle deployed to ${oracleAddress}`) | ||
|
||
try { | ||
await hre.run('verify:ChainlinkOracle', { | ||
address: oracleAddress, | ||
aggregator, | ||
stalenessthresholdsecs, | ||
}) | ||
} catch (e) { | ||
console.log('Unable to verify on etherscan', e) | ||
} | ||
}) | ||
|
||
task('verify:ChainlinkOracle') | ||
.addParam('address', 'the contract address', undefined, types.string, false) | ||
.addParam('aggregator', 'the address of the backing chainlink aggregator') | ||
.addParam('stalenessthresholdsecs', 'the number of seconds before refresh') | ||
.setAction(async function (args: TaskArguments, hre) { | ||
const { address, aggregator, stalenessthresholdsecs } = args | ||
|
||
await hre.run('verify:verify', { | ||
address, | ||
constructorArguments: [aggregator, stalenessthresholdsecs], | ||
}) | ||
}) |
Oops, something went wrong.