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

Composable stable pool versioning #2034

Merged
Show file tree
Hide file tree
Changes from 5 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
28 changes: 28 additions & 0 deletions pkg/interfaces/contracts/pool-utils/IPoolVersion.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

pragma solidity >=0.7.0 <0.9.0;

/**
* @notice Simple interface to retrieve the version of pools deployed by a pool factory.
*/
interface IPoolVersion {
/**
* @dev Returns a JSON representation of the deployed pool version containing name, version number and task ID.
*
* This is typically only useful in complex Pool deployment schemes, where multiple subsystems need to know about
* each other. Note that this value will only be updated at factory creation time.
*/
function getPoolVersion() external view returns (string memory);
}
25 changes: 25 additions & 0 deletions pkg/interfaces/contracts/pool-utils/IVersion.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

pragma solidity >=0.7.0 <0.9.0;

/**
* @notice Simple interface to retrieve the version of a deployed contract.
*/
interface IVersion {
/**
* @dev Returns a JSON representation of the contract version containing name, version number and task ID.
*/
function version() external view returns (string memory);
}
28 changes: 28 additions & 0 deletions pkg/interfaces/contracts/pool-utils/IVersionProvider.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

pragma solidity >=0.7.0 <0.9.0;

/**
* @notice Simple interface to retrieve the version of a deployed contract.
*
* @dev The contract implementing the interface may provide the actual version, or forward the call to another
* version provider (e.g. a pool will forward the call to its respective pool factory).
*/
interface IVersionProvider {
/**
* @dev Returns a JSON representation of the contract version containing name, version number and task ID.
*/
function version() external view returns (string memory);
jubeira marked this conversation as resolved.
Show resolved Hide resolved
}
11 changes: 10 additions & 1 deletion pkg/pool-stable/contracts/ComposableStablePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import "@balancer-labs/v2-interfaces/contracts/pool-stable/StablePoolUserData.so
import "@balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/BalancerErrors.sol";
import "@balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolFeePercentagesProvider.sol";
import "@balancer-labs/v2-interfaces/contracts/pool-utils/IRateProvider.sol";
import "@balancer-labs/v2-interfaces/contracts/pool-utils/IVersion.sol";

import "@balancer-labs/v2-solidity-utils/contracts/math/FixedPoint.sol";
import "@balancer-labs/v2-solidity-utils/contracts/math/Math.sol";
Expand Down Expand Up @@ -50,6 +51,7 @@ import "./StableMath.sol";
*/
contract ComposableStablePool is
IRateProvider,
IVersion,
BaseGeneralPool,
StablePoolAmplification,
ComposableStablePoolRates,
Expand All @@ -64,6 +66,8 @@ contract ComposableStablePool is
// We are preminting half of that value (rounded up).
uint256 private constant _PREMINTED_TOKEN_BALANCE = 2**(111);

string private _version;

// The constructor arguments are received in a struct to work around stack-too-deep issues
struct NewPoolParams {
IVault vault;
Expand All @@ -79,6 +83,7 @@ contract ComposableStablePool is
uint256 pauseWindowDuration;
uint256 bufferPeriodDuration;
address owner;
string version;
}

constructor(NewPoolParams memory params)
Expand All @@ -99,7 +104,7 @@ contract ComposableStablePool is
ComposableStablePoolRates(_extractRatesParams(params))
ProtocolFeeCache(params.protocolFeeProvider, ProtocolFeeCache.DELEGATE_PROTOCOL_SWAP_FEES_SENTINEL)
{
// solhint-disable-previous-line no-empty-blocks
_version = params.version;
}

// Translate parameters to avoid stack-too-deep issues in the constructor
Expand Down Expand Up @@ -130,6 +135,10 @@ contract ComposableStablePool is
});
}

function version() external view override returns (string memory) {
return _version;
}

