Skip to content
This repository was archived by the owner on Aug 22, 2025. It is now read-only.
Merged
13 changes: 13 additions & 0 deletions src/strategies/forte-staking/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# forte-staking

This strategy is for staking $FOR tokes. Voting power is calculated by taking into account the access level and time of staking.

Here is an example of parameters:

```json
{
"symbol": "FOR",
"stakingAddress": "0x6b175474e89094c44da98b954eedeac495271d0f",
"kycAddress": "0x86f53212865b6fddb99633dc002a7f7aacaaa8db"
}
```
23 changes: 23 additions & 0 deletions src/strategies/forte-staking/examples.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[
{
"name": "Example query",
"strategy": {
"name": "forte-staking",
"params": {
"stakingAddress": "0x249E662fe228Eff1e7dCE7cF3E78dFD481C7Ba3E",
"kycAddress": "0x86f53212865b6fddb99633dc002a7f7aacaaa8db",
"symbol": "FORTE"
}
},
"network": "11155111",
"addresses": [
"0xe5405Dabe7d24F044941cEE4eA73a194659D7bD4",
"0x9Fb190F6Da7cdDd939bB4f661c134051ecf6A8B5",
"0x12363F899a1b2039a2A5a1A717be896AFA446382",
"0xE3D777106b622474a2974839061D652a7Af3C989",
"0x9B42F52E69C9bA94991A7D7e7aF73b2340a43216",
"0xd99675E7583e73E8DDC6bdbcbff5321983232763"
],
"snapshot": 8541444
}
]
74 changes: 74 additions & 0 deletions src/strategies/forte-staking/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { BigNumber } from '@ethersproject/bignumber';
import { Multicaller } from '../../utils';
import { formatUnits } from '@ethersproject/units';

export const author = 'forte';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be a github related to forte 😅 it will help identify you if you want to update this strategy in future

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😅 ok I wasn't aware this had the purpose of giving update privileges. I changed it to my GH user

export const version = '0.0.1';

type batch = [stakeAmount: BigNumber, timeStamp: BigNumber];
const stakeAmount = 0; // index of the stake amount in the batch tuple
const timeStamp = 1; // index of the timestamp in the batch tuple

const abiStaking = [
'function getStakedBatches(address _user) external view returns ((uint256, uint256)[] memory)'
];

const abiKYC = [
'function getAccessLevel(address _account) external view returns (uint8)'
];

export async function strategy(
space,
network,
provider,
addresses,
options,
snapshot
): Promise<Record<string, number>> {
const blockTag = typeof snapshot === 'number' ? snapshot : 'latest';

// getting the staked batches
const stakeCall = new Multicaller(network, provider, abiStaking, {
blockTag
});
addresses.forEach((address) =>
stakeCall.call(address, options.stakingAddress, 'getStakedBatches', [
address
])
);
const stakeResult: Record<string, batch[]> = await stakeCall.execute();

// getting the KYC level
const kycCall = new Multicaller(network, provider, abiKYC, {
blockTag
});
addresses.forEach((address) =>
kycCall.call(address, options.kycAddress, 'getAccessLevel', [address])
);
const kycResult: Record<string, number> = await kycCall.execute();

// return voting power
return Object.fromEntries(
Object.entries(stakeResult).map(([address, rawBatches]) => [
address,
calculateVotingPower(rawBatches, kycResult[address])
])
);
}

function calculateVotingPower(rawBatches: batch[], kycLevel: number): number {
let votingPower: bigint = 0n;
rawBatches.forEach((batch) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This forEach could be replaced with reduce and ``votingPowerbeing replaced withaccumulator` so line 61 would be `rawBatches.reduce((acc, batch) => {` and the return value would be `return acc + (stake * BigInt(4 * (daysStaked > 1 ? daysStaked - 1 : 0))) / 1461n;`

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great suggestion. Implemented.

console.log('batch', batch);
const today: number = +new Date();
const stakeDate: number = +new Date(Number(batch[timeStamp]._hex) * 1000); // * 1000 to convert to ms
const daysStaked: number = Math.floor(
(today - stakeDate) / (60 * 60 * 24 * 1000) // (...) / (1 day in ms)
);
const stake: bigint = BigInt(batch[stakeAmount]._hex);
votingPower +=
(stake * BigInt(4 * (daysStaked > 1 ? daysStaked - 1 : 0))) / 1461n;
});
votingPower = votingPower * BigInt(kycLevel > 2 ? 2 : kycLevel);
return parseFloat(formatUnits(votingPower));
}
36 changes: 36 additions & 0 deletions src/strategies/forte-staking/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/Strategy",
"definitions": {
"Strategy": {
"title": "Strategy",
"type": "object",
"properties": {
"symbol": {
"type": "string",
"title": "Symbol",
"examples": ["e.g. FOR"],
"maxLength": 16
},
"stakingAddress": {
"type": "string",
"title": "Contract address",
"examples": ["e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"],
"pattern": "^0x[a-fA-F0-9]{40}$",
"minLength": 42,
"maxLength": 42
},
"kycAddress": {
"type": "string",
"title": "Contract address",
"examples": ["e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"],
"pattern": "^0x[a-fA-F0-9]{40}$",
"minLength": 42,
"maxLength": 42
}
},
"required": ["stakingAddress", "kycAddress"],
"additionalProperties": false
}
}
}
4 changes: 3 additions & 1 deletion src/strategies/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ import * as shroomyVotingPower from './shroomy-voting-power';
import * as pufferGetPastVotes from './puffer-getpastvotes';
import * as prlInSpRL2Balance from './prl-in-sprl2-balance';
import * as edenOnlineOverride from './eden-online-override';
import * as forteStaking from './forte-staking';

const strategies = {
'shroomy-voting-power': shroomyVotingPower,
Expand Down Expand Up @@ -981,7 +982,8 @@ const strategies = {
'dappcomposer-getvotingunits': dappcomposerGetVotingUnits,
'puffer-getpastvotes': pufferGetPastVotes,
'prl-in-sprl2-balance': prlInSpRL2Balance,
'eden-online-override': edenOnlineOverride
'eden-online-override': edenOnlineOverride,
'forte-staking': forteStaking
};

Object.keys(strategies).forEach(function (strategyName) {
Expand Down