Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main'
Browse files Browse the repository at this point in the history
# Conflicts:
#	deployments/SY-swETH.json
#	package.json
#	scripts/configuration.ts
#	scripts/consts.ts
#	yarn.lock
  • Loading branch information
aaron-alderman committed Aug 2, 2023
2 parents 41e8483 + b9505f0 commit 45bd785
Show file tree
Hide file tree
Showing 13 changed files with 3,419 additions and 2,780 deletions.
73 changes: 62 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,70 @@ 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

## Hardhat configuration

Firstly, configure your network (arbitrum/bsc/mainnet) inside `./hardhat.config.ts`.
### Set up

Secondly, please also configure the `NETWORK` variable in `./scripts/configuration.ts` accordingly:
This repository runs in yarn environment so this step is as simple as running:

```ts
export const NETWORK = SUPPORTED_CHAINS.MAINNET;
```

## Deployment
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 `MarketConfiguration` in `./scripts/configuration.ts`.
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
* @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
*/
const minApy = 0.01; // 1%
const maxApy = 0.05; // 5%
const startTimestamp = 1689206400;
const endTimestamp = 1750896000;

export const MarketConfiguration = {
name: 'SY swETH',
symbol: 'SY-swETH',
doCacheIndex: true,
expiry: endTimestamp,
...calculateParameters(minApy, maxApy, startTimestamp, endTimestamp),
};
```

The remaining three fields in MarketConfiguration are `name`, `symbol` (quite straight-forward) and `doCacheIndex`. For `doCacheIndex`, we usually leave it as `true` for ethereum mainnet deployment and `false` for any other chain to save gas for PT/YT related transactions.

### Run deployment script

Expand All @@ -51,6 +95,11 @@ This step is only to ensure your market has minimum liquidity before you can act

### Parameters preparation

Inside `./scripts/seed-liquidity.ts`, make sure the import in line 6 is point to your according deployment output file, in case of swETH, it should be:
```ts
import marketAddresses from '../deployments/SY-swETH.json';
```

Inside `./scripts/configuration.ts`, please fill in the parameters for these two variables:

```ts
Expand All @@ -70,11 +119,13 @@ export const AMOUNT_TO_SEED = toWei(0.01);
### Run script

```
yarn hardhat run scripts/seed-liquidity.ts
yarn hardhat run scripts/seed-liquidity.ts --network <YOUR_NETWORK_NAME>
```

## Final notes

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.
160 changes: 160 additions & 0 deletions contracts/AuraEthxBbAWethSY.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// 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";
import "@pendle/core-v2/contracts/core/StandardizedYield/implementations/BalancerStable/base/Linear/BbAPoolHelper.sol";

contract AuraEthxBbAWethSY is PendleAuraBalancerStableLPSYV2, BbAWethHelper {
uint256 internal constant AURA_PID = 134;
address internal constant LP = 0x4CbdE5C4B4B53EBE4aF4adB85404725985406163;
address internal constant ETHx = 0xA35b1B31Ce002FBF2058D22F30f95D405200A15b;

address internal constant LINEAR_PREVIEW = 0x73187e5b27F2aadD5fFee023d6a9E179365F2ad6;
address internal constant COMPOSABLE_PREVIEW = 0x4239Ddd3c50463383670E86c119220849BFaF64a;

address internal constant _BB_A_WETH = 0xbB6881874825E60e1160416D6C426eae65f2459E;
address internal constant _WA_WETH = 0x03928473f25bb2da6Bc880b07eCBaDC636822264;
bytes32 internal constant _BB_A_WETH_POOL_ID =
0xbb6881874825e60e1160416d6c426eae65f2459e000000000000000000000592;

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

constructor(
string memory _name,
string memory _symbol
)
BbAWethHelper(LinearPreview(LINEAR_PREVIEW), _BB_A_WETH, _BB_A_WETH_POOL_ID, _WA_WETH)
PendleAuraBalancerStableLPSYV2(
_name,
_symbol,
LP,
AURA_PID,
ComposableStablePreview(COMPOSABLE_PREVIEW)
)
//solhint-disable-next-line
{

}

function _deposit(
address tokenIn,
uint256 amount
) internal override returns (uint256 amountSharesOut) {
if (tokenIn == NATIVE || tokenIn == WETH || tokenIn == WA_WETH) {
uint256 amountBbAWeth = _depositBbAWeth(tokenIn, amount);
amountSharesOut = super._deposit(BB_A_WETH, amountBbAWeth);
} else {
amountSharesOut = super._deposit(tokenIn, amount);
}
}

function _redeem(
address receiver,
address tokenOut,
uint256 amountSharesToRedeem
) internal override returns (uint256 amountTokenOut) {
if (tokenOut == NATIVE || tokenOut == WETH || tokenOut == WA_WETH) {
uint256 amountBbAWeth = super._redeem(address(this), BB_A_WETH, amountSharesToRedeem);
amountTokenOut = _redeemBbAWeth(receiver, tokenOut, amountBbAWeth);
} else {
return super._redeem(receiver, tokenOut, amountSharesToRedeem);
}
}

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

function _previewRedeem(
address tokenOut,
uint256 amountSharesToRedeem
) internal view override returns (uint256 amountTokenOut) {
if (tokenOut == NATIVE || tokenOut == WETH || tokenOut == WA_WETH) {
uint256 amountBbAWeth = super._previewRedeem(BB_A_WETH, amountSharesToRedeem);
amountTokenOut = _previewRedeemBbAWeth(tokenOut, amountBbAWeth);
} else {
return 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] = ETHx;
res[2] = _BB_A_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] = 0xAAE054B9b822554dd1D9d1F48f892B4585D3bbf0;
res[2] = 0xbB6881874825E60e1160416D6C426eae65f2459E;
}

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 override returns (address[] memory res) {
res = new address[](6);
res[0] = NATIVE;
res[1] = WETH;
res[2] = WA_WETH;
res[3] = BB_A_WETH;
res[4] = ETHx;
res[5] = LP;
}

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

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

function isValidTokenOut(address token) public view override returns (bool) {
return isValidTokenIn(token);
}
}
Loading

0 comments on commit 45bd785

Please sign in to comment.