/**
* @notice Return the minimum BPT balance, required to avoid minimum token balances.
* @dev This amount is minted and immediately burned on pool initialization, so that the total supply
Expand Down
28 changes: 23 additions & 5 deletions pkg/pool-stable/contracts/ComposableStablePoolFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;

import "@balancer-labs/v2-interfaces/contracts/pool-utils/IPoolVersion.sol";
import "@balancer-labs/v2-interfaces/contracts/pool-utils/IVersion.sol";
import "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
import "@balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolFeePercentagesProvider.sol";

Expand All @@ -23,13 +25,28 @@ import "@balancer-labs/v2-pool-utils/contracts/factories/FactoryWidePauseWindow.

import "./ComposableStablePool.sol";

contract ComposableStablePoolFactory is BasePoolSplitCodeFactory, FactoryWidePauseWindow {
contract ComposableStablePoolFactory is IVersion, IPoolVersion, BasePoolSplitCodeFactory, FactoryWidePauseWindow {
IProtocolFeePercentagesProvider private _protocolFeeProvider;
string private _version;
string private _poolVersion;

constructor(IVault vault, IProtocolFeePercentagesProvider protocolFeeProvider)
BasePoolSplitCodeFactory(vault, type(ComposableStablePool).creationCode)
{
constructor(
IVault vault,
IProtocolFeePercentagesProvider protocolFeeProvider,
string memory factoryVersion,
string memory poolVersion
) BasePoolSplitCodeFactory(vault, type(ComposableStablePool).creationCode) {
_protocolFeeProvider = protocolFeeProvider;
_version = factoryVersion;
_poolVersion = poolVersion;
}

function version() external view override returns (string memory) {
return _version;
}

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

/**
Expand Down Expand Up @@ -64,7 +81,8 @@ contract ComposableStablePoolFactory is BasePoolSplitCodeFactory, FactoryWidePau
swapFeePercentage: swapFeePercentage,
pauseWindowDuration: pauseWindowDuration,
bufferPeriodDuration: bufferPeriodDuration,
owner: owner
owner: owner,
version: getPoolVersion()
})
)
)
Expand Down
27 changes: 26 additions & 1 deletion pkg/pool-stable/test/ComposableStablePoolFactory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,27 @@ describe('ComposableStablePoolFactory', function () {

let createTime: BigNumber;
let protocolFeeExemptFlags: boolean[];
let factoryVersion: string, poolVersion: string;

before('setup signers', async () => {
[, owner] = await ethers.getSigners();
});

sharedBeforeEach('deploy factory & tokens', async () => {
vault = await Vault.create();
factory = await deploy('ComposableStablePoolFactory', { args: [vault.address, vault.getFeesProvider().address] });
factoryVersion = JSON.stringify({
name: 'ComposableStablePoolFactory',
version: '1',
deployment: 'test-deployment',
});
poolVersion = JSON.stringify({
name: 'ComposableStablePool',
version: '0',
deployment: 'test-deployment',
});
factory = await deploy('ComposableStablePoolFactory', {
args: [vault.address, vault.getFeesProvider().address, factoryVersion, poolVersion],
});
createTime = await currentTimestamp();

tokens = await TokenList.create(['baDAI', 'baUSDC', 'baUSDT'], { sorted: true });
Expand Down Expand Up @@ -70,10 +83,22 @@ describe('ComposableStablePoolFactory', function () {
pool = await createPool();
});

it('sets the factory version', async () => {
expect(await factory.version()).to.equal(factoryVersion);
});

it('sets the vault', async () => {
expect(await pool.getVault()).to.equal(vault.address);
});

it('sets the pool version', async () => {
expect(await pool.version()).to.equal(poolVersion);
});

it('gets pool version from the factory', async () => {
expect(await factory.getPoolVersion()).to.equal(poolVersion);
});

it('registers tokens in the vault', async () => {
const poolId = await pool.getPoolId();
const poolTokens = await vault.getPoolTokens(poolId);
Expand Down
2 changes: 2 additions & 0 deletions pvt/helpers/src/models/pools/stable/StablePoolDeployer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export default {
bufferPeriodDuration,
amplificationParameter,
from,
version,
} = params;

const owner = TypesConverter.toAddress(params.owner);
Expand All @@ -56,6 +57,7 @@ export default {
pauseWindowDuration,
bufferPeriodDuration,
owner,
version: version,
},
],
from,
Expand Down
2 changes: 2 additions & 0 deletions pvt/helpers/src/models/pools/stable/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export type RawStablePoolDeployment = {
from?: SignerWithAddress;
vault?: Vault;
mockedVault?: boolean;
version?: string;
};

export type StablePoolDeployment = {
Expand All @@ -134,6 +135,7 @@ export type StablePoolDeployment = {
rateProviders: Account[];
tokenRateCacheDurations: BigNumberish[];
exemptFromYieldProtocolFeeFlags: boolean[];
version: string;
pauseWindowDuration?: BigNumberish;
bufferPeriodDuration?: BigNumberish;
owner?: SignerWithAddress;
Expand Down
3 changes: 3 additions & 0 deletions pvt/helpers/src/models/types/TypesConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export default {
swapFeePercentage,
pauseWindowDuration,
bufferPeriodDuration,
version,
} = params;

if (!tokens) tokens = new TokenList();
Expand All @@ -144,6 +145,7 @@ export default {
if (!pauseWindowDuration) pauseWindowDuration = 3 * MONTH;
if (!bufferPeriodDuration) bufferPeriodDuration = MONTH;
if (!exemptFromYieldProtocolFeeFlags) exemptFromYieldProtocolFeeFlags = Array(tokens.length).fill(false);
if (!version) version = 'test';

return {
tokens,
Expand All @@ -155,6 +157,7 @@ export default {
pauseWindowDuration,
bufferPeriodDuration,
owner: params.owner,
version,
};
},

Expand Down