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

Rebase LinearPool #1955

Merged
merged 23 commits into from
Oct 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0a154f6
refactor: rename BasePool to LegacyBasePool
EndymionJkb Oct 27, 2022
0b1df67
refactor: move new BasePool out of managed pool
EndymionJkb Oct 27, 2022
c25fe9b
refactor: generalize BasePool to handle LinearPool's need for the rec…
EndymionJkb Oct 27, 2022
44e95ef
refactor: add _computeScalingFactor to helpers (no longer in BasePool)
EndymionJkb Oct 27, 2022
f32fae8
refactor: move LinearPool to BasePool
EndymionJkb Oct 27, 2022
e45dd27
refactor: some renaming and reorganization
EndymionJkb Oct 27, 2022
cdcf6d2
refactor: rename again to reduce diff
EndymionJkb Oct 27, 2022
d59c3e5
Merge branch 'master' into legacy-base
EndymionJkb Oct 27, 2022
7bc02f1
Merge branch 'legacy-base' into rebase-linear
EndymionJkb Oct 27, 2022
4113d74
Merge branch 'master' into rebase-linear
EndymionJkb Oct 27, 2022
249672a
fix: cardinality of assetManagers
EndymionJkb Oct 27, 2022
cdabe65
refactor: don't mint if 0 tokens
EndymionJkb Oct 27, 2022
c05662e
refactor: adjust to constant composable BPT index
EndymionJkb Oct 27, 2022
cc2ed9a
lint
EndymionJkb Oct 28, 2022
a844d60
docs: move comments
EndymionJkb Oct 28, 2022
b8d2766
refactor: refactor token sorting; remove unused function
EndymionJkb Oct 28, 2022
3a8e138
eslint
EndymionJkb Oct 28, 2022
5db0a2d
lint (function args)
EndymionJkb Oct 28, 2022
2051692
lint
EndymionJkb Oct 28, 2022
f067e39
refactor: inline constants
EndymionJkb Oct 28, 2022
4fdfa20
refactor: allow minting 0 BPT
EndymionJkb Oct 28, 2022
d07d0a6
fix: encode targets
EndymionJkb Oct 28, 2022
c5741d4
test: add test to ensure target setting does not overwrite state
EndymionJkb Oct 28, 2022
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
277 changes: 153 additions & 124 deletions pkg/pool-linear/contracts/LinearPool.sol

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions pkg/pool-linear/test/LinearPool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,13 @@ describe('LinearPool', function () {
describe('set targets', () => {
const originalLowerTarget = fp(1000);
const originalUpperTarget = fp(5000);
const originalSwapFee = fp(0.057);

sharedBeforeEach('deploy pool and set initial targets', async () => {
await deployPool({ mainToken, wrappedToken, upperTarget: originalUpperTarget }, true);
await setBalances(pool, { mainBalance: originalLowerTarget.add(originalUpperTarget).div(2) });
await pool.setTargets(originalLowerTarget, originalUpperTarget);
await pool.setSwapFeePercentage(originalSwapFee);
});

const setBalances = async (
Expand Down Expand Up @@ -329,6 +331,15 @@ describe('LinearPool', function () {
});
});

it('does not overwrite other state', async () => {
const newLowerTarget = originalLowerTarget.div(2);
const newUpperTarget = originalUpperTarget.mul(2);

await pool.setTargets(newLowerTarget, newUpperTarget);

expect(await pool.getSwapFeePercentage()).to.equal(originalSwapFee);
});

it('reverts if the lower target is fractional', async () => {
const newLowerTarget = originalLowerTarget.add(1);
const newUpperTarget = originalUpperTarget;
Expand Down
15 changes: 9 additions & 6 deletions pkg/pool-utils/contracts/NewBasePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ abstract contract NewBasePool is
* This is useful to make sure Pool initialization happens only once, but derived Pools can change this value (even
* to zero) by overriding this function.
*/
function _getMinimumBpt() internal pure returns (uint256) {
function _getMinimumBpt() internal pure virtual returns (uint256) {
return _DEFAULT_MINIMUM_BPT;
}

Expand Down Expand Up @@ -214,13 +214,15 @@ abstract contract NewBasePool is

_ensureNotPaused();
if (totalSupply() == 0) {
(bptAmountOut, amountsIn) = _onInitializePool(sender, userData);
(bptAmountOut, amountsIn) = _onInitializePool(sender, recipient, userData);

// On initialization, we lock _getMinimumBpt() by minting it for the zero address. This BPT acts as a
// minimum as it will never be burned, which reduces potential issues with rounding, and also prevents the
// Pool from ever being fully drained.
// Some pool types do not require this mechanism, and the minimum BPT might be zero.
_require(bptAmountOut >= _getMinimumBpt(), Errors.MINIMUM_BPT);
_mintPoolTokens(address(0), _getMinimumBpt());

_mintPoolTokens(recipient, bptAmountOut - _getMinimumBpt());
} else {
(bptAmountOut, amountsIn) = _onJoinPool(sender, balances, userData);
Expand Down Expand Up @@ -347,10 +349,11 @@ abstract contract NewBasePool is
* The tokens granted to the Pool will be transferred from `sender`. These amounts are considered upscaled and will
* be downscaled (rounding up) before being returned to the Vault.
*/
function _onInitializePool(address sender, bytes memory userData)
internal
virtual
returns (uint256 bptAmountOut, uint256[] memory amountsIn);
function _onInitializePool(
address sender,
address recipient,
bytes memory userData
) internal virtual returns (uint256 bptAmountOut, uint256[] memory amountsIn);

/**
* @dev Called whenever the Pool is joined after the first initialization join (see `_onInitializePool`).
Expand Down
2 changes: 1 addition & 1 deletion pkg/pool-utils/contracts/test/MockNewBasePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ contract MockNewBasePool is NewBasePool {
)
{}

function _onInitializePool(address, bytes memory userData) internal override returns (uint256, uint256[] memory) {
function _onInitializePool(address, address, bytes memory userData) internal override returns (uint256, uint256[] memory) {
emit InnerOnInitializePoolCalled(userData);

uint256[] memory amountsIn = userData.initialAmountsIn();
Expand Down
10 changes: 5 additions & 5 deletions pkg/pool-weighted/contracts/managed/ManagedPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -438,11 +438,11 @@ contract ManagedPool is ManagedPoolSettings {

// Initialize

function _onInitializePool(address sender, bytes memory userData)
internal
override
returns (uint256 bptAmountOut, uint256[] memory amountsIn)
{
function _onInitializePool(
address sender,
address,
bytes memory userData
) internal override returns (uint256 bptAmountOut, uint256[] memory amountsIn) {
// Check allowlist for LPs, if applicable
_require(_isAllowedAddress(_getPoolState(), sender), Errors.ADDRESS_NOT_ALLOWLISTED);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ contract MockManagedPoolSettings is ManagedPoolSettings {
return _getVirtualSupply();
}

function _onInitializePool(address, bytes memory userData) internal override returns (uint256, uint256[] memory) {
function _onInitializePool(address, address, bytes memory userData) internal override returns (uint256, uint256[] memory) {
WeightedPoolUserData.JoinKind kind = userData.joinKind();
_require(kind == WeightedPoolUserData.JoinKind.INIT, Errors.UNINITIALIZED);

Expand Down
53 changes: 8 additions & 45 deletions pkg/solidity-utils/contracts/helpers/ERC20Helpers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ function _asIAsset(IERC20[] memory tokens) pure returns (IAsset[] memory assets)

function _sortTokens(
IERC20 tokenA,
IERC20 tokenB,
IERC20 tokenC
IERC20 tokenB
) pure returns (IERC20[] memory tokens) {
(uint256 indexTokenA, uint256 indexTokenB, uint256 indexTokenC) = _getSortedTokenIndexes(tokenA, tokenB, tokenC);
tokens = new IERC20[](3);
tokens[indexTokenA] = tokenA;
tokens[indexTokenB] = tokenB;
tokens[indexTokenC] = tokenC;
bool aFirst = tokenA < tokenB;
IERC20[] memory sortedTokens = new IERC20[](2);

sortedTokens[0] = aFirst ? tokenA : tokenB;
sortedTokens[1] = aFirst ? tokenB : tokenA;

return sortedTokens;
}

function _insertSorted(IERC20[] memory tokens, IERC20 token) pure returns (IERC20[] memory sorted) {
Expand Down Expand Up @@ -65,41 +66,3 @@ function _findTokenIndex(IERC20[] memory tokens, IERC20 token) pure returns (uin

_revert(Errors.INVALID_TOKEN);
}

function _getSortedTokenIndexes(
IERC20 tokenA,
IERC20 tokenB,
IERC20 tokenC
)
pure
returns (
uint256 indexTokenA,
uint256 indexTokenB,
uint256 indexTokenC
)
{
if (tokenA < tokenB) {
if (tokenB < tokenC) {
// (tokenA, tokenB, tokenC)
return (0, 1, 2);
} else if (tokenA < tokenC) {
// (tokenA, tokenC, tokenB)
return (0, 2, 1);
} else {
// (tokenC, tokenA, tokenB)
return (1, 2, 0);
}
} else {
// tokenB < tokenA
if (tokenC < tokenB) {
// (tokenC, tokenB, tokenA)
return (2, 1, 0);
} else if (tokenC < tokenA) {
// (tokenB, tokenC, tokenA)
return (2, 0, 1);
} else {
// (tokenB, tokenA, tokenC)
return (1, 0, 2);
}
}
}
11 changes: 11 additions & 0 deletions pkg/solidity-utils/contracts/helpers/ScalingHelpers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
pragma solidity ^0.7.0;

import "../math/FixedPoint.sol";
import "../math/Math.sol";
import "../openzeppelin/ERC20.sol";
import "./InputHelpers.sol";

// solhint-disable
Expand Down Expand Up @@ -93,3 +95,12 @@ function _downscaleUpArray(uint256[] memory amounts, uint256[] memory scalingFac
amounts[i] = FixedPoint.divUp(amounts[i], scalingFactors[i]);
}
}

function _computeScalingFactor(IERC20 token) view returns (uint256) {
// Tokens that don't implement the `decimals` method are not supported.
uint256 tokenDecimals = ERC20(address(token)).decimals();

// Tokens with more than 18 decimals are not supported.
uint256 decimalsDifference = Math.sub(18, tokenDecimals);
return FixedPoint.ONE * 10**decimalsDifference;
}
22 changes: 20 additions & 2 deletions pvt/helpers/src/models/pools/linear/LinearPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ export default class LinearPool extends BasePool {
);
}

// Order the tokens the same way the Vault will
static getTokenList(mainToken: Token, wrappedToken: Token, bptToken: Token): TokenList {
const tokens: Token[] = [];

tokens.push(bptToken);
tokens.push(mainToken.address < wrappedToken.address ? mainToken : wrappedToken);
tokens.push(mainToken.address < wrappedToken.address ? wrappedToken : mainToken);

return new TokenList(tokens);
}

constructor(
instance: Contract,
poolId: string,
Expand All @@ -69,7 +80,14 @@ export default class LinearPool extends BasePool {
swapFeePercentage: BigNumberish,
owner?: SignerWithAddress
) {
super(instance, poolId, vault, new TokenList([wrappedToken, mainToken, bptToken]).sort(), swapFeePercentage, owner);
super(
instance,
poolId,
vault,
LinearPool.getTokenList(mainToken, wrappedToken, bptToken),
swapFeePercentage,
owner
);
this.mainToken = mainToken;
this.wrappedToken = wrappedToken;
this.bptToken = bptToken;
Expand All @@ -83,7 +101,7 @@ export default class LinearPool extends BasePool {
}

get getLinearTokens(): TokenList {
return new TokenList([this.wrappedToken, this.mainToken, this.bptToken]).sort();
return LinearPool.getTokenList(this.mainToken, this.wrappedToken, this.bptToken);
}

get mainIndex(): number {
Expand Down