Skip to content

Commit

Permalink
Added vETH-wETH Aura SY & Adjust deployment script/docs
Browse files Browse the repository at this point in the history
  • Loading branch information
ngfam committed Jul 21, 2023
1 parent faeb910 commit 19c84c1
Show file tree
Hide file tree
Showing 11 changed files with 239 additions and 33 deletions.
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,49 @@ ETHERSCAN_KEY=...
PRIVATE_KEY=...
```

**Note**: `ETHERSCAN_KEY` should match the block explorer key of the network you are deploying.
**Note**: `ETHERSCAN_KEY` should match the block explorer key of the network you are deploying.

## Deployment

### Set up

This repository runs in yarn environment so this step is as simple as running:

```
yarn install
```

### Contract and Parameters preparation


#### SY contract
First step is to get your contract ready inside `./contracts/` folder as we currently have `./contracts/SwETHSY.sol`.

After that, you will have to fill in the parameters for the following parameters corresponding to your interest bearing token:
Next, you will prepare the deploy implementation for your SY contract in `./scripts/deploy-sy.ts`. Below is an example of SwETHSY deployment.

```ts
/**
* @dev This function aims to deploy your SY contract
* @dev The below implementation show how to deploy a SwETH SY contract
*
* To deploy your own SY contract, you need to:
* - Change the contract name / type name in "deploy<YOUR_CONTRACT_NAME>(deployer, 'YOUR_CONTRACT_NAME', [...])"
* - Change the deployment params to match your constructor arguments
*/
export async function deploySY(deployer: SignerWithAddress): Promise<IStandardizedYield> {
const sy = await deploy<SwETHSY>(deployer, 'SwETHSY', [
MarketConfiguration.name,
MarketConfiguration.symbol,
'0xf951E335afb289353dc249e82926178EaC7DEd78', // SWETH address
]);

return await getContractAt<IStandardizedYield>('IStandardizedYield', sy.address);
}
```

#### Parameters

Once you are done with SY deploy implementation, you will have to fill in the parameters for the following parameters corresponding to your interest bearing token:
```ts
/**
* @dev The following parameters are used to calculate the market deployment params
Expand Down Expand Up @@ -88,3 +122,5 @@ yarn hardhat run scripts/seed-liquidity.ts --network <YOUR_NETWORK_NAME>
We highly recommend you to use a stable RPC with good nonce management for the deployment. Otherwise sending two transactions in a row could result in transaction replacement.

The current script has already put a delay between any two transactions being sent but sometime it is still not enough on bad RPC.

Please contact us if you run into any problem.
147 changes: 147 additions & 0 deletions contracts/AuraVethWethSY.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

import "@pendle/core-v2/contracts/core/StandardizedYield/implementations/BalancerStable/base/PendleAuraBalancerStableLPSYV2.sol";
import "@pendle/core-v2/contracts/core/StandardizedYield/implementations/BalancerStable/base/ComposableStable/ComposableStablePreview.sol";

contract AuraWethVethSY is PendleAuraBalancerStableLPSYV2 {
address internal constant VETH = 0x4Bc3263Eb5bb2Ef7Ad9aB6FB68be80E43b43801F;
address internal constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

uint256 internal constant AURA_PID = 128;
address internal constant LP = 0x156C02f3f7fEf64a3A9D80CCF7085f23ccE91D76;

address internal constant COMPOSABLE_PREVIEW = 0x4239Ddd3c50463383670E86c119220849BFaF64a;

bool internal constant NO_TOKENS_EXEMPT = true;
bool internal constant ALL_TOKENS_EXEMPT = false;

constructor(
string memory _name,
string memory _symbol
)
PendleAuraBalancerStableLPSYV2(
_name,
_symbol,
LP,
AURA_PID,
ComposableStablePreview(COMPOSABLE_PREVIEW)
)
//solhint-disable-next-line
{

}

function _deposit(
address tokenIn,
uint256 amount
) internal virtual override returns (uint256 amountSharesOut) {
if (tokenIn == NATIVE) {
IWETH(WETH).deposit{ value: amount }();
amountSharesOut = super._deposit(WETH, amount);
} else {
amountSharesOut = super._deposit(tokenIn, amount);
}
}

function _redeem(
address receiver,
address tokenOut,
uint256 amountSharesToRedeem
) internal virtual override returns (uint256) {
if (tokenOut == NATIVE) {
uint256 amountTokenOut = super._redeem(address(this), WETH, amountSharesToRedeem);
IWETH(WETH).withdraw(amountTokenOut);
_transferOut(NATIVE, receiver, amountTokenOut);
return amountTokenOut;
} else {
return super._redeem(receiver, tokenOut, amountSharesToRedeem);
}
}

function _previewDeposit(
address tokenIn,
uint256 amountTokenToDeposit
) internal view virtual override returns (uint256 amountSharesOut) {
if (tokenIn == NATIVE) {
amountSharesOut = super._previewDeposit(WETH, amountTokenToDeposit);
} else {
amountSharesOut = super._previewDeposit(tokenIn, amountTokenToDeposit);
}
}

function _previewRedeem(
address tokenOut,
uint256 amountSharesToRedeem
) internal view virtual override returns (uint256 amountTokenOut) {
if (tokenOut == NATIVE) {
amountTokenOut = super._previewRedeem(WETH, amountSharesToRedeem);
} else {
amountTokenOut = super._previewRedeem(tokenOut, amountSharesToRedeem);
}
}

function _getImmutablePoolData() internal pure override returns (bytes memory ret) {
ComposableStablePreview.ImmutableData memory res;
res.poolTokens = _getPoolTokenAddresses();
res.rateProviders = _getRateProviders();
res.rawScalingFactors = _getRawScalingFactors();
res.isExemptFromYieldProtocolFee = _getExemption();
res.LP = LP;
res.noTokensExempt = NO_TOKENS_EXEMPT;
res.allTokensExempt = ALL_TOKENS_EXEMPT;
res.bptIndex = _getBPTIndex();
res.totalTokens = res.poolTokens.length;

return abi.encode(res);
}

// --------------------------------- POOL CONSTANTS ---------------------------------
function _getPoolTokenAddresses() internal pure override returns (address[] memory res) {
res = new address[](3);
res[0] = LP;
res[1] = VETH;
res[2] = WETH;
}

function _getBPTIndex() internal pure override returns (uint256) {
return 0;
}

function _getRateProviders() internal pure returns (address[] memory res) {
res = new address[](3);
res[0] = 0x0000000000000000000000000000000000000000;
res[1] = 0x12589A727aeFAc3fbE5025F890f1CB97c269BEc2;
res[2] = 0x0000000000000000000000000000000000000000;
}

function _getRawScalingFactors() internal pure returns (uint256[] memory res) {
res = new uint256[](3);
res[0] = res[1] = res[2] = 1e18;
}

function _getExemption() internal pure returns (bool[] memory res) {
res = new bool[](3);
res[0] = res[1] = res[2] = false;
}

function getTokensIn() public view virtual override returns (address[] memory res) {
res = new address[](4);
res[0] = LP;
res[1] = WETH;
res[2] = VETH;
res[3] = NATIVE;
}

function getTokensOut() public view virtual override returns (address[] memory res) {
return getTokensIn();
}

function isValidTokenIn(address token) public view virtual override returns (bool) {
return (token == LP || token == WETH || token == VETH || token == NATIVE);
}

function isValidTokenOut(address token) public view virtual override returns (bool) {
return isValidTokenIn(token);
}
}
8 changes: 4 additions & 4 deletions deployments/SY-swETH.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "SY swETH",
"symbol": "SY-swETH",
"expiry": 1750896000,
"scalarRoot": "112278200000000000000",
"initialRateAnchor": "1087110000000000000",
"doCacheIndex": true,
"expiry": 1750896000,
"scalarRoot": "106799962313000000000",
"initialRateAnchor": "1059899851000000000",
"SY": "0x4bF3B85a7ec25Ac743E4Eb21f745B1213116f4ff",
"PT": "0x83DdA45D873De56967B7aaE067180b55C7635832",
"YT": "0xB21a491068e99631590891b4553deC84555Fe75C",
"market": "0x8F8644d86b2f09839CC9dA52358535e292466c74"
"market": "0xFb3ED50aA7e997Bd588a250E6469F68a971A79DD"
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"@nomiclabs/hardhat-ethers": "^2.0.5",
"@nomiclabs/hardhat-etherscan": "^2.1.8",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"@pendle/core-v2": "^2.21.1",
"@pendle/core-v2": "^2.22.2",
"hardhat-contract-sizer": "^2.8.0",
"@typechain/ethers-v5": "^9.0.0",
"@typechain/hardhat": "^4.0.0"
Expand Down
5 changes: 2 additions & 3 deletions scripts/configuration.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { ZERO_ADDRESS } from './consts';
import { toWei } from './helper';
import { SUPPORTED_CHAINS } from './types';
import { calculateParameters } from './param-helper'
import { calculateParameters } from './param-helper';

/**
* @dev The following parameters are used to calculate the market deployment params
* @minApy and @maxApy are the minimum and maximum APY of the interest bearing asset
* @startTimestamp and @endTimestamp are the start and end time of the market
* @startTimestamp and @endTimestamp are the start and end time of the market
*/
const minApy = 0.01; // 1%
const maxApy = 0.05; // 5%
Expand Down
22 changes: 22 additions & 0 deletions scripts/deploy-sy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
import { IStandardizedYield, SwETHSY } from '../typechain-types';
import { deploy, getContractAt } from './helper';
import { MarketConfiguration } from './configuration';

