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

Update to Deploy 11 #502

Merged
merged 8 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
314 changes: 314 additions & 0 deletions examples/createAndInitPool/createAndInitPoolV3.ts
Copy link
Member

@MattPereira MattPereira Nov 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This v3 pool creation script is still kinda messy and would benefit from Permit2helper method, but seems like decent pinch option for deploying v3 pools and could start discussion about examples that are set up to send transactions to live network

No worries if you prefer to dump it for this PR, just thought I'd offer the option for consideration

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can leave it in for now but should be tidied as part of wider example changes.

Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
/**
* Quick script to deploy partially boosted pool we need for testing
*
* Run with:
* pnpm example ./examples/createAndInitPool/createAndInitPoolV3.ts
*/

import { config } from 'dotenv';
config();

import {
// createTestClient,
http,
publicActions,
// walletActions,
zeroAddress,
parseUnits,
createWalletClient,
getContract,
PrivateKeyAccount,
} from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import {
stablePoolFactoryAbi_V3,
CreatePoolV3StableInput,
CreatePool,
PoolType,
ChainId,
CHAINS,
InitPoolDataProvider,
InitPool,
InitPoolInput,
TokenType,
PERMIT2,
BALANCER_ROUTER,
permit2Abi,
erc20Abi,
MaxAllowanceExpiration,
PermitDetails,
Permit2Batch,
MaxSigDeadline,
AllowanceTransfer,
balancerRouterAbi,
PublicWalletClient,
} from 'src';
// import { startFork, ANVIL_NETWORKS } from 'test/anvil/anvil-global-setup';
import { findEventInReceiptLogs } from 'test/lib/utils/findEventInReceiptLogs';
// import { makeForkTx } from 'examples/lib/makeForkTx';
// import { getSlot } from 'examples/lib/getSlot';

const SWAP_FEE_PERCENTAGE_DECIMALS = 16;
const AAVE_FAUCET_USDT = {
address: '0xaa8e23fb1079ea71e0a56f48a2aa51851d8433d0' as `0x${string}`,
decimals: 6,
};
const STATA_ETH_DAI = {
address: '0xDE46e43F46ff74A23a65EBb0580cbe3dFE684a17' as `0x${string}`,
rateProvider: '0x22db61f3a8d81d3d427a157fdae8c7eb5b5fd373' as `0x${string}`,
decimals: 18,
};

async function runAgainstFork() {
// User defined inputs
// const { rpcUrl } = await startFork(ANVIL_NETWORKS.SEPOLIA);
const rpcUrl = process.env.SEPOLIA_RPC_URL;
const chainId = ChainId.SEPOLIA;

const userAccount = privateKeyToAccount(
process.env.PRIVATE_KEY as `0x${string}`,
);

// Use this client to submit txs to live network
const client = createWalletClient({
chain: CHAINS[chainId],
transport: http(rpcUrl),
account: userAccount,
}).extend(publicActions);

// Use this client to run against a local fork
// const client = createTestClient({
// mode: 'anvil',
// chain: CHAINS[chainId],
// transport: http(rpcUrl),
// })
// .extend(publicActions)
// .extend(walletActions);

const createPoolInput: CreatePoolV3StableInput = {
name: 'USDT stataDAI partially boosted',
symbol: 'USDT-stataDAI',
poolType: PoolType.Stable,
tokens: [
{
address: AAVE_FAUCET_USDT.address,
rateProvider: zeroAddress,
tokenType: TokenType.STANDARD,
paysYieldFees: false,
},
{
address: STATA_ETH_DAI.address,
rateProvider: STATA_ETH_DAI.rateProvider,
tokenType: TokenType.TOKEN_WITH_RATE,
paysYieldFees: true,
},
],
amplificationParameter: BigInt(33),
swapFeePercentage: parseUnits('0.001', SWAP_FEE_PERCENTAGE_DECIMALS),
pauseManager: zeroAddress,
swapFeeManager: zeroAddress,
poolHooksContract: zeroAddress,
enableDonation: false,
disableUnbalancedLiquidity: false,
protocolVersion: 3,
chainId,
};
const initAmounts = [
{
address: AAVE_FAUCET_USDT.address,
rawAmount: parseUnits('10', AAVE_FAUCET_USDT.decimals),
decimals: AAVE_FAUCET_USDT.decimals,
},
{
address: STATA_ETH_DAI.address,
rawAmount: parseUnits('10', STATA_ETH_DAI.decimals),
decimals: STATA_ETH_DAI.decimals,
},
];

// Build the create pool call using the SDK
const call = await createPoolCall(createPoolInput);

// Submit the create pool tx and wait for the PoolCreated event to find pool address
const poolAddress = await createPool({ client, call, userAccount });
console.log('Created Pool Address: ', poolAddress);

// Approve permit2 contract to spend tokens used for init
for (const token of initAmounts) {
const tokenContract = getContract({
address: token.address,
abi: erc20Abi,
client,
});
await tokenContract.write.approve([PERMIT2[chainId], token.rawAmount]);
}

// Build the init pool call using the SDK
const initCall = await initPool({
chainId,
rpcUrl,
userAccount,
poolAddress,
initAmounts,
});

// Set up batch and sig for permit2
const { batch, signature } = await createPermit2({
client,
userAccount,
initAmounts,
chainId,
});

// Init the pool with permitBatchAndCall
const router = getContract({
address: BALANCER_ROUTER[chainId],
abi: balancerRouterAbi,
client,
});
const args = [[], [], batch, signature, [initCall.callData]] as const;
const hash = await router.write.permitBatchAndCall(args);
console.log('hash', hash);

// Make the tx against the local fork and print the result
// await makeForkTx(
// initCall,
// {
// rpcUrl,
// chainId,
// impersonateAccount: userAccount.address,
// forkTokens: initAmounts.map((a) => ({
// address: a.address,
// slot: getSlot(chainId, a.address),
// rawBalance: a.rawAmount,
// })),
// },
// [...initAmounts.map((a) => a.address), poolAddress],
// createPoolInput.protocolVersion,
// );
}

