Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add version to base pools and refactor pool constructors #2080

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion pkg/interfaces/contracts/pool-utils/IBasePoolFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;

import "./IFactoryCreatedPoolVersion.sol";
import "./IVersion.sol";
import "../solidity-utils/helpers/IAuthentication.sol";

interface IBasePoolFactory is IAuthentication {
interface IBasePoolFactory is IAuthentication, IVersion, IFactoryCreatedPoolVersion {
/**
* @dev Returns true if `pool` was created by this factory.
*/
Expand Down
10 changes: 10 additions & 0 deletions pkg/interfaces/contracts/vault/IBasePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ import "./IPoolSwapStructs.sol";
* either IGeneralPool or IMinimalSwapInfoPool
*/
interface IBasePool is IPoolSwapStructs {
struct BasePoolParams {
IVault vault;
string name;
string symbol;
uint256 pauseWindowDuration;
uint256 bufferPeriodDuration;
address owner;
string version;
}

/**
* @dev Called by the Vault when a user calls `IVault.joinPool` to add liquidity to this Pool. Returns how many of
* each registered token the user should provide, as well as the amount of protocol fees the Pool owes to the Vault.
Expand Down
28 changes: 10 additions & 18 deletions pkg/pool-linear/contracts/LinearPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -125,31 +125,23 @@ abstract contract LinearPool is ILinearPool, IGeneralPool, IRateProvider, NewBas
event TargetsSet(IERC20 indexed token, uint256 lowerTarget, uint256 upperTarget);

constructor(
IVault vault,
string memory name,
string memory symbol,
BasePoolParams memory basePoolParams,
IERC20 mainToken,
IERC20 wrappedToken,
uint256 upperTarget,
address[] memory assetManagers,
uint256 swapFeePercentage,
uint256 pauseWindowDuration,
uint256 bufferPeriodDuration,
address owner
uint256 swapFeePercentage
)
NewBasePool(
vault,
basePoolParams,
PoolRegistrationLib.registerComposablePool(
vault,
IVault.PoolSpecialization.GENERAL,
_sortTokens(mainToken, wrappedToken),
assetManagers
),
name,
symbol,
pauseWindowDuration,
bufferPeriodDuration,
owner
basePoolParams.vault,
PoolRegistrationLib.PoolRegistrationParams({
specialization: IVault.PoolSpecialization.GENERAL,
tokens: _sortTokens(mainToken, wrappedToken),
assetManagers: assetManagers
})
)
)
{
// Set tokens
Expand Down
21 changes: 4 additions & 17 deletions pkg/pool-linear/contracts/aave/AaveLinearPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,26 @@ import "@balancer-labs/v2-pool-utils/contracts/Version.sol";

import "../LinearPool.sol";

contract AaveLinearPool is LinearPool, Version {
contract AaveLinearPool is LinearPool {
ILendingPool private immutable _lendingPool;

struct ConstructorArgs {
IVault vault;
string name;
string symbol;
IERC20 mainToken;
IERC20 wrappedToken;
address assetManager;
uint256 upperTarget;
uint256 swapFeePercentage;
uint256 pauseWindowDuration;
uint256 bufferPeriodDuration;
address owner;
string version;
}

constructor(ConstructorArgs memory args)
constructor(BasePoolParams memory basePoolParams, ConstructorArgs memory args)
LinearPool(
args.vault,
args.name,
args.symbol,
basePoolParams,
args.mainToken,
args.wrappedToken,
args.upperTarget,
_toAssetManagerArray(args),
args.swapFeePercentage,
args.pauseWindowDuration,
args.bufferPeriodDuration,
args.owner
args.swapFeePercentage
)
Version(args.version)
{
_lendingPool = IStaticAToken(address(args.wrappedToken)).LENDING_POOL();
_require(address(args.mainToken) == IStaticAToken(address(args.wrappedToken)).ASSET(), Errors.TOKENS_MISMATCH);
Expand Down
74 changes: 40 additions & 34 deletions pkg/pool-linear/contracts/aave/AaveLinearPoolFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;

import "@balancer-labs/v2-interfaces/contracts/vault/IBasePool.sol";
import "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
import "@balancer-labs/v2-interfaces/contracts/standalone-utils/IBalancerQueries.sol";
import "@balancer-labs/v2-interfaces/contracts/pool-utils/ILastCreatedPoolFactory.sol";
import "@balancer-labs/v2-interfaces/contracts/pool-utils/IFactoryCreatedPoolVersion.sol";

import "@balancer-labs/v2-pool-utils/contracts/Version.sol";
import "@balancer-labs/v2-pool-utils/contracts/factories/BasePoolFactory.sol";
import "@balancer-labs/v2-pool-utils/contracts/factories/FactoryWidePauseWindow.sol";

Expand All @@ -30,41 +30,34 @@ import "@balancer-labs/v2-solidity-utils/contracts/openzeppelin/ReentrancyGuard.
import "./AaveLinearPool.sol";
import "./AaveLinearPoolRebalancer.sol";

contract AaveLinearPoolFactory is
ILastCreatedPoolFactory,
IFactoryCreatedPoolVersion,
Version,
BasePoolFactory,
ReentrancyGuard,
FactoryWidePauseWindow
{
contract AaveLinearPoolFactory is ILastCreatedPoolFactory, BasePoolFactory, ReentrancyGuard, FactoryWidePauseWindow {
struct PoolDeploymentParams {
bytes32 rebalancerSalt;
bytes rebalancerCreationCode;
address expectedRebalancerAddress;
}

// Used for create2 deployments
uint256 private _nextRebalancerSalt;

IBalancerQueries private immutable _queries;

address private _lastCreatedPool;
string private _poolVersion;

constructor(
IVault vault,
IProtocolFeePercentagesProvider protocolFeeProvider,
IBalancerQueries queries,
string memory factoryVersion,
string memory poolVersion
) BasePoolFactory(vault, protocolFeeProvider, type(AaveLinearPool).creationCode) Version(factoryVersion) {
) BasePoolFactory(vault, protocolFeeProvider, type(AaveLinearPool).creationCode, factoryVersion, poolVersion) {
_queries = queries;
_poolVersion = poolVersion;
}

function getLastCreatedPool() external view override returns (address) {
return _lastCreatedPool;
}

function getPoolVersion() public view override returns (string memory) {
return _poolVersion;
}

function _create(bytes memory constructorArgs) internal virtual override returns (address) {
address pool = super._create(constructorArgs);
_lastCreatedPool = pool;
Expand Down Expand Up @@ -97,45 +90,58 @@ contract AaveLinearPoolFactory is
// approach is that create2 requires the full creation code, including constructor arguments, and among those is
// the Pool's address. To work around this, we have the Rebalancer fetch this address from `getLastCreatedPool`,
// which will hold the Pool's address after we call `_create`.

bytes32 rebalancerSalt = bytes32(_nextRebalancerSalt);
_nextRebalancerSalt += 1;

bytes memory rebalancerCreationCode = abi.encodePacked(
type(AaveLinearPoolRebalancer).creationCode,
abi.encode(getVault(), _queries)
);
address expectedRebalancerAddress = Create2.computeAddress(rebalancerSalt, keccak256(rebalancerCreationCode));
PoolDeploymentParams memory deploymentParams = _getPoolDeploymentParameters();

(uint256 pauseWindowDuration, uint256 bufferPeriodDuration) = getPauseConfiguration();

AaveLinearPool.ConstructorArgs memory args = AaveLinearPool.ConstructorArgs({
IBasePool.BasePoolParams memory basePoolParams = IBasePool.BasePoolParams({
vault: getVault(),
name: name,
symbol: symbol,
mainToken: mainToken,
wrappedToken: wrappedToken,
assetManager: expectedRebalancerAddress,
upperTarget: upperTarget,
swapFeePercentage: swapFeePercentage,
pauseWindowDuration: pauseWindowDuration,
bufferPeriodDuration: bufferPeriodDuration,
owner: owner,
version: getPoolVersion()
});

AaveLinearPool pool = AaveLinearPool(_create(abi.encode(args)));
AaveLinearPool.ConstructorArgs memory args = AaveLinearPool.ConstructorArgs({
mainToken: mainToken,
wrappedToken: wrappedToken,
assetManager: deploymentParams.expectedRebalancerAddress,
upperTarget: upperTarget,
swapFeePercentage: swapFeePercentage
});

AaveLinearPool pool = AaveLinearPool(_create(abi.encode(basePoolParams, args)));

// LinearPools have a separate post-construction initialization step: we perform it here to
// ensure deployment and initialization are atomic.
pool.initialize();

// Not that the Linear Pool's deployment is complete, we can deploy the Rebalancer, verifying that we correctly
// predicted its deployment address.
address actualRebalancerAddress = Create2.deploy(0, rebalancerSalt, rebalancerCreationCode);
require(expectedRebalancerAddress == actualRebalancerAddress, "Rebalancer deployment failed");
address actualRebalancerAddress = Create2.deploy(
0,
deploymentParams.rebalancerSalt,
deploymentParams.rebalancerCreationCode
);
require(deploymentParams.expectedRebalancerAddress == actualRebalancerAddress, "Rebalancer deployment failed");

// We don't return the Rebalancer's address, but that can be queried in the Vault by calling `getPoolTokenInfo`.
return pool;
}

function _getPoolDeploymentParameters() private returns (PoolDeploymentParams memory deploymentParams) {
deploymentParams.rebalancerSalt = bytes32(_nextRebalancerSalt);
_nextRebalancerSalt += 1;

deploymentParams.rebalancerCreationCode = abi.encodePacked(
type(AaveLinearPoolRebalancer).creationCode,
abi.encode(getVault(), _queries)
);
deploymentParams.expectedRebalancerAddress = Create2.computeAddress(
deploymentParams.rebalancerSalt,
keccak256(deploymentParams.rebalancerCreationCode)
);
}
}
18 changes: 4 additions & 14 deletions pkg/pool-linear/contracts/button-wood/UnbuttonAaveLinearPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,19 @@ import "../LinearPool.sol";
*/
contract UnbuttonAaveLinearPool is LinearPool {
constructor(
IVault vault,
string memory name,
string memory symbol,
BasePoolParams memory basePoolParams,
IUnbuttonToken mainToken,
IUnbuttonToken wrappedToken,
uint256 upperTarget,
uint256 swapFeePercentage,
uint256 pauseWindowDuration,
uint256 bufferPeriodDuration,
address owner
uint256 swapFeePercentage
)
LinearPool(
vault,
name,
symbol,
basePoolParams,
mainToken, // wAMPL
wrappedToken, // wAaveAMPL
upperTarget,
new address[](2),
swapFeePercentage,
pauseWindowDuration,
bufferPeriodDuration,
owner
swapFeePercentage
)
{
// wAMPL.underlying() == AMPL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,19 @@ import "@balancer-labs/v2-pool-utils/contracts/factories/FactoryWidePauseWindow.
import "./UnbuttonAaveLinearPool.sol";

contract UnbuttonAaveLinearPoolFactory is BasePoolFactory, FactoryWidePauseWindow {
constructor(IVault vault, IProtocolFeePercentagesProvider protocolFeeProvider)
BasePoolFactory(vault, protocolFeeProvider, type(UnbuttonAaveLinearPool).creationCode)
constructor(
IVault vault,
IProtocolFeePercentagesProvider protocolFeeProvider,
string memory factoryVersion,
string memory poolVersion
)
BasePoolFactory(
vault,
protocolFeeProvider,
type(UnbuttonAaveLinearPool).creationCode,
factoryVersion,
poolVersion
)
{
// solhint-disable-previous-line no-empty-blocks
}
Expand All @@ -46,16 +57,19 @@ contract UnbuttonAaveLinearPoolFactory is BasePoolFactory, FactoryWidePauseWindo
LinearPool pool = UnbuttonAaveLinearPool(
_create(
abi.encode(
getVault(),
name,
symbol,
IBasePool.BasePoolParams({
vault: getVault(),
name: name,
symbol: symbol,
pauseWindowDuration: pauseWindowDuration,
bufferPeriodDuration: bufferPeriodDuration,
owner: owner,
version: getPoolVersion()
}),
mainToken,
wrappedToken,
upperTarget,
swapFeePercentage,
pauseWindowDuration,
bufferPeriodDuration,
owner
swapFeePercentage
)
)
);
Expand Down
25 changes: 3 additions & 22 deletions pkg/pool-linear/contracts/erc4626/ERC4626LinearPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,12 @@ contract ERC4626LinearPool is LinearPool {
uint256 private immutable _rateScaleFactor;

constructor(
IVault vault,
string memory name,
string memory symbol,
BasePoolParams memory basePoolParams,
IERC20 mainToken,
IERC4626 wrappedToken,
uint256 upperTarget,
uint256 swapFeePercentage,
uint256 pauseWindowDuration,
uint256 bufferPeriodDuration,
address owner
)
LinearPool(
vault,
name,
symbol,
mainToken,
wrappedToken,
upperTarget,
new address[](2),
swapFeePercentage,
pauseWindowDuration,
bufferPeriodDuration,
owner
)
{
uint256 swapFeePercentage
) LinearPool(basePoolParams, mainToken, wrappedToken, upperTarget, new address[](2), swapFeePercentage) {
// We do NOT enforce mainToken == wrappedToken.asset() even
// though this is the expected behavior in most cases. Instead,
// we assume a 1:1 relationship between mainToken and
Expand Down
Loading