-
Notifications
You must be signed in to change notification settings - Fork 809
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
[erc721-with-landtype-multiplier] Add strategy erc721-with-landtype-multiplier #1529
Open
monish-nagre
wants to merge
9
commits into
snapshot-labs:master
Choose a base branch
from
monish-nagre:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
984ebed
Add strategy erc721-with-landtype-multiplier
monish-nagre de5aa0d
edit changes for test
monish-nagre 0130ff1
erc721-with-landtype-multiplier
monish-nagre 0110383
erc721-with-landtype-multiplier
monish-nagre 322d7ca
Merge branch 'master' into master
ChaituVR d14e6df
Merge branch 'master' into master
ChaituVR a74f3fb
erc721-with-landtype-multiplier
monish-nagre 808e56b
Merge remote-tracking branch 'origin/master'
monish-nagre 7ca5b0f
Merge branch 'master' into master
ChaituVR File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# ERC721 with Multiplier Landtype Strategy | ||
|
||
This strategy returns the balances of the voters for a specific ERC721 NFT with an arbitrary multiplier based on the type of land they own. | ||
Types Of Land : | ||
Mega contributes 25000 VP | ||
Large contributes 10000 VP | ||
Medium contributes 4000 VP | ||
Unit contributes 2000 VP | ||
|
||
## Parameters | ||
|
||
- **address**: The address of the ERC721 contract. | ||
- **multiplier**: The multiplier to be applied to the balance. | ||
- **symbol**: The symbol of the ERC721 token. | ||
|
||
Here is an example of parameters: | ||
|
||
```json | ||
{ | ||
"address": "0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB", | ||
"symbol": "LAND" | ||
} | ||
``` |
19 changes: 19 additions & 0 deletions
19
src/strategies/erc721-with-landtype-multiplier/examples.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
[ | ||
{ | ||
"name": "Example query", | ||
"strategy": { | ||
"name": "erc721-with-landtype-multiplier", | ||
"params": { | ||
"address": "0xdBd34637BC7793DDC2A02A89b3E6592249a45a12", | ||
"symbol": "LAND" | ||
} | ||
}, | ||
"network": "137", | ||
"addresses": [ | ||
"0xf3597bc963b657203177e59184d5a3b93d465c94", | ||
"0xa2fe5ff21c1e634723f5847cc61033a929e1dcfc", | ||
"0x9069fdde8df22aab332b326d34c7c376c62d0076" | ||
], | ||
"snapshot": 12453212 | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { multicall } from '../../utils'; | ||
import { BigNumber } from '@ethersproject/bignumber'; | ||
|
||
export const author = 'monish-nagre'; | ||
export const version = '0.1.0'; | ||
|
||
const abi = [ | ||
'function balanceOf(address owner) public view returns (uint256)', | ||
'function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256)', | ||
'function landData(uint256 tokenId) public view returns (uint256 landId, string landType, string x, string y, string z)' | ||
]; | ||
|
||
// Voting power based on land type | ||
const landTypeVotingPower: { [key: string]: number } = { | ||
'Mega': 25000, | ||
'Large': 10000, | ||
'Medium': 4000, | ||
'Unit': 2000 | ||
}; | ||
|
||
export async function strategy( | ||
space: string, | ||
network: string, | ||
provider: any, | ||
addresses: string[], | ||
options: any, | ||
snapshot: number | string | ||
): Promise<{ [address: string]: number }> { | ||
const blockTag = typeof snapshot === 'number' ? snapshot : 'latest'; | ||
|
||
try { | ||
// Step 1: Get the balance of each address | ||
const balanceCalls = addresses.map((address: string) => [options.address, 'balanceOf', [address]]); | ||
const balanceResponse = await multicall(network, provider, abi, balanceCalls, { blockTag }); | ||
|
||
// Check if balanceResponse is an array and has valid data | ||
if (!Array.isArray(balanceResponse) || balanceResponse.length !== addresses.length) { | ||
throw new Error('Balance response is not valid'); | ||
} | ||
|
||
// Parse balance response | ||
const balances = balanceResponse.map((response: any) => BigNumber.from(response[0]).toNumber()); | ||
console.log('Balance response:', balances); | ||
|
||
// Step 2: Get all token IDs for each address | ||
const tokenCalls: [string, string, [string, number]][] = []; | ||
addresses.forEach((address: string, i: number) => { | ||
const balance = balances[i]; | ||
for (let j = 0; j < balance; j++) { | ||
tokenCalls.push([options.address, 'tokenOfOwnerByIndex', [address, j]]); | ||
} | ||
}); | ||
|
||
if (tokenCalls.length === 0) { | ||
return {}; | ||
} | ||
|
||
const tokenResponse = await multicall(network, provider, abi, tokenCalls, { blockTag }); | ||
|
||
// Check if tokenResponse is an array and has valid data | ||
if (!Array.isArray(tokenResponse)) { | ||
throw new Error('Token response is not an array'); | ||
} | ||
|
||
// Parse token response | ||
const tokenIds = tokenResponse.map((response: any) => BigNumber.from(response[0]).toString()); | ||
console.log('Token response:', tokenIds); | ||
ChaituVR marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Step 3: Get land type for each token ID | ||
const landDataCalls: [string, string, [BigNumber]][] = tokenIds.map((tokenId: string) => [options.address, 'landData', [BigNumber.from(tokenId)]]); | ||
const landDataResponse = await multicall(network, provider, abi, landDataCalls, { blockTag }); | ||
|
||
// Check if landDataResponse is an array and has valid data | ||
if (!Array.isArray(landDataResponse) || landDataResponse.length !== tokenIds.length) { | ||
throw new Error('Land data response is not valid'); | ||
} | ||
|
||
// Step 4: Calculate voting power based on land type | ||
const votingPower: { [address: string]: number } = {}; | ||
let tokenIndex = 0; | ||
addresses.forEach((address: string, i: number) => { | ||
votingPower[address] = 0; | ||
const balance = balances[i]; | ||
for (let j = 0; j < balance; j++) { | ||
const landType = landDataResponse[tokenIndex].landType; | ||
votingPower[address] += landTypeVotingPower[landType] || 0; | ||
tokenIndex++; | ||
} | ||
}); | ||
|
||
console.log('Voting power:', votingPower); | ||
ChaituVR marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return votingPower; | ||
} catch (error) { | ||
return {}; | ||
} | ||
ChaituVR marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if my balance is in millions, we will send million calls to this multicall? 😄 is there some other way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My current maximum supply of ERC721 tokens is 5000 and the balance is unlikely to be high due to the expensive nature of the lands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should throw some error if it crosses a certain number, else it may eat all memory, or if there is way to get total supply of the tokens, and if it goes beyond a certain number we can make this strategy to stop working
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for suppport ...
add abi : [ 'function totalSupply() external view returns (uint256)' ]
const MAX_SUPPLY_THRESHOLD = totalSupply; // Set max supply threshold dynamically
// Check if the number of calls exceeds the maximum threshold
if (tokenCalls.length > MAX_SUPPLY_THRESHOLD) {
throw new Error(
Number of token calls (${tokenCalls.length}) exceeds the maximum threshold (${MAX_SUPPLY_THRESHOLD})
);}
may i add these changes , it's okay ? i mean is satisfied for strategy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should set a static MAX_SUPPLY_THRESHOLD, also this may allow few users and block few users 😅
I think it would be better if we could:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I Understood ,
sorry for above response : ( My current maximum supply of ERC721 tokens is 5000 and the balance is unlikely to be high due to the expensive nature of the lands. ) its not my current supply , is my max limit that the land mint i.e 5000.
In my contract , the maximum LAND MINTING supply is 5000, and currently we sell (land-count) is 150 .
Soo we should set the MAX_SUPPLY_THRESHOLD to 5000.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
works
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for reply ...
soo now , should i push the updated code ?
when i remove the try catch , my testcase runs now :
Test strategy "erc721-with-landtype-multiplier" with example index 0
✓ Strategy name should be lowercase and should not contain any special char expect hyphen (1 ms)
✓ Strategy name should be same as in examples.json (1 ms)
✓ Addresses in example should be minimum 3 and maximum 20
✓ Must use a snapshot block number in the past (5979 ms)
✕ Strategy should run without any errors (916 ms)
✕ Should return an array of object with addresses (1 ms)
✕ Should take less than 10 sec. to resolve
✕ File examples.json should include at least 1 address with a positive score
✕ Returned addresses should be checksum addresses
✕ Voting power should not depend on other addresses (410 ms)
Test strategy "erc721-with-landtype-multiplier" with example index 0 (latest snapshot)
✓ Strategy should run without any errors (2155 ms)
✓ Should return an array of object with addresses (3 ms)
Test strategy "erc721-with-landtype-multiplier" with example index 0 (with 500 addresses)
○ skipped Should work with 500 addresses
○ skipped Should take less than 20 sec. to resolve with 500 addresses
Other tests with example index 0
○ skipped Check schema (if available) is valid with examples.json
○ skipped Check schema (if available) all arrays in all levels should contain
items
property○ skipped Strategy should work even when strategy symbol is null
Others:
✓ Author in strategy should be a valid github username (331 ms)
✓ Version in strategy should be a valid string (1 ms)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes please
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for support ... @ChaituVR
Yes i pushed the updated code now .