Skip to content

Commit

Permalink
refactor: rename factory + add inheritance graph (aave-dao#13)
Browse files Browse the repository at this point in the history
* docs: add inheritance image

* refactor: rename factory

* docs: add some more docs on readm
  • Loading branch information
sakulstra authored Aug 19, 2024
1 parent 58076f3 commit 3781bb6
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.0;
import '../../interfaces/IMarketReportTypes.sol';
import {TransparentProxyFactory, ITransparentProxyFactory} from 'solidity-utils/contracts/transparent-proxy/TransparentProxyFactory.sol';
import {StataTokenV2} from 'aave-v3-periphery/contracts/static-a-token/StataTokenV2.sol';
import {StaticATokenFactory} from 'aave-v3-periphery/contracts/static-a-token/StaticATokenFactory.sol';
import {StataTokenFactory} from 'aave-v3-periphery/contracts/static-a-token/StataTokenFactory.sol';
import {IErrors} from '../../interfaces/IErrors.sol';

contract AaveV3HelpersProcedureTwo is IErrors {
Expand All @@ -20,7 +20,7 @@ contract AaveV3HelpersProcedureTwo is IErrors {
new StataTokenV2(IPool(pool), IRewardsController(rewardsController))
);
staticATokenReport.staticATokenFactoryImplementation = address(
new StaticATokenFactory(
new StataTokenFactory(
IPool(pool),
proxyAdmin,
ITransparentProxyFactory(staticATokenReport.transparentProxyFactory),
Expand All @@ -33,7 +33,7 @@ contract AaveV3HelpersProcedureTwo is IErrors {
).create(
staticATokenReport.staticATokenFactoryImplementation,
proxyAdmin,
abi.encodeWithSelector(StaticATokenFactory.initialize.selector)
abi.encodeWithSelector(StataTokenFactory.initialize.selector)
);

return staticATokenReport;
Expand Down
15 changes: 9 additions & 6 deletions src/periphery/contracts/static-a-token/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,22 @@

## About

The static-a-token contains an [EIP-4626](https://eips.ethereum.org/EIPS/eip-4626) generic token vault/wrapper for all Aave v3 pools.
The StataToken in an [EIP-4626](https://eips.ethereum.org/EIPS/eip-4626) generic token vault/wrapper intended to be used with aave v3 aTokens.

## Features

- **Full [EIP-4626](https://eips.ethereum.org/EIPS/eip-4626) compatibility.**
- **Accounting for any potential liquidity mining rewards.** Let’s say some team of the Aave ecosystem (or the Aave community itself) decides to incentivize deposits of USDC on Aave v3 Ethereum. By holding `stataUSDC`, the user will still be eligible for those incentives.
It is important to highlight that while currently the wrapper supports infinite reward tokens by design (e.g. AAVE incentivizing stETH & Lido incentivizing stETH as well), each reward needs to be permissionlessly registered which bears some [⁽¹⁾](#limitations).
- **Meta-transactions support.** To enable interfaces to offer gas-less transactions to deposit/withdraw on the wrapper/Aave protocol (also supported on Aave v3). Including permit() for transfers of the `stataAToken` itself.
- **Upgradable by the Aave governance.** Similar to other contracts of the Aave ecosystem, the Level 1 executor (short executor) will be able to add new features to the deployed instances of the `stataTokens`.
- **Powered by a stataToken Factory.** Whenever a token will be listed on Aave v3, anybody will be able to call the stataToken Factory to deploy an instance for the new asset, permissionless, but still assuring the code used and permissions are properly configured without any extra headache.
- **Upgradable by the Aave governance.** Similar to other contracts of the Aave ecosystem, the Level 1 executor (short executor) will be able to add new features to the deployed instances of the `StataTokens`.
- **Powered by a StataTokenFactory.** Whenever a token will be listed on Aave v3, anybody will be able to call the StataTokenFactory to deploy an instance for the new asset, permissionless, but still assuring the code used and permissions are properly configured without any extra headache.

See [IStata4626LM.sol](./interfaces/IERC20AaveLM.sol) for detailed method documentation.

## Deployed Addresses

The staticATokenFactory is deployed for all major Aave v3 pools.
An up to date address can be fetched from the respective [address-book pool library](https://github.com/bgd-labs/aave-address-book/blob/main/src/AaveV3Ethereum.sol).
The StataTokenFactory is deployed for all major Aave v3 pools.
An up to date address can be fetched from the respective [address-book pool library](https://search.onaave.com/?q=stata%20factory).

## Limitations

Expand All @@ -37,6 +36,8 @@ For this project, the security procedures applied/being finished are:
- The test suite of the codebase itself.
- Certora audit/property checking for all the dynamics of the `stataToken`, including respecting all the specs of [EIP-4626](https://eips.ethereum.org/EIPS/eip-4626).

---

## Upgrade Notes StataTokenV2

### Inheritance
Expand All @@ -54,6 +55,8 @@ The implementation is seperated in two ERC20 extentions and one actual "merger"
In addition it adds a `latestAnswer` priceFeed, which returns the share price based on how aave prices the underlying.
3. `StataTokenV2` is the main contract inheriting `ERC20AaveLM` and `ERC4626StataToken`, while also adding `Pausability`, `Rescuability`, `Permit` and the actual initialization.

![inheritance graph](./inheritance.png)

### Libraries

The previous `StaticATokenLM` relied on `WadRayMath` and `WadRayMathExplicitRounding` - a custom version where one can specify the rounding behavior - for math operations.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ import {IERC20Metadata} from 'solidity-utils/contracts/oz-common/interfaces/IERC
import {ITransparentProxyFactory} from 'solidity-utils/contracts/transparent-proxy/interfaces/ITransparentProxyFactory.sol';
import {Initializable} from 'solidity-utils/contracts/transparent-proxy/Initializable.sol';
import {StataTokenV2} from './StataTokenV2.sol';
import {IStaticATokenFactory} from './interfaces/IStaticATokenFactory.sol';
import {IStataTokenFactory} from './interfaces/IStataTokenFactory.sol';

/**
* @title StaticATokenFactory
* @notice Factory contract that keeps track of all deployed static aToken wrappers for a specified pool.
* This registry also acts as a factory, allowing to deploy new static aTokens on demand.
* There can only be one static aToken per underlying on the registry at a time.
* @title StataTokenFactory
* @notice Factory contract that keeps track of all deployed StataTokens for a specified pool.
* This registry also acts as a factory, allowing to deploy new StataTokens on demand.
* There can only be one StataToken per underlying on the registry at any time.
* @author BGD labs
*/
contract StaticATokenFactory is Initializable, IStaticATokenFactory {
contract StataTokenFactory is Initializable, IStataTokenFactory {
IPool public immutable POOL;
address public immutable PROXY_ADMIN;
ITransparentProxyFactory public immutable TRANSPARENT_PROXY_FACTORY;
Expand All @@ -40,8 +40,8 @@ contract StaticATokenFactory is Initializable, IStaticATokenFactory {

function initialize() external initializer {}

///@inheritdoc IStaticATokenFactory
function createStaticATokens(address[] memory underlyings) external returns (address[] memory) {
///@inheritdoc IStataTokenFactory
function createStataTokens(address[] memory underlyings) external returns (address[] memory) {
address[] memory staticATokens = new address[](underlyings.length);
for (uint256 i = 0; i < underlyings.length; i++) {
address cachedStaticAToken = _underlyingToStaticAToken[underlyings[i]];
Expand Down Expand Up @@ -79,13 +79,13 @@ contract StaticATokenFactory is Initializable, IStaticATokenFactory {
return staticATokens;
}

///@inheritdoc IStaticATokenFactory
function getStaticATokens() external view returns (address[] memory) {
///@inheritdoc IStataTokenFactory
function getStataTokens() external view returns (address[] memory) {
return _staticATokens;
}

///@inheritdoc IStaticATokenFactory
function getStaticAToken(address underlying) external view returns (address) {
///@inheritdoc IStataTokenFactory
function getStataToken(address underlying) external view returns (address) {
return _underlyingToStaticAToken[underlying];
}
}
5 changes: 5 additions & 0 deletions src/periphery/contracts/static-a-token/StataTokenV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import {ERC4626Upgradeable, ERC4626StataTokenUpgradeable, IPool} from './ERC4626
import {ERC20AaveLMUpgradeable, IRewardsController} from './ERC20AaveLMUpgradeable.sol';
import {IStataTokenV2} from './interfaces/IStataTokenV2.sol';

/**
* @title StataTokenV2
* @notice A 4626 Vault which wrapps aTokens in order to translate the rebasing nature of yield accrual into a non-rebasing value accrual.
* @author BGD labs
*/
contract StataTokenV2 is
ERC20PermitUpgradeable,
ERC20AaveLMUpgradeable,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

interface IStataTokenFactory {
error NotListedUnderlying(address underlying);

/**
* @notice Creates new StataTokens
* @param underlyings the addresses of the underlyings to create.
* @return address[] addresses of the new StataTokens.
*/
function createStataTokens(address[] memory underlyings) external returns (address[] memory);

/**
* @notice Returns all StataTokens deployed via this registry.
* @return address[] list of StataTokens
*/
function getStataTokens() external view returns (address[] memory);

/**
* @notice Returns the StataToken for a given underlying.
* @param underlying the address of the underlying.
* @return address the StataToken address.
*/
function getStataToken(address underlying) external view returns (address);
}

This file was deleted.

10 changes: 5 additions & 5 deletions tests/periphery/static-a-token/TestBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.10;
import {IERC20Metadata, IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol';
import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol';
import {ITransparentProxyFactory} from 'solidity-utils/contracts/transparent-proxy/TransparentProxyFactory.sol';
import {StaticATokenFactory} from '../../../src/periphery/contracts/static-a-token/StaticATokenFactory.sol';
import {StataTokenFactory} from '../../../src/periphery/contracts/static-a-token/StataTokenFactory.sol';
import {StataTokenV2} from '../../../src/periphery/contracts/static-a-token/StataTokenV2.sol';
import {IERC20AaveLM} from '../../../src/periphery/contracts/static-a-token/interfaces/IERC20AaveLM.sol';
import {TestnetProcedures, TestnetERC20} from '../../utils/TestnetProcedures.sol';
Expand All @@ -24,7 +24,7 @@ abstract contract BaseTest is TestnetProcedures {
StataTokenV2 public stataTokenV2;
address public proxyAdmin;
ITransparentProxyFactory public proxyFactory;
StaticATokenFactory public factory;
StataTokenFactory public factory;

address[] rewardTokens;

Expand Down Expand Up @@ -53,10 +53,10 @@ abstract contract BaseTest is TestnetProcedures {
proxyFactory = ITransparentProxyFactory(report.transparentProxyFactory);
proxyAdmin = report.proxyAdmin;

factory = StaticATokenFactory(report.staticATokenFactoryProxy);
factory.createStaticATokens(contracts.poolProxy.getReservesList());
factory = StataTokenFactory(report.staticATokenFactoryProxy);
factory.createStataTokens(contracts.poolProxy.getReservesList());

stataTokenV2 = StataTokenV2(factory.getStaticAToken(underlying));
stataTokenV2 = StataTokenV2(factory.getStataToken(underlying));
}

function _skipBlocks(uint128 blocks) internal {
Expand Down

0 comments on commit 3781bb6

Please sign in to comment.