const createPoolCall = async (createPoolInput) => {
const createPool = new CreatePool();
const call = createPool.buildCall(createPoolInput);
return call;
};

const initPool = async ({
chainId,
rpcUrl,
userAccount,
poolAddress,
initAmounts,
}) => {
const initPool = new InitPool();
const poolType = PoolType.Stable;
const initPoolDataProvider = new InitPoolDataProvider(chainId, rpcUrl);

const initPoolInput: InitPoolInput = {
sender: userAccount,
recipient: userAccount,
amountsIn: initAmounts,
chainId,
minBptAmountOut: 0n,
};

const poolState = await initPoolDataProvider.getInitPoolData(
poolAddress,
poolType,
3,
);

const call = initPool.buildCall(initPoolInput, poolState);
console.log('init pool call', call);
return call;
};

async function createPool({ client, call, userAccount }) {
const hash = await client.sendTransaction({
to: call.to,
data: call.callData,
account: userAccount,
});
const transactionReceipt = await client.waitForTransactionReceipt({
hash,
});

const poolCreatedEvent = findEventInReceiptLogs({
receipt: transactionReceipt,
eventName: 'PoolCreated',
abi: stablePoolFactoryAbi_V3,
to: call.to,
});

const {
args: { pool: poolAddress },
} = poolCreatedEvent;
return poolAddress;
}

async function createPermit2({
client,
userAccount,
initAmounts,
chainId,
}: {
client: PublicWalletClient;
userAccount: PrivateKeyAccount;
initAmounts: {
address: `0x${string}`;
rawAmount: bigint;
decimals: number;
}[];
chainId: ChainId;
}) {
const owner = userAccount.address;
const permit2Contract = getContract({
address: PERMIT2[chainId],
abi: permit2Abi,
client,
});

const details: PermitDetails[] = await Promise.all(
initAmounts.map(async (token) => {
const [, , nonce] = await permit2Contract.read.allowance([
owner,
token.address,
BALANCER_ROUTER[chainId],
]);

return {
token: token.address,
amount: token.rawAmount,
expiration: Number(MaxAllowanceExpiration),
nonce,
};
}),
);

const batch: Permit2Batch = {
details,
spender: BALANCER_ROUTER[chainId],
sigDeadline: MaxSigDeadline,
};

const { domain, types, values } = AllowanceTransfer.getPermitData(
batch,
PERMIT2[chainId],
chainId,
);

const signature = await client.signTypedData({
account: userAccount,
message: {
...values,
},
domain,
primaryType: 'PermitBatch',
types,
});

return { batch, signature };
}

export default runAgainstFork;
2 changes: 1 addition & 1 deletion test/anvil/anvil-global-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const ANVIL_NETWORKS: Record<NetworksWithFork, NetworkSetup> = {
rpcEnv: 'SEPOLIA_RPC_URL',
fallBackRpc: 'https://sepolia.gateway.tenderly.co',
port: ANVIL_PORTS.SEPOLIA,
forkBlockNumber: 7164489n,
forkBlockNumber: 7167280n, // Matt moved this blockNo after deploying new partial boosted pool
johngrantuk marked this conversation as resolved.
Show resolved Hide resolved
},
OPTIMISM: {
rpcEnv: 'OPTIMISM_RPC_URL',
Expand Down
4 changes: 2 additions & 2 deletions test/mockData/partialBoostedPool.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { PoolStateWithUnderlyings } from '@/entities';

export const partialBoostedPool_USDT_stataDAI: PoolStateWithUnderlyings = {
id: '0x31e7f3a9b9c834a752887723b017397e928d9ede',
address: '0x31e7f3a9b9c834a752887723b017397e928d9ede',
id: '0xCE7601b157e0871332D2295F274a0f4314a1585D',
address: '0xCE7601b157e0871332D2295F274a0f4314a1585D',
type: 'Stable',
protocolVersion: 3,
tokens: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const usdtToken = new Token(chainId, USDT.address, USDT.decimals);
const daiToken = new Token(chainId, DAI.address, DAI.decimals);

// TODO: pending test pool to be created/initialized
describe.skip('V3 add liquidity partial boosted', () => {
describe('V3 add liquidity partial boosted', () => {
let rpcUrl: string;
let client: PublicWalletClient & TestActions;
let testAddress: Address;
Expand Down
Loading