/**
* @dev This function aims to deploy your SY contract
* @dev The below implementation show how to deploy a SwETH SY contract
*
* To deploy your own SY contract, you need to:
* - Change the contract name / type name in "deploy<YOUR_CONTRACT_NAME>(deployer, 'YOUR_CONTRACT_NAME', [...])"
* - Change the deployment params to match your constructor arguments
*/
export async function deploySY(deployer: SignerWithAddress): Promise<IStandardizedYield> {
const sy = await deploy<SwETHSY>(deployer, 'SwETHSY', [
MarketConfiguration.name,
MarketConfiguration.symbol,
'0xf951E335afb289353dc249e82926178EaC7DEd78', // SWETH address
]);

return await getContractAt<IStandardizedYield>('IStandardizedYield', sy.address);
}
18 changes: 11 additions & 7 deletions scripts/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { ethers } from 'hardhat';
import { JSONReplacerBigNum, delay, deploy, getPendleContracts } from './helper';
import { SwETHSY } from '../typechain-types';
import { MarketConfiguration } from './configuration';
import { SUPPORTED_CHAINS } from './types';
import fs from 'fs';
import path from 'path';
import { SAFE_WAIT_TIME } from './consts';
import { deploySY } from './deploy-sy';

const SWETH = '0xf951E335afb289353dc249e82926178EaC7DEd78';

