Skip to content

Commit

Permalink
Merge branch 'release/v4.8.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
TylerEther committed Jul 16, 2024
2 parents 20c3678 + 225370e commit 7b48fbf
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 8 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## v4.8.0
### Dependencies
- Upgrade adrastia-core to v4.8.0.

### Accumulators
- Add ManagedAdrastiaUtilizationAndErrorAccumulator: An AdrastiaUtilizationAndErrorAccumulator that implements standard management functions.

## v4.7.4
### Prudentia
#### Computers
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.13;

import "@adrastia-oracle/adrastia-core/contracts/accumulators/proto/adrastia/AdrastiaUtilizationAndErrorAccumulator.sol";

import "@openzeppelin-v4/contracts/access/AccessControlEnumerable.sol";

import "../../AccumulatorConfig.sol";
import "../../../access/Roles.sol";

contract ManagedAdrastiaUtilizationAndErrorAccumulator is
AccessControlEnumerable,
AdrastiaUtilizationAndErrorAccumulator,
AccumulatorConfig
{
struct TargetConfig {
bool initialized;
uint112 target;
}

mapping(address => TargetConfig) internal targets;

/// @notice An event emitted when a target is initialized or uninitialized.
/// @param token The token that is initialized. address(0) is used for the default target.
/// @param initialized Whether the target is initialized or uninitialized.
event TargetInitialized(address indexed token, bool initialized);

/// @notice An event emitted when a target is updated.
/// @param token The token that is updated.
/// @param target The new target.
event TargetUpdated(address indexed token, uint112 target);

/// @notice An error thrown when attempting to set a new target that is the same as the current target.
/// @dev This is thrown to make it more noticeable when nothing changes. It's probably a mistake.
/// @param token The token that is unchanged.
/// @param target The unchanged target.
error TargetNotChanged(address token, uint112 target);

/// @notice An error thrown when attempting to revert to the default target when the target is already using the
/// default target.
/// @param token The token that is already using the default target.
error AlreadyUsingDefaultTarget(address token);

constructor(
address sbOracle_,
bool considerEmptyAs100Percent_,
uint112 target_,
IAveragingStrategy averagingStrategy_,
uint8 decimals_,
uint256 updateTheshold_,
uint256 minUpdateDelay_,
uint256 maxUpdateDelay_
)
AdrastiaUtilizationAndErrorAccumulator(
sbOracle_,
considerEmptyAs100Percent_,
target_,
averagingStrategy_,
decimals_,
updateTheshold_,
minUpdateDelay_,
maxUpdateDelay_
)
AccumulatorConfig(uint32(updateTheshold_), uint32(minUpdateDelay_), uint32(maxUpdateDelay_))
{
initializeDefaultTarget(target_);
}

/// @notice Sets a new target for the given token.
/// @dev Only accounts with the TARGET_ADMIN role can call this function.
/// @param token The token to set the target for. address(0) is used for the default target.
/// @param target The new target.
function setTarget(address token, uint112 target) external virtual onlyRole(Roles.TARGET_ADMIN) {
TargetConfig storage targetConfig = targets[token];

bool initialized = targetConfig.initialized;
uint112 oldTarget = targetConfig.target;

if (initialized && oldTarget == target) {
// Revert to signal that nothing was changed.
revert TargetNotChanged(token, target);
}

targetConfig.initialized = true;
targetConfig.target = target;

if (!initialized) {
emit TargetInitialized(token, true);
}

emit TargetUpdated(token, target);
}

/// @notice Checks if the given token is using the default target.
/// @param token The token to check.
/// @return Whether the token is using the default target.
function isUsingDefaultTarget(address token) external view virtual returns (bool) {
if (token == address(0)) {
// address(0) specifies the default target.
return true;
}

return !targets[token].initialized;
}

/// @notice Reverts the target for the given token to the default target.
/// @dev Only accounts with the TARGET_ADMIN role can call this function.
/// @param token The token to revert the target for.
function revertToDefaultTarget(address token) external virtual onlyRole(Roles.TARGET_ADMIN) {
if (token == address(0)) {
// Revert to signal that nothing was changed.
revert AlreadyUsingDefaultTarget(token);
}

TargetConfig storage targetConfig = targets[token];

if (!targetConfig.initialized) {
// Revert to signal that nothing was changed.
revert AlreadyUsingDefaultTarget(token);
}

targetConfig.initialized = false;

emit TargetInitialized(token, false);
}

function canUpdate(bytes memory data) public view virtual override returns (bool) {
// Return false if the message sender is missing the required role
if (!hasRole(Roles.ORACLE_UPDATER, address(0)) && !hasRole(Roles.ORACLE_UPDATER, msg.sender)) return false;

return super.canUpdate(data);
}

function update(bytes memory data) public virtual override onlyRoleOrOpenRole(Roles.ORACLE_UPDATER) returns (bool) {
return super.update(data);
}

function supportsInterface(
bytes4 interfaceId
) public view virtual override(AccessControlEnumerable, LiquidityAccumulator) returns (bool) {
return
AccessControlEnumerable.supportsInterface(interfaceId) ||
LiquidityAccumulator.supportsInterface(interfaceId);
}

function initializeDefaultTarget(uint112 target) internal virtual {
TargetConfig storage targetConfig = targets[address(0)];

targetConfig.initialized = true;
targetConfig.target = target;

emit TargetInitialized(address(0), true);
emit TargetUpdated(address(0), target);
}

function _updateDelay() internal view virtual override returns (uint256) {
return config.updateDelay;
}

function _heartbeat() internal view virtual override returns (uint256) {
return config.heartbeat;
}

function _updateThreshold() internal view virtual override returns (uint256) {
return config.updateThreshold;
}

function fetchTarget(bytes memory data) internal view virtual override returns (uint112 target) {
address token = abi.decode(data, (address));

TargetConfig memory tokenConfig = targets[token];
if (!tokenConfig.initialized) {
// If the target is not initialized, use the default target.
target = targets[address(0)].target;
} else {
target = tokenConfig.target;
}
}
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adrastia-oracle/adrastia-periphery",
"version": "4.7.4",
"version": "4.8.0",
"main": "index.js",
"author": "TRILEZ SOFTWARE INC.",
"license": "BUSL-1.1",
Expand Down Expand Up @@ -30,7 +30,7 @@
"access": "public"
},
"dependencies": {
"@adrastia-oracle/adrastia-core": "4.7.1",
"@adrastia-oracle/adrastia-core": "4.8.0",
"@openzeppelin-v3/contracts": "npm:@openzeppelin/[email protected]",
"@openzeppelin-v4/contracts": "npm:@openzeppelin/[email protected]"
},
Expand Down
51 changes: 49 additions & 2 deletions test/accumulators/managed-liquidity-accumulator.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ const RATE_ADMIN_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("RATE_AD
const UPDATE_PAUSE_ADMIN_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UPDATE_PAUSE_ADMIN_ROLE"));
const TARGET_ADMIN_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("TARGET_ADMIN_ROLE"));

