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

feat(SpellStaking): Add support for Blast and Kava #16

Merged
merged 1 commit into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
| MagicGlp Arbitrum | [task](https://app.gelato.network/functions/task/0x46cdddc42edb01fb462cb22efd2578d22351629689b00434531df2e254665279:42161) |
| MagicGlp Avalanche | [task](https://app.gelato.network/functions/task/0x36ee967b80c68152c0af1c69d49ff60f0eb41264f3cebc4dcc8b16843c7038be:43114) |
| SpellSwapper | [task](https://app.gelato.network/functions/task/0x9d6f1f55569bf50b6273f4e1b6a75fc64d8cd906d7c401d501f207f19120e3a0:1) |
| SpellStaking Blast | [task](https://app.gelato.network/functions/task/0xd6b36b19af229cc7291882eac23c45741ef962d1f58d9c5b37ef4ff6a5cf12ce:81457) |
| Velodrome vOP/USDC | [task](https://app.gelato.network/functions/task/0x1593a557fbbccc9b8c41f175b059eac993a508e9c104036a1bb93f23b1e5d1e1:10) |
| WBTC InterestStrategy | [task](https://app.gelato.network/functions/task/0xdbf9b9d3f40c0c5a44fed95d0d8b1a7ec70882f56e5c3f64a67b4963ca144775:1) |
| WETH InterestStrategy | [task](https://app.gelato.network/functions/task/0x49b5af6155b652aa036b3cf22f798f14384aa4b124cb9780ac3141389b00e311:1) |
Expand Down
6 changes: 6 additions & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const config = {
"ethereum",
"avalanche",
"arbitrum",
"blast",
"fantom",
"optimism",
"polygon",
Expand Down Expand Up @@ -49,6 +50,11 @@ const config = {
url: "https://arb1.arbitrum.io/rpc",
accounts: [PRIVATE_KEY],
},
blast: {
chainId: 81457,
url: "https://rpc.ankr.com/blast ",
accounts: [PRIVATE_KEY],
},
fantom: {
chainId: 250,
url: "https://rpc2.fantom.network",
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
"url": "https://github.com/Abracadabra-money/web3-functions",
"private": false,
"scripts": {
"build": "bun run clean && bun run install && npx tsc",
"build": "bun run clean && bun run install && tsc",
"clean": "rm -rf dist",
"typecheck": "tsc --noEmit",
"lint": "biome check",
"lint:fix": "biome check --write",
"lint:ci": "biome ci",
"run-task": "concurrently -m 1 \"bun:run-task:*(!run-task:[^:]+:)\"",
"create-task:gm": "hardhat run ./scripts/create-gm-task.ts --network ethereum",
"create-task:spell-staking": "killall -9 anvil; hardhat run ./scripts/create-spell-staking-task.ts --network anvil",
"create-task:spell-staking": "hardhat run ./scripts/create-spell-staking-task.ts",
"create-task:magiclvl": "hardhat run ./scripts/create-magiclvl-task.ts --network anvil",
"create-task:process-locks": "hardhat run ./scripts/create-process-locks-task.ts --network arbitrum",
"create-task:spell-swapper": "hardhat run ./scripts/create-spell-swapper-task.ts --network ethereum",
Expand All @@ -30,7 +30,9 @@
"run-task:spell-staking:mainnet": "hardhat w3f-run spell-staking --logs --network ethereum",
"run-task:spell-staking:avalanche": "hardhat w3f-run spell-staking --logs --network avalanche",
"run-task:spell-staking:arbitrum": "hardhat w3f-run spell-staking --logs --network arbitrum",
"run-task:spell-staking:blast": "hardhat w3f-run spell-staking --logs --network blast",
"run-task:spell-staking:fantom": "hardhat w3f-run spell-staking --logs --network fantom",
"run-task:spell-staking:kava": "hardhat w3f-run spell-staking --logs --network kava",
"run-task:gm": "hardhat w3f-run gm --logs --network arbitrum",
"run-task:magiclvl": "hardhat w3f-run magiclvl --logs --network bsc",
"run-task:process-locks": "concurrently --kill-others-on-fail -m 1 bun:run-task:process-locks:*",
Expand Down
2 changes: 1 addition & 1 deletion scripts/create-spell-staking-task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const main = async () => {
console.log();
}

const ALTCHAIN_IDS = [250, 43114, 42161];
const ALTCHAIN_IDS = [250, 43114, 42161, 81457] as const;

for (const chainId of ALTCHAIN_IDS) {
console.log(`Creating ChainId ${chainId} Task`);
Expand Down
2 changes: 2 additions & 0 deletions utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export const ARBITRUM_SPELL =
"0x3e6648c5a70a150a88bce65f4ad4d506fe15d2af" as const satisfies Address;
export const ARBITRUM_OPS_SAFE =
"0xA71A021EF66B03E45E0d85590432DFCfa1b7174C" as const satisfies Address;
export const GELATO_PROXY =
"0x4D0c7842cD6a04f8EDB39883Db7817160DA159C3" as const satisfies Address;
131 changes: 80 additions & 51 deletions web3-functions/spell-staking/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
type Web3FunctionContext,
} from "@gelatonetwork/web3-functions-sdk";
import { BigNumber, Contract, utils } from "ethers";
import { GELATO_PROXY } from "../../utils/constants";
import { LZ_CHAIN_IDS } from "../../utils/lz";
import { SimulationUrlBuilder } from "../../utils/tenderly";

Expand Down Expand Up @@ -38,8 +39,10 @@ const MSPELL_STAKING_ADDRESSES: { [chainId: number]: string } = {
const MIM_ADDRESSES: { [chainId: number]: string } = {
1: "0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3", // Ethereum
250: "0x82f0B8B456c1A451378467398982d4834b6829c1", // Fantom
2222: "0x471EE749bA270eb4c1165B5AD95E614947f6fCeb", // Kava
43114: "0x130966628846BFd36ff31a822705796e8cb8C18D", // Avalanche
42161: "0xFEa7a6a0B346362BF88A9e4A88416B77a57D6c2A", // Arbitrum
81457: "0x76DA31D7C9CbEAE102aff34D3398bC450c8374c1", // Blast
};
const SPELL_ADDRESSES: { [chainId: number]: string } = {
1: "0x090185f2135308BaD17527004364eBcC2D37e5F6", // Ethereum
Expand All @@ -48,8 +51,13 @@ const SPELL_ADDRESSES: { [chainId: number]: string } = {
42161: "0x3E6648C5a70A150A88bCE65F4aD4d506Fe15d2AF", // Arbitrum
};

const WITHDRAWER_ADDRESS_LEGACY =
"0x2C9f65BD1a501CB406584F5532cE57c28829B131" as const;
const WITHDRAWER_ADDRESS_LATEST =
"0x22d0e6A4e9b658184248f5e0BF89A0D763849544" as const;

const MAINNET_ADDRESSES = {
withdrawer: "0x2C9f65BD1a501CB406584F5532cE57c28829B131",
withdrawer: WITHDRAWER_ADDRESS_LEGACY,
distributor: "0x953DAb0e64828972853E7faA45634620A40Fa479",
sSpell: "0x26FA3fFFB6EfE8c1E69103aCb4044C26B9A106a9",
treasury: "0xDF2C270f610Dc35d8fFDA5B453E74db5471E126B",
Expand Down Expand Up @@ -80,20 +88,25 @@ Web3Function.onRun(async (context: Web3FunctionContext) => {
const WITHDRAWER_INTERFACE = new utils.Interface(WITHDRAWER_ABI);
const DISTRIBUTOR_INTERFACE = new utils.Interface(DISTRIBUTOR_ABI);

// same address on all chains
const WITHDRAWER_ADDRESS = "0x2C9f65BD1a501CB406584F5532cE57c28829B131";
const ALTCHAIN_IDS = [250, 2222, 43114, 42161, 81457] as const;
const CHAIN_IDS = [1, ...ALTCHAIN_IDS] as const;

// supported chains
const ALTCHAIN_IDS = [250, 43114, 42161];
const CHAIN_IDS = [1, ...ALTCHAIN_IDS];
const WITHDRAWER_ADDRESS = {
1: WITHDRAWER_ADDRESS_LEGACY,
250: WITHDRAWER_ADDRESS_LEGACY,
2222: WITHDRAWER_ADDRESS_LATEST,
42161: WITHDRAWER_ADDRESS_LEGACY,
43114: WITHDRAWER_ADDRESS_LEGACY,
81457: WITHDRAWER_ADDRESS_LATEST,
} as const satisfies Record<(typeof CHAIN_IDS)[number], string>;

/////////////////////////////////////////////////
// Initialization
/////////////////////////////////////////////////
const info: {
[chainId: number]: {
withdrawer: Contract;
spell: Contract;
spell: Contract | undefined;
mSpellStakedAmount: BigNumber;
sSpellStakedAmount: BigNumber;
};
Expand All @@ -103,8 +116,15 @@ Web3Function.onRun(async (context: Web3FunctionContext) => {
const provider = multiChainProvider.chainId(chainId);

info[chainId] = {
withdrawer: new Contract(WITHDRAWER_ADDRESS, WITHDRAWER_ABI, provider),
spell: new Contract(SPELL_ADDRESSES[chainId], IERC20_ABI, provider),
withdrawer: new Contract(
WITHDRAWER_ADDRESS[chainId],
WITHDRAWER_ABI,
provider,
),
spell:
SPELL_ADDRESSES[chainId] !== undefined
? new Contract(SPELL_ADDRESSES[chainId], IERC20_ABI, provider)
: undefined,
mSpellStakedAmount: BigNumber.from(0),
sSpellStakedAmount: BigNumber.from(0),
};
Expand Down Expand Up @@ -158,24 +178,27 @@ Web3Function.onRun(async (context: Web3FunctionContext) => {
// Fetch staked amounts
await Promise.all(
CHAIN_IDS.map(async (chainId) => {
// mSPELL staked amount
info[chainId].mSpellStakedAmount = await info[chainId].spell.balanceOf(
MSPELL_STAKING_ADDRESSES[chainId],
);

// sSPELL staked amount (mainnet only)
if (chainId === MAINNET_CHAIN_ID) {
info[chainId].sSpellStakedAmount = await info[
chainId
].spell.balanceOf(MAINNET_ADDRESSES.sSpell);
const spellContract = info[chainId].spell;
if (spellContract !== undefined) {
// mSPELL staked amount
info[chainId].mSpellStakedAmount = await spellContract.balanceOf(
MSPELL_STAKING_ADDRESSES[chainId],
);

// sSPELL staked amount (mainnet only)
if (chainId === MAINNET_CHAIN_ID) {
info[chainId].sSpellStakedAmount = await spellContract.balanceOf(
MAINNET_ADDRESSES.sSpell,
);
totalSpellStaked = totalSpellStaked.add(
info[chainId].sSpellStakedAmount,
);
}

totalSpellStaked = totalSpellStaked.add(
info[chainId].sSpellStakedAmount,
info[chainId].mSpellStakedAmount,
);
}

totalSpellStaked = totalSpellStaked.add(
info[chainId].mSpellStakedAmount,
);
}),
);

Expand Down Expand Up @@ -223,30 +246,32 @@ Web3Function.onRun(async (context: Web3FunctionContext) => {
});

// AltChain allocations
for (const chainId in ALTCHAIN_IDS) {
const amountToBridge = mimBalanceInDistributor
.mul(info[ALTCHAIN_IDS[chainId]].mSpellStakedAmount)
.div(totalSpellStaked);

// Estimate bridging fee
const { fee, gas } = await distributorMainnet.estimateBridgingFee(
amountToBridge.toString(),
LZ_CHAIN_IDS[ALTCHAIN_IDS[chainId]],
MSPELL_STAKING_ADDRESSES[ALTCHAIN_IDS[chainId]],
); // use default minDstGasLookup

distributions.push({
recipient: MSPELL_STAKING_ADDRESSES[ALTCHAIN_IDS[chainId]],
gas: gas.toString(),
lzChainId: LZ_CHAIN_IDS[ALTCHAIN_IDS[chainId]].toString(),
fee: fee.toString(),
amount: amountToBridge.toString(),
});
for (const chainId of ALTCHAIN_IDS) {
if (info[chainId].spell !== undefined) {
const amountToBridge = mimBalanceInDistributor
.mul(info[chainId].mSpellStakedAmount)
.div(totalSpellStaked);

// Estimate bridging fee
const { fee, gas } = await distributorMainnet.estimateBridgingFee(
amountToBridge.toString(),
LZ_CHAIN_IDS[chainId],
MSPELL_STAKING_ADDRESSES[chainId],
); // use default minDstGasLookup

distributions.push({
recipient: MSPELL_STAKING_ADDRESSES[chainId],
gas: gas.toString(),
lzChainId: LZ_CHAIN_IDS[chainId].toString(),
fee: fee.toString(),
amount: amountToBridge.toString(),
});
}
}

// withdraw
callData.push({
to: WITHDRAWER_ADDRESS,
to: MAINNET_ADDRESSES.withdrawer,
data: WITHDRAWER_INTERFACE.encodeFunctionData("withdraw", []),
});

Expand All @@ -273,13 +298,17 @@ Web3Function.onRun(async (context: Web3FunctionContext) => {

// withdraw
callData.push({
to: WITHDRAWER_ADDRESS,
to: WITHDRAWER_ADDRESS[
gelatoArgs.chainId as keyof typeof WITHDRAWER_ADDRESS
],
data: WITHDRAWER_INTERFACE.encodeFunctionData("withdraw", []),
});

// bridge
callData.push({
to: WITHDRAWER_ADDRESS,
to: WITHDRAWER_ADDRESS[
gelatoArgs.chainId as keyof typeof WITHDRAWER_ADDRESS
],
data: WITHDRAWER_INTERFACE.encodeFunctionData("bridge", [
mimBalanceInDistributor,
fee,
Expand Down Expand Up @@ -318,11 +347,11 @@ Web3Function.onRun(async (context: Web3FunctionContext) => {
await storage.set("lastRun", timestamp.toString());

SimulationUrlBuilder.log(
[WITHDRAWER_ADDRESS],
[callData[0].to],
[0],
[callData[0].data],
[gelatoArgs.chainId],
callData.map(() => GELATO_PROXY),
callData.map(({ to }) => to),
callData.map(() => 0),
callData.map(({ data }) => data),
callData.map(() => gelatoArgs.chainId),
);

return {
Expand Down