Expand All @@ -14,11 +13,7 @@ async function main() {

const pendleContracts = await getPendleContracts();

const sy = await deploy<SwETHSY>(deployer, 'SwETHSY', [
MarketConfiguration.name,
MarketConfiguration.symbol,
SWETH,
]);
const sy = await deploySY(deployer);

await delay(SAFE_WAIT_TIME, 'before deploying PT/YT');

Expand Down Expand Up @@ -47,6 +42,15 @@ async function main() {
MarketConfiguration.scalarRoot,
MarketConfiguration.initialRateAnchor
);
await delay(SAFE_WAIT_TIME, 'after create market');

// approve inf tokenIns for the path of pendle router -> sy address
await pendleContracts.router.approveInf([
{
tokens: await sy.getTokensIn(),
spender: sy.address,
},
]);

fs.writeFileSync(
path.resolve(__dirname, '../deployments', `${MarketConfiguration.symbol}.json`),
Expand Down
8 changes: 7 additions & 1 deletion scripts/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ export async function verifyContract(contract: string, constructor: any[]) {
}
}

/**
*
* @param deployer signer for deployer
* @param abiType abi type (contract name)
* @param args constructor arguments
* @returns the contract itself with specified type
*/
export async function deploy<CType extends Contract>(deployer: SignerWithAddress, abiType: string, args: any[]) {
console.log(`Deploying ${abiType}...`);
const contractFactory = await hre.ethers.getContractFactory(abiType);
Expand Down Expand Up @@ -92,4 +99,3 @@ export async function safeApproveInf(deployer: SignerWithAddress, token: string,
const allowance = await contract.allowance(deployer.address, to);
if (allowance.lt(INF.div(2))) await contract.connect(deployer).approve(to, INF);
}

5 changes: 3 additions & 2 deletions scripts/param-helper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { toWei } from "./helper";
import { BigNumber } from 'ethers';
import { toWei } from './helper';

/**
* Validates the given start and end timestamps.
Expand Down Expand Up @@ -31,7 +32,7 @@ export function calculateParameters(
rateMax: number,
startTimestamp: number,
endTimestamp: number
): { scalarRoot: BN; initialRateAnchor: BN } {
): { scalarRoot: BigNumber; initialRateAnchor: BigNumber } {
validateTimestamps(startTimestamp, endTimestamp);
const yearsToExpiry = (endTimestamp - startTimestamp) / 31536000;
const rateMinScaled = Math.pow(rateMin + 1, yearsToExpiry);
Expand Down
9 changes: 0 additions & 9 deletions scripts/seed-liquidity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,6 @@ async function main() {
const YT = await getContractAt<IERC20>('IERC20', marketAddresses.YT);
const LP = await getContractAt<IERC20>('IERC20', marketAddresses.market);

// approve inf tokenIns for router
await pendleContracts.router.approveInf([
{
tokens: await SY.getTokensIn(),
spender: SY.address,
},
]);
await delay(SAFE_WAIT_TIME, 'after approveInf on router');

await pendleContracts.router.mintSyFromToken(
deployer.address,
SY.address,
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -804,10 +804,10 @@
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.3.3.tgz#ff6ee919fc2a1abaf72b22814bfb72ed129ec137"
integrity sha512-tDBopO1c98Yk7Cv/PZlHqrvtVjlgK5R4J6jxLwoO7qxK4xqOiZG+zSkIvGFpPZ0ikc3QOED3plgdqjgNTnBc7g==

"@pendle/core-v2@^2.21.1":
version "2.21.1"
resolved "https://registry.yarnpkg.com/@pendle/core-v2/-/core-v2-2.21.1.tgz#ad6ee6ade06be75bdf083e5ee6b40d0cd70252e5"
integrity sha512-FwFi5GzT1BK1ehxMmNFVBbJqLJQUEy2UvaBG4elZP1dt96ceKSBBy/7XpO5kl6FwT1/TwEqD292MHE4punVi1A==
"@pendle/core-v2@^2.22.2":
version "2.22.2"
resolved "https://registry.yarnpkg.com/@pendle/core-v2/-/core-v2-2.22.2.tgz#e29ab39d0a1e65ff71021f385ee44ad70449286d"
integrity sha512-85Nk2zKqKKpEJChiLmrW5aO3XXf3QJDRpvbyWInFJ7XT3lGck6uZQ7Pa35Mg4yzd/DJHcOtRNfDKFx3HKcb8Wg==
dependencies:
"@chainlink/contracts" "^0.6.1"
"@openzeppelin/contracts" "4.7.3"
Expand Down

0 comments on commit 19c84c1

Please sign in to comment.