Skip to content

Commit

Permalink
Merge pull request #14 from alpaca-finance/chore/pyth-paradeen-feed-s…
Browse files Browse the repository at this point in the history
…cript

[main][chore] pyth paradeen feed script
  • Loading branch information
wow-alpaca authored Mar 18, 2024
2 parents 3a318d9 + 039e80c commit c3d0444
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 1 deletion.
2 changes: 1 addition & 1 deletion contracts.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,4 @@
"AP": "0x2Fb74F8E1e9EFaEEc31e57946e0C1bC6853ca4f1",
"rewardToken": "0xb0188B0bb2cD4a6D2744637fC83C94a284B247Da"
}
}
}
1 change: 1 addition & 0 deletions contracts.tenderly.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"TradeMining": {
"tradeMiningManager": "0x480DC16F44401235E20f849384f764f50B3Adb46",
"paradeen": "0x06ed8e9DD7e3CAee9461145Cc8D7747d0Da23b21",
"pythParadeen": "",
"AP": "0xF12Ef0f68521761192e04343a013980947223Ca3",
"rewardToken": "0x55d398326f99059fF775485246999027B3197955"
}
Expand Down
144 changes: 144 additions & 0 deletions deploy/trade-mining/paradeen-feed-pyth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";
import { ethers } from "hardhat";
import { getConfig } from "../utils/config";
import { BigNumber } from "ethers";
import {
AP__factory,
ERC20__factory,
Paradeen__factory,
} from "../../typechain";
import * as readlineSync from "readline-sync";
import { getCoinGeckoPriceUSD } from "../utils/price";
import { formatEther } from "ethers/lib/utils";

interface FeedParadeenParams {
weekTimestamp: BigNumber;
amount: BigNumber;
}

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const config = getConfig();
const signer = (await ethers.getSigners())[0];
const pythExponent = BigNumber.from(10).pow(6);

// contracts
const ap = AP__factory.connect(config.TradeMining.AP, ethers.provider);
const pyth = ERC20__factory.connect(config.TradeMining.rewardToken, signer);
const paradeen = Paradeen__factory.connect(
config.TradeMining.pythParadeen,
signer
);

// constants
const E18 = BigNumber.from(10).pow(18);
const WEEK = BigNumber.from(604800);
const MAX_BPS = BigNumber.from(10000);

// configs
const tradingFeeBps = 9;
const weeklyFeeThreshold = BigNumber.from(20000).mul(E18);
const endTimestamp = 1716422400; // May 23, 2024

console.log(`> Prepare data...`);

const currentBlock = await ethers.provider.getBlock("latest");
const weekCursor = BigNumber.from(currentBlock.timestamp).div(WEEK).mul(WEEK);

const weeklyTradingVolume = await ap.weeklyTotalSupply(weekCursor);
const tradingFeeCollected = weeklyTradingVolume
.mul(tradingFeeBps)
.mul(2) // account closing volume assure
.div(MAX_BPS);
const pythPrice = await getCoinGeckoPriceUSD("pyth-network");

console.log(`> Weekly trading volume: ${formatEther(weeklyTradingVolume)}`);
console.log(`> Trading fee collected: ${formatEther(tradingFeeCollected)}`);
console.log(`> Pyth price: ${formatEther(pythPrice)}\n`);

let amountToFeed: BigNumber;

if (tradingFeeCollected.lt(weeklyFeeThreshold)) {
console.log(
`> Trading fee collected is < ${formatEther(weeklyFeeThreshold)} USD`
);
amountToFeed = tradingFeeCollected.mul(E18).div(pythPrice);
} else {
console.log(
`> Trading fee collected is > ${formatEther(weeklyFeeThreshold)} USD`
);
amountToFeed = weeklyFeeThreshold.mul(E18).div(pythPrice);
}

console.log(`> Amount to feed: ${formatEther(amountToFeed)} Pyth`);

const PARAMS_INPUT: Array<FeedParadeenParams> = [
{
weekTimestamp: weekCursor,
amount: amountToFeed.mul(pythExponent).div(E18),
},
];

// Check feed timestamp
const weeklyReward = await paradeen.tokensPerWeek(weekCursor);
if (weeklyReward.gt(0)) {
console.log("====================================");
console.log(
`> Weekly reward for ${weekCursor}: ${formatEther(
weeklyReward.mul(E18).div(pythExponent)
)} Pyth`
);
console.log(`> Already fed for this week`);
const goNext = readlineSync.question(
"Confirm to re-feed (increase)? (y/n): "
);
switch (goNext.toLowerCase()) {
case "y":
break;
case "n":
console.log("Aborting");
return;
default:
console.log("Invalid input");
return;
}
}

if (weekCursor.gt(endTimestamp)) {
console.log("> The campaign has ended, no need to feed");
return;
}

// Ask for confirmation
console.table(PARAMS_INPUT);
const confirm = readlineSync.question("Confirm? (y/n): ");
switch (confirm.toLowerCase()) {
case "y":
break;
case "n":
console.log("Aborting");
return;
default:
console.log("Invalid input");
return;
}

const timestamps = PARAMS_INPUT.map((p) =>
p.weekTimestamp.div(WEEK).mul(WEEK)
);
const amounts = PARAMS_INPUT.map((p) => p.amount);

console.log("> Approving Pyth to Paradeen...");
const approvedTx = await pyth.approve(paradeen.address, amountToFeed);
console.log(`> ⛓ Tx submitted: ${approvedTx.hash}`);

console.log("> Feeding rewards to Paradeen");
const tx = await paradeen.feed(timestamps, amounts);
console.log(`> ⛓ Tx submitted: ${tx.hash}`);
console.log(`> Waiting tx to be mined...`);
await tx.wait();
console.log(`> Tx mined!`);
};

export default func;
func.tags = ["FeedParadeenPyth"];
19 changes: 19 additions & 0 deletions deploy/utils/price.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import axios from "axios";
import { BigNumber } from "ethers";
import { parseEther } from "ethers/lib/utils";

export async function getCoinGeckoPriceUSD(
assetId: string
): Promise<BigNumber> {
let tokenPrice = BigNumber.from(0);
try {
const response = await axios.get(
`https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=${assetId}`
);
tokenPrice = parseEther(response.data[0]["current_price"].toString());
} catch (error) {
throw new Error(`Error fetching price for ${assetId}: ${error}`);
}

return tokenPrice;
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@
"deploy:mainnet:trade-mining:ap-token:upgrade:ap-token": "hardhat --network mainnet deploy --no-compile --reset --tags UpgradeAPToken",
"deploy:mainnet:trade-mining:paradeen": "hardhat --network mainnet deploy --no-compile --reset --tags Paradeen",
"deploy:mainnet:trade-mining:feed-paradeen": "hardhat --network mainnet deploy --no-compile --reset --tags FeedParadeen",
"deploy:mainnet:trade-mining:feed-paradeen-pyth": "hardhat --network mainnet deploy --no-compile --reset --tags FeedParadeenPyth",
"deploy:mainnet:trade-mining:set_mineable": "hardhat --network mainnet deploy --no-compile --reset --tags SetMiningManagerMinable",
"deploy:mainnet:trade-mining:set_miner_manager_auth": "hardhat --network mainnet deploy --no-compile --reset --tags SetMiningManagerAuth",
"deploy:mainnet:trade-mining:set_miner_manager_point": "hardhat --network mainnet deploy --no-compile --reset --tags SetMiningManagerPoint",
Expand Down

0 comments on commit c3d0444

Please sign in to comment.