Skip to content

Commit

Permalink
Merge pull request #425 from balancer/stable-pool-creation
Browse files Browse the repository at this point in the history
Stable pool creation
  • Loading branch information
MattPereira authored Oct 7, 2024
2 parents 15a856e + 128313b commit 092cd77
Show file tree
Hide file tree
Showing 21 changed files with 788 additions and 211 deletions.
5 changes: 5 additions & 0 deletions .changeset/rare-scissors-reflect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@balancer/sdk": minor
---

Support for v3 stable pool creation
1 change: 1 addition & 0 deletions src/abi/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export * from './weightedPoolFactoryV4.V2';
export * from './weightedPoolV4.V2';
export * from './weightedPool.V3';
export * from './vaultAdmin.V3';
export * from './stablePoolFactory.V3';
246 changes: 246 additions & 0 deletions src/abi/stablePoolFactory.V3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
export const stablePoolFactoryAbi_V3 = [
{
inputs: [
{ internalType: 'contract IVault', name: 'vault', type: 'address' },
{
internalType: 'uint32',
name: 'pauseWindowDuration',
type: 'uint32',
},
{ internalType: 'string', name: 'factoryVersion', type: 'string' },
{ internalType: 'string', name: 'poolVersion', type: 'string' },
],
stateMutability: 'nonpayable',
type: 'constructor',
},
{ inputs: [], name: 'Disabled', type: 'error' },
{ inputs: [], name: 'MaxTokens', type: 'error' },
{ inputs: [], name: 'PoolPauseWindowDurationOverflow', type: 'error' },
{ inputs: [], name: 'SenderNotAllowed', type: 'error' },
{ inputs: [], name: 'StandardPoolWithCreator', type: 'error' },
{ anonymous: false, inputs: [], name: 'FactoryDisabled', type: 'event' },
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: 'address',
name: 'pool',
type: 'address',
},
],
name: 'PoolCreated',
type: 'event',
},
{
inputs: [
{ internalType: 'string', name: 'name', type: 'string' },
{ internalType: 'string', name: 'symbol', type: 'string' },
{
components: [
{
internalType: 'contract IERC20',
name: 'token',
type: 'address',
},
{
internalType: 'enum TokenType',
name: 'tokenType',
type: 'uint8',
},
{
internalType: 'contract IRateProvider',
name: 'rateProvider',
type: 'address',
},
{
internalType: 'bool',
name: 'paysYieldFees',
type: 'bool',
},
],
internalType: 'struct TokenConfig[]',
name: 'tokens',
type: 'tuple[]',
},
{
internalType: 'uint256',
name: 'amplificationParameter',
type: 'uint256',
},
{
components: [
{
internalType: 'address',
name: 'pauseManager',
type: 'address',
},
{
internalType: 'address',
name: 'swapFeeManager',
type: 'address',
},
{
internalType: 'address',
name: 'poolCreator',
type: 'address',
},
],
internalType: 'struct PoolRoleAccounts',
name: 'roleAccounts',
type: 'tuple',
},
{
internalType: 'uint256',
name: 'swapFeePercentage',
type: 'uint256',
},
{
internalType: 'address',
name: 'poolHooksContract',
type: 'address',
},
{ internalType: 'bool', name: 'enableDonation', type: 'bool' },
{
internalType: 'bool',
name: 'disableUnbalancedLiquidity',
type: 'bool',
},
{ internalType: 'bytes32', name: 'salt', type: 'bytes32' },
],
name: 'create',
outputs: [{ internalType: 'address', name: 'pool', type: 'address' }],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [],
name: 'disable',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [{ internalType: 'bytes4', name: 'selector', type: 'bytes4' }],
name: 'getActionId',
outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'getAuthorizer',
outputs: [
{ internalType: 'contract IAuthorizer', name: '', type: 'address' },
],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'getDefaultLiquidityManagement',
outputs: [
{
components: [
{
internalType: 'bool',
name: 'disableUnbalancedLiquidity',
type: 'bool',
},
{
internalType: 'bool',
name: 'enableAddLiquidityCustom',
type: 'bool',
},
{
internalType: 'bool',
name: 'enableRemoveLiquidityCustom',
type: 'bool',
},
{
internalType: 'bool',
name: 'enableDonation',
type: 'bool',
},
],
internalType: 'struct LiquidityManagement',
name: 'liquidityManagement',
type: 'tuple',
},
],
stateMutability: 'pure',
type: 'function',
},
{
inputs: [],
name: 'getDefaultPoolHooksContract',
outputs: [{ internalType: 'address', name: '', type: 'address' }],
stateMutability: 'pure',
type: 'function',
},
{
inputs: [{ internalType: 'bytes32', name: 'salt', type: 'bytes32' }],
name: 'getDeploymentAddress',
outputs: [{ internalType: 'address', name: '', type: 'address' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'getNewPoolPauseWindowEndTime',
outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'getOriginalPauseWindowEndTime',
outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'getPauseWindowDuration',
outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'getPoolVersion',
outputs: [{ internalType: 'string', name: '', type: 'string' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'getVault',
outputs: [
{ internalType: 'contract IVault', name: '', type: 'address' },
],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'isDisabled',
outputs: [{ internalType: 'bool', name: '', type: 'bool' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [{ internalType: 'address', name: 'pool', type: 'address' }],
name: 'isPoolFromFactory',
outputs: [{ internalType: 'bool', name: '', type: 'bool' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'version',
outputs: [{ internalType: 'string', name: '', type: 'string' }],
stateMutability: 'view',
type: 'function',
},
] as const;
2 changes: 2 additions & 0 deletions src/entities/createPool/createPoolV3/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import {
CreatePoolInput,
} from '../types';
import { CreatePoolWeightedV3 } from './weighted/createPoolWeighted';
import { CreatePoolStableV3 } from './stable/createPoolStable';

export class CreatePoolV3 implements CreatePoolBase {
private readonly createPoolTypes: Record<string, CreatePoolBase> = {};

constructor() {
this.createPoolTypes = {
[PoolType.Weighted]: new CreatePoolWeightedV3(),
[PoolType.Stable]: new CreatePoolStableV3(),
};
}

Expand Down
57 changes: 57 additions & 0 deletions src/entities/createPool/createPoolV3/stable/createPoolStable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { getRandomBytes32 } from '@/entities/utils/getRandomBytes32';
import { encodeFunctionData, zeroAddress } from 'viem';
import {
CreatePoolBase,
CreatePoolV3StableInput,
CreatePoolBuildCallOutput,
PoolRoleAccounts,
} from '../../types';
import { stablePoolFactoryAbi_V3 } from '@/abi';
import { STABLE_POOL_FACTORY_BALANCER_V3, sortByAddress } from '@/utils';
import { Hex } from '@/types';

export class CreatePoolStableV3 implements CreatePoolBase {
buildCall(input: CreatePoolV3StableInput): CreatePoolBuildCallOutput {
const callData = this.encodeCall(input);
return {
callData,
to: STABLE_POOL_FACTORY_BALANCER_V3[input.chainId],
};
}

private encodeCall(input: CreatePoolV3StableInput): Hex {
const sortedTokenConfigs = sortByAddress(input.tokens);

const roleAccounts: PoolRoleAccounts = {
pauseManager: input.pauseManager,
swapFeeManager: input.swapFeeManager,
poolCreator: zeroAddress, // balancer core pool types are not allowed to have a creator
};

const args = [
input.name || input.symbol,
input.symbol,
sortedTokenConfigs.map(
({ address, rateProvider, tokenType, paysYieldFees }) => ({
token: address,
tokenType,
rateProvider,
paysYieldFees,
}),
),
input.amplificationParameter,
roleAccounts,
input.swapFeePercentage,
input.poolHooksContract,
input.enableDonation,
input.disableUnbalancedLiquidity,
input.salt || getRandomBytes32(),
] as const;

return encodeFunctionData({
abi: stablePoolFactoryAbi_V3,
functionName: 'create',
args,
});
}
}
13 changes: 12 additions & 1 deletion src/entities/createPool/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ export type CreatePoolV3BaseInput = CreatePoolBaseInput & {
disableUnbalancedLiquidity: boolean;
};

export type CreatePoolV3StableInput = CreatePoolV3BaseInput & {
poolType: PoolType.Stable;
amplificationParameter: bigint; // value between 1e3 and 5000e3
tokens: {
address: Address;
rateProvider: Address;
tokenType: TokenType;
paysYieldFees: boolean;
}[];
};
export type CreatePoolV3WeightedInput = CreatePoolV3BaseInput & {
poolType: PoolType.Weighted;
tokens: {
Expand All @@ -63,7 +73,8 @@ export type CreatePoolV3WeightedInput = CreatePoolV3BaseInput & {
export type CreatePoolInput =
| CreatePoolV2WeightedInput
| CreatePoolV2ComposableStableInput
| CreatePoolV3WeightedInput;
| CreatePoolV3WeightedInput
| CreatePoolV3StableInput;

export type CreatePoolBuildCallOutput = {
callData: Hex;
Expand Down
13 changes: 2 additions & 11 deletions src/entities/inputValidator/inputValidatorBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import {
RemoveLiquidityInput,
RemoveLiquidityRecoveryInput,
} from '@/entities/removeLiquidity/types';
import {
CreatePoolV2ComposableStableInput,
CreatePoolV2WeightedInput,
CreatePoolV3WeightedInput,
} from '../createPool/types';
import { CreatePoolInput } from '../createPool/types';
import { InitPoolInput, InitPoolInputV3 } from '../initPool/types';
import { PoolState } from '../types';
import {
Expand All @@ -32,12 +28,7 @@ export class InputValidatorBase {
}
}

validateCreatePool(
input:
| CreatePoolV2WeightedInput
| CreatePoolV3WeightedInput
| CreatePoolV2ComposableStableInput,
) {
validateCreatePool(input: CreatePoolInput) {
validateCreatePoolTokens(input.tokens);
if (input.protocolVersion === 3) {
input.tokens.forEach(({ tokenType, rateProvider }) => {
Expand Down
Loading

0 comments on commit 092cd77

Please sign in to comment.