const WETH = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2";
const USDC = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48";
const WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const BAL = "0xba100000625a3754423978a60c9317c58a424e3D";

const MIN_UPDATE_DELAY = 1;
Expand Down Expand Up @@ -1103,6 +1103,39 @@ async function deployAlocUtilizationAndErrorAccumulator() {
);
}

async function deployAdrastiaUtilizationAndErrorAccumulator() {
const mockOracleFactory = await ethers.getContractFactory("MockOracle");
const mockOracle = await mockOracleFactory.deploy(ethers.constants.AddressZero, DEFAULT_DECIMALS);
await mockOracle.deployed();

// Set an observation for USDC
const totalBorrow = ethers.utils.parseUnits("90", DEFAULT_DECIMALS);
const totalSupply = ethers.utils.parseUnits("100", DEFAULT_DECIMALS);

await mockOracle.stubSetObservationNow(USDC, 0, totalBorrow, totalSupply);

// Deploy the averaging strategy
const averagingStrategyFactory = await ethers.getContractFactory(
ARITHMETIC_AVERAGING_ABI,
ARITHMETIC_AVERAGING_BYTECODE
);
const averagingStrategy = await averagingStrategyFactory.deploy();
await averagingStrategy.deployed();

// Deploy accumulator
const accumulatorFactory = await ethers.getContractFactory("ManagedAdrastiaUtilizationAndErrorAccumulator");
return await accumulatorFactory.deploy(
mockOracle.address,
true,
DEFAULT_UTILIZATION_TARGET,
averagingStrategy.address,
DEFAULT_UTILIZATION_DECIMALS,
TWO_PERCENT_CHANGE,
MIN_UPDATE_DELAY,
MAX_UPDATE_DELAY
);
}

async function deployTrueFiAloc() {
const alocFactory = await ethers.getContractFactory("AlocStub");
const aloc = await alocFactory.deploy();
Expand Down Expand Up @@ -1301,3 +1334,17 @@ describeLiquidityAccumulatorTests(
describeRefreshTokenMappingsTests("ManagedCompoundV2SBAccumulator", deployCompoundV2SBAccumulator);
describeRefreshTokenMappingsTests("ManagedIonicSBAccumulator", deployIonicSBAccumulator);
describeRefreshTokenMappingsTests("ManagedVenusIsolatedSBAccumulator", deployVenusIsolatedSBAccumulator);

describeLiquidityAccumulatorTests(
"ManagedAdrastiaUtilizationAndErrorAccumulator",
deployAdrastiaUtilizationAndErrorAccumulator,
generateDexBasedUpdateData,
true,
/*
Smart contracts can update the accumulator because it reads from a secured oracle and thus isn't susceptible to
manipulation.
*/
true,
() => USDC,
describeUtilizationAndErrorAccumulatorTests
);
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
# yarn lockfile v1


"@adrastia-oracle/adrastia-core@4.7.1":
version "4.7.1"
resolved "https://registry.yarnpkg.com/@adrastia-oracle/adrastia-core/-/adrastia-core-4.7.1.tgz#787bed1195a5ad0504b7dd3483a56a99a71e6a52"
integrity sha512-Cu7c8mP8g6Bgywwer7xB0sK2F+2n5vqPeQSD91RjjrmUhfHG2AgbPCWRJs4e4qutwXwzDWpErBOgHsr4c9tQsg==
"@adrastia-oracle/adrastia-core@4.8.0":
version "4.8.0"
resolved "https://registry.yarnpkg.com/@adrastia-oracle/adrastia-core/-/adrastia-core-4.8.0.tgz#3eb9f7b93ada156ea2be9439e2e41f5ecf07cdb4"
integrity sha512-iGAgKwLzJE+PE/TDtXRUQxiyF7zqdgtCv5QZj03PxORiLuoQbL0Q9rh8awhrXm6MoOJ2AVrn4T8X7/KFtx1/GQ==
dependencies:
"@openzeppelin-v4/contracts" "npm:@openzeppelin/[email protected]"
"@prb/math" "^2.5.0"
Expand Down

0 comments on commit 7b48fbf

Please sign in to comment.