Skip to content

Instantly share code, notes, and snippets.

@tsudmi
Last active August 29, 2025 11:08
Show Gist options
  • Select an option

  • Save tsudmi/a1e28b3a542c16c8a71859cbde8d049e to your computer and use it in GitHub Desktop.

Select an option

Save tsudmi/a1e28b3a542c16c8a71859cbde8d049e to your computer and use it in GitHub Desktop.
import {ethers} from "ethers";
const provider = new ethers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID");
const userAddress = "0x2365887bBdb7fF611F54b380573a5055170fAE7D";
const osTokenEscrow = "0x09e84205DF7c68907e619D07aFD90143c5763605";
const contractAddresses = {
leverageStratV1: "0x48cD14FDB8e72A03C8D952af081DBB127D6281fc",
leverageStratV2: "0x7575BC9E5168f27B97F9028905A2Adf91d2fF53d",
keeper: "0x6B5815467da09DaA7DC83Db21c9239d98Bb487b5",
boostHelpers: "0xdD3Cee7ECa7308f1CECf86A46A00698A5C81FD93",
};
const contractAbis = {
leverageStrat: [
{
anonymous: false,
inputs: [
{indexed: true, internalType: "address", name: "vault", type: "address"},
{indexed: true, internalType: "address", name: "user", type: "address"},
{indexed: false, internalType: "uint256", name: "osTokenShares", type: "uint256"},
{indexed: false, internalType: "uint256", name: "leverageOsTokenShares", type: "uint256"},
{indexed: false, internalType: "address", name: "referrer", type: "address"}
],
name: "Deposited",
type: "event"
},
{
inputs: [
{internalType: "address", name: "vault", type: "address"},
{internalType: "address", name: "user", type: "address"}
],
name: "getStrategyProxy",
outputs: [{internalType: "address", name: "proxy", type: "address"}],
stateMutability: "view",
type: "function"
},
{
inputs: [{internalType: "address", name: "proxy", type: "address"}],
name: "isStrategyProxyExiting",
outputs: [{internalType: "bool", name: "isExiting", type: "bool"}],
stateMutability: "view",
type: "function"
}
],
keeper: [
{
anonymous: false,
inputs: [
{indexed: true, internalType: "address", name: "caller", type: "address"},
{indexed: true, internalType: "bytes32", name: "rewardsRoot", type: "bytes32"},
{indexed: false, internalType: "uint256", name: "avgRewardPerSecond", type: "uint256"},
{indexed: false, internalType: "uint64", name: "updateTimestamp", type: "uint64"},
{indexed: false, internalType: "uint64", name: "nonce", type: "uint64"},
{indexed: false, internalType: "string", name: "rewardsIpfsHash", type: "string"}
],
name: "RewardsUpdated",
type: "event"
}
],
vault: [
{
anonymous: false,
inputs: [
{indexed: true, internalType: "address", name: "owner", type: "address"},
{indexed: true, internalType: "address", name: "receiver", type: "address"},
{indexed: false, internalType: "uint256", name: "positionTicket", type: "uint256"},
{indexed: false, internalType: "uint256", name: "shares", type: "uint256"}
],
name: "ExitQueueEntered",
type: "event"
}
],
boostHelpers: [
{
inputs: [
{internalType: "address", name: "user", type: "address"},
{internalType: "address", name: "vault", type: "address"},
{
components: [
{internalType: "bytes32", name: "rewardsRoot", type: "bytes32"},
{internalType: "int160", name: "reward", type: "int160"},
{internalType: "uint160", name: "unlockedMevReward", type: "uint160"},
{internalType: "bytes32[]", name: "proof", type: "bytes32[]"}
],
internalType: "struct IKeeperRewards.HarvestParams",
name: "harvestParams",
type: "tuple"
},
{
components: [
{internalType: "uint256", name: "positionTicket", type: "uint256"},
{internalType: "uint256", name: "timestamp", type: "uint256"}
],
internalType: "struct IBoostHelpers.ExitRequest",
name: "exitRequest",
type: "tuple"
}
],
name: "getBoostOsTokenShares",
outputs: [{internalType: "uint256", name: "", type: "uint256"}],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [{internalType: "address", name: "proxy", type: "address"}],
name: "getProxyLeverageStrategy",
outputs: [{internalType: "contract ILeverageStrategy", name: "", type: "address"}],
stateMutability: "view",
type: "function"
},
{
inputs: [
{internalType: "address", name: "vault", type: "address"},
{internalType: "address", name: "user", type: "address"}
],
name: "getStrategyProxy",
outputs: [{internalType: "address", name: "proxy", type: "address"}],
stateMutability: "view",
type: "function"
}
]
};
const contracts = {
leverageStratV1: new ethers.Contract(contractAddresses.leverageStratV1, contractAbis.leverageStrat, provider),
leverageStratV2: new ethers.Contract(contractAddresses.leverageStratV2, contractAbis.leverageStrat, provider),
keeper: new ethers.Contract(contractAddresses.keeper, contractAbis.keeper, provider),
boostHelpers: new ethers.Contract(contractAddresses.boostHelpers, contractAbis.boostHelpers, provider)
};
async function getVaultHarvestParams(vaultAddress, allRewards, rewardsRoot) {
const vault = allRewards.vaults.find(v => v.vault === vaultAddress);
return vault ? {
rewardsRoot,
reward: BigInt(vault.consensus_reward) + BigInt(vault.unlocked_mev_reward) + BigInt(vault.locked_mev_reward),
unlockedMevReward: vault.unlocked_mev_reward,
proof: vault.proof
} : {rewardsRoot: "0x", reward: "0", unlockedMevReward: "0", proof: []};
}
async function fetchDepositedVaults() {
const eventsV1 = await contracts.leverageStratV1.queryFilter(
contracts.leverageStratV1.filters.Deposited(null, userAddress), 21288813, "latest"
);
const eventsV2 = await contracts.leverageStratV2.queryFilter(
contracts.leverageStratV2.filters.Deposited(null, userAddress), 23242393, "latest"
);
return [...new Set(eventsV1.concat(eventsV2).map(event => event.args.vault))];
}
async function getLastRewards() {
const events = await contracts.keeper.queryFilter(contracts.keeper.filters.RewardsUpdated(), 0, "latest");
if (!events.length) return [null, null];
const lastEvent = events.pop();
const jsonText = await fetch("https://ipfs.io/ipfs/" + lastEvent.args.rewardsIpfsHash).then(res => res.text());
return [lastEvent.args.rewardsRoot, JSON.parse(jsonText.replace(/(\d{16,})/g, '"$1"'))];
}
async function getLastVaultExitRequest(vaultAddress, proxy, leverageStrategyAddress) {
const leverageStrat = new ethers.Contract(leverageStrategyAddress, contractAbis.leverageStrat, provider);
if (!(await leverageStrat.isStrategyProxyExiting(proxy))) {
return {positionTicket: 0, timestamp: 0};
}
const vault = new ethers.Contract(vaultAddress, contractAbis.vault, provider);
const events = await vault.queryFilter(vault.filters.ExitQueueEntered(proxy, osTokenEscrow));
if (!events.length) throw new Error("No exit request found");
const lastEvent = events.pop();
return {
positionTicket: lastEvent.args.positionTicket,
timestamp: (await provider.getBlock(lastEvent.blockNumber)).timestamp
};
}
async function main() {
const vaults = await fetchDepositedVaults();
if (!vaults.length) return;
const [rewardsRoot, allRewards] = await getLastRewards();
for (const vaultAddress of vaults) {
const proxy = await contracts.boostHelpers.getStrategyProxy(vaultAddress, userAddress);
const leverageStrategyAddress = await contracts.boostHelpers.getProxyLeverageStrategy(proxy);
const vaultHarvestParams = await getVaultHarvestParams(vaultAddress, allRewards, rewardsRoot);
const exitRequest = await getLastVaultExitRequest(vaultAddress, proxy, leverageStrategyAddress);
const boostOsTokenShares = await contracts.boostHelpers.getBoostOsTokenShares.staticCall(userAddress, vaultAddress, vaultHarvestParams, exitRequest);
console.log(`Vault: ${vaultAddress}, User: ${userAddress} Boost Shares: ${ethers.formatEther(boostOsTokenShares)}`);
}
}
main().catch(console.error);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment