Skip to content

Commit

Permalink
[bubblegum-kids] add bubblegum-kids strategy (snapshot-labs#1351)
Browse files Browse the repository at this point in the history
* add bubblegum-kids strategy

* add more test ids + comments

* rm unnecessary schema

* tweak comment
  • Loading branch information
flaflafla authored Nov 18, 2023
1 parent 52d6e60 commit 5c8be90
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/strategies/bubblegum-kids/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# bubblegum-kids

This strategy determines voting power based on an address' holdings of Bubblegum Kids and Bubblegum Puppies NFTs, including staked NFTs.
22 changes: 22 additions & 0 deletions src/strategies/bubblegum-kids/examples.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[
{
"name": "Example query",
"strategy": {
"name": "bubblegum-kids"
},
"network": "1",
"addresses": [
"0xfec4465b6aeac9c90e552ae7766bdc0ee0d8dbc9",
"0x146860d31ab0f6dc858106f1a5d7a52bd6c86d1d",
"0x8edc7272a444057d1556df2a1173e6799c3c5ae0",
"0x8af2bd409ea0290029c14aac5d1be77d5c9a114f",
"0x41636ddf4abb1aa78863101626acdc861d4e8a0b",
"0xd341108b067cd308cf8cc7e13fb9982b0cba2f4e",
"0xdf05770b388ee62362917bea9dc96f0dee3b246e",
"0xf98e849c4b0de9750630f1c23c1bea9e79b4edb3",
"0xf68b74b89093315c5bf018348886c9fdd8308d7f",
"0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5"
],
"snapshot": 18589032
}
]
98 changes: 98 additions & 0 deletions src/strategies/bubblegum-kids/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { getAddress } from '@ethersproject/address';
import { BigNumberish } from '@ethersproject/bignumber';
import { formatUnits } from '@ethersproject/units';
import { Multicaller } from '../../utils';

export const author = 'flaflafla';
export const version = '0.1.1';

// contracts available on Ethereum mainnet and Goerli testnet
const kidsAddressByNetwork = {
1: '0xa5ae87B40076745895BB7387011ca8DE5fde37E0',
5: '0x66B04973b83ea796960D6f8ea22856714e01765f'
};

const puppiesAddressByNetwork = {
1: '0x86e9C5ad3D4b5519DA2D2C19F5c71bAa5Ef40933',
5: '0x053A3213E75b78c0b80b2f88e243cf519e834c02'
};

const stakingAddressByNetwork = {
1: '0xf48415039913DBdF17e337e681de922A9cb04010',
5: '0xe5f1433b6eCc6bE74E413b54f4c1eA2671b1cA0F'
};

const abi = [
// Kids and Puppies contracts
'function balanceOf(address owner) external view returns (uint256)',
// staking contract
'function depositsOf(address account) external view returns (uint256[][2])'
];

/**
* Voting power is calculated as the sum of a user's Bubblegum Kids
* and Bubblegum Puppies holdings, with each NFT counting as 1. Kids
* and Puppies deposited to the staking contract also count as 1.
*/
export async function strategy(
_space,
network,
provider,
addresses,
_options,
snapshot
): Promise<Record<string, number>> {
const blockTag = typeof snapshot === 'number' ? snapshot : 'latest';

const multi = new Multicaller(network, provider, abi, { blockTag });

addresses.forEach((address) => {
// get Kids balance
multi.call(`${address}.kids`, kidsAddressByNetwork[network], 'balanceOf', [
address
]);

// get Puppies balance
multi.call(
`${address}.puppies`,
puppiesAddressByNetwork[network],
'balanceOf',
[address]
);

// get staking deposits (returns and array of two arrays:
// a list of Kids ids and a list of Puppies ids)
multi.call(
`${address}.staking`,
stakingAddressByNetwork[network],
'depositsOf',
[address]
);
});

const result: {
address: {
kids: BigNumberish;
puppies: BigNumberish;
staking: [Array<BigNumberish>, Array<BigNumberish>];
};
} = await multi.execute();

return Object.fromEntries(
Object.entries(result).map(([address, { kids, puppies, staking }]) => {
const [stakedKids, stakedPuppies] = staking;

const kidsCount = parseFloat(formatUnits(kids, 0));
const stakedKidsCount = stakedKids.length;

const puppiesCount = parseFloat(formatUnits(puppies, 0));
const stakedPuppiesCount = stakedPuppies.length;

// calculate total voting power
const votingPower =
kidsCount + stakedKidsCount + puppiesCount + stakedPuppiesCount;

return [getAddress(address), votingPower];
})
);
}
4 changes: 3 additions & 1 deletion src/strategies/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ import * as mangroveStationQVScaledToMGV from './mangrove-station-qv-scaled-to-m
import * as floki from './floki';
import * as hatsProtocolHatId from './hats-protocol-hat-id';
import * as hatsProtocolHatIds from './hats-protocol-hat-ids';
import * as bubblegumKids from './bubblegum-kids';

const strategies = {
'cap-voting-power': capVotingPower,
Expand Down Expand Up @@ -956,7 +957,8 @@ const strategies = {
'mangrove-station-qv-scaled-to-mgv': mangroveStationQVScaledToMGV,
floki,
'hats-protocol-hat-id': hatsProtocolHatId,
'hats-protocol-hat-ids': hatsProtocolHatIds
'hats-protocol-hat-ids': hatsProtocolHatIds,
'bubblegum-kids': bubblegumKids,

Check failure on line 961 in src/strategies/index.ts

View workflow job for this annotation

GitHub Actions / lint / Lint

Delete `,`
};

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

0 comments on commit 5c8be90

Please sign in to comment.