Skip to content

Commit

Permalink
feat: return ABI in nft-claimer payload (#101)
Browse files Browse the repository at this point in the history
* fix: update mint signature validation

* fix: update domain name

* chore: add nftClainer tests

* chore: add more test

* refactor: rename sign methods + improve tests

* chore: skip yet untestable test

* fix: fix overflow error on BigNumber

* fix: only use test domain

* chore: update test

* Update .env.test

* Update test/.env.test

* chore: remove unused dependencies

* chore: remove unused dependencies

* fix: fix missing test env values

* fix: update NFT Claimer deploy signer

* fix: update signer

* fix: update nft claimer deploy signature generation + refactoring

* fix: remove unused import

* chore: fix tests

* fix: update deploy code for updated smart contract

* fix: fix nft claimer deploy signature

* fix: fix nftClaimer deploy signature

* chore: fix tests

* fix: remove unused env variable

* fix: fix test for new deploy smart contract

* fix: return also all params required for the tx

* fix: add new proposer param to mint signature

* fix: fix nft claimer mint signature generator

* feat: retrieve mint contract address from subgraphj

* fix: bump nft claimer subgraph version

* fix: bump subgraph version

* fix: update nft claimer subgraph url

* feat: add support for base58 proposal ID

* feat: sign message only if space has enabled minting

* chore: fix tests

* chore: fix tests

* fix: return salt in deploy payload

* fix: use number salt

* fix: add support for both IPFS version for proposal ID

* chore: fix merge conflict

* chore: update README

* fix: fix deploy signature

* fix: fix signature

* fix: check that spacecollection does not exist yet

* feat: ensure that given address params are valid addresses

* feat: validate address arguments

* feat: use dynamic domain

* fix: lock snapshot.js to 0.4.97

Due to newer version breaking jest test

* chore: fix timer issue on dependent snapshot.js

* chore: enable jest fakeTimer globally

* Revert "chore: enable jest fakeTimer globally"

This reverts commit 524754d.

* Revert "chore: fix timer issue on dependent snapshot.js"

This reverts commit ff2522f.

* feat: return `verifyingContract` in deploy payload

* fix: use `forEach` for loop

* fix: remove unused assertion

* chore: print test code coverage

* chore: move all process.env definition to file's top

* fix: fail early to avoid unecessary request

* fix: fail early to avoid unecessary request

* chore: remove `NETWORK`, in favor of autodetection from `HUB_URL`

* chore: remove unused check

* chore: disable code coverage in e2e tests

* chore: improve readability

* feat: add endpoint to return the snapshotFee

* chore: make it clear which contract the ABI is coming from

* feat: auto-expire the cache

* fix: fix wrong ABI, and remove unused functions

* feat: return contract ABI in payload

* chore: remove unused import

* chore: update README with new returned property

---------

Co-authored-by: Chaitanya <[email protected]>
  • Loading branch information
wa0x6e and ChaituVR authored Jul 6, 2023
1 parent 0a4c167 commit f01c461
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 26 deletions.
24 changes: 3 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ Validate offchain data, and return a payload

#### Get global data

Retrieve global data from the smart contract (results are cached in the StorageEngine, with a 60min TTL).
Retrieve global data from the smart contract.

Send a `GET` request to `/api/nft-claimer`

Expand Down Expand Up @@ -182,26 +182,6 @@ Send a `POST` request with:
curl -X POST localhost:3005/api/nft-claimer/deploy -H "Content-Type: application/json" -d '{"id": "fabien.eth", "address": "00000000000000000000000000000000000000000000000000000000000004d2", "salt": "123454678", "maxSupply": 100, "mintPrice": 10000, "spaceTreasury": "00000000000000000000000000000000000000000000000000000000000004d2", "proposerFee": 10}'
```

#### Sign deploy

Sign and return the payload for the SpaceCollectionFactory contract, in order to deploy a new SpaceCollection contract

Send a `POST` request with:

| `keyname` | Type | Description | Example |
| --------------- | -------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `address` | Wallet address | The sender wallet address | `0x00000000000000000000000000000000000000000000000000000000000004d2` |
| `id` | `string` | A space ID | `fabien.eth` |
| `salt` | `string` | A string representation of a BigInt number | `72536493147621360896130495100276306361343381736075662552878320684807833746288` |
| `maxSupply` | `number` | The maximum number of mintable NFTs for each proposal | `100` |
| `mintPrice` | `string` | A string representation a a BigInt number, for the price in wei | `100000000000000000` |
| `spaceTreasury` | Wallet address | The wallet address receiving the funds | `0x00000000000000000000000000000000000000000000000000000000000004d2` |
| `proposerFee` | `number` | A number between 0 and 100, for the percentage of the mint price reversed to the proposal creator | `5` |

```bash
curl -X POST localhost:3005/api/nft-claimer/deploy -H "Content-Type: application/json" -d '{"id": "fabien.eth", "address": "00000000000000000000000000000000000000000000000000000000000004d2", "salt": "123454678", "maxSupply": 100, "mintPrice": 10000, "spaceTreasury": "00000000000000000000000000000000000000000000000000000000000004d2", "proposerFee": 10}'
```

If the given `address` is the space controller, and the space has not setup NFT Claimer yet, this endpoint will return a `payload` object, with all parameters required for sending the transaction to the SpaceCollectionFactory contract

##### Example payload
Expand All @@ -210,6 +190,7 @@ If the given `address` is the space controller, and the space has not setup NFT
{
"initializer": "0x977b0efb00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000091fd2c8d24767db4ece7069aa27832ffaf8590f300000000000000000000000091fd2c8d24767db4ece7069aa27832ffaf8590f300000000000000000000000000000000000000000000000000000000000000075465737444414f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003302e3100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007656e732e65746800000000000000000000000000000000000000000000000000",
"salt": "123454678",
"abi": "function deployProxy(address implementation, bytes initializer, uint256 salt, uint8 v, bytes32 r, bytes32 s)",
"implementation": "0x33505720a7921d23E6b02EB69623Ed6A008Ca511",
"signature": {
"r": "0xac72b099abc370f7dadca09110907fd0856d1e343b64dcb13bc4a55fa00fc8de",
Expand Down Expand Up @@ -251,6 +232,7 @@ If given proposal's space has enabled NFT claimer, and there are still mintable
"proposer": "0x1abb90a506a352e51d587b0ee8c387c0b129ea018aa77345fe7b5c2defa7d150",
"recipient": "0x1abb90a506a352e51d587b0ee8c387c0b129ea018aa77345fe7b5c2defa7d150",
"spaceId": "fabien.eth",
"abi": "function mint(address proposer, uint256 proposalId, uint256 salt, uint8 v, bytes32 r, bytes32 s)",
"proposalId": "72536493147621360896130495100276306361343381736075662552878320684807833746288",
"signature": {
"r": "0xac72b099abc370f7dadca09110907fd0856d1e343b64dcb13bc4a55fa00fc8de",
Expand Down
9 changes: 5 additions & 4 deletions src/lib/nftClaimer/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { getAddress } from '@ethersproject/address';
import { splitSignature } from '@ethersproject/bytes';
import { Interface } from '@ethersproject/abi';
import { FormatTypes, Interface } from '@ethersproject/abi';
import { fetchSpace } from '../../helpers/snapshot';
import { signer, validateAddresses, validateSpace } from './utils';
import abi from './deployImplementationAbi.json';
import spaceCollectionAbi from './spaceCollectionImplementationAbi.json';
import spaceFactoryAbi from './spaceFactoryAbi.json';

const DeployType = {
Deploy: [
Expand Down Expand Up @@ -47,6 +48,7 @@ export default async function payload(
const result = {
initializer,
salt,
abi: new Interface(spaceFactoryAbi).getFunction('deployProxy').format(FormatTypes.full),
verifyingContract: VERIFYING_CONTRACT,
implementation: IMPLEMENTATION_ADDRESS,
signature: await generateSignature(IMPLEMENTATION_ADDRESS, initializer, salt)
Expand All @@ -66,7 +68,6 @@ function getInitializer(args: {
spaceTreasury: string;
spaceOwner: string;
}) {
const abiInterface = new Interface(abi);
const params = [
args.spaceId,
'0.1',
Expand All @@ -81,7 +82,7 @@ function getInitializer(args: {
// the smart contract version
// NOTE Do not forget to remove the last 4 params in the ABI when copy/pasting
// from the smart contract
const initializer = abiInterface.encodeFunctionData('initialize', params);
const initializer = new Interface(spaceCollectionAbi).encodeFunctionData('initialize', params);
const result = `${INITIALIZE_SELECTOR}${initializer.slice(10)}`;

console.debug('Initializer params', params);
Expand Down
5 changes: 4 additions & 1 deletion src/lib/nftClaimer/mint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
numberizeProposalId,
validateAddresses
} from './utils';
import abi from './spaceCollectionImplementationAbi.json';
import { FormatTypes, Interface } from '@ethersproject/abi';

const MintType = {
Mint: [
Expand Down Expand Up @@ -45,7 +47,8 @@ export default async function payload(
contractAddress: verifyingContract,
spaceId: proposal?.space.id,
...message,
salt
salt,
abi: new Interface(abi).getFunction('mint').format(FormatTypes.full)
};
}

Expand Down
45 changes: 45 additions & 0 deletions src/lib/nftClaimer/spaceCollectionImplementationAbi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
[
{
"inputs": [
{ "internalType": "string", "name": "name", "type": "string" },
{ "internalType": "string", "name": "version", "type": "string" },
{ "internalType": "uint128", "name": "_maxSupply", "type": "uint128" },
{ "internalType": "uint256", "name": "_mintPrice", "type": "uint256" },
{ "internalType": "uint8", "name": "_proposerFee", "type": "uint8" },
{ "internalType": "address", "name": "_spaceTreasury", "type": "address" },
{ "internalType": "address", "name": "_spaceOwner", "type": "address" }
],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{ "internalType": "address", "name": "proposer", "type": "address" },
{ "internalType": "uint256", "name": "proposalId", "type": "uint256" },
{ "internalType": "uint256", "name": "salt", "type": "uint256" },
{ "internalType": "uint8", "name": "v", "type": "uint8" },
{ "internalType": "bytes32", "name": "r", "type": "bytes32" },
{ "internalType": "bytes32", "name": "s", "type": "bytes32" }
],
"name": "mint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{ "internalType": "address[]", "name": "proposers", "type": "address[]" },
{ "internalType": "uint256[]", "name": "proposalIds", "type": "uint256[]" },
{ "internalType": "uint256", "name": "salt", "type": "uint256" },
{ "internalType": "uint8", "name": "v", "type": "uint8" },
{ "internalType": "bytes32", "name": "r", "type": "bytes32" },
{ "internalType": "bytes32", "name": "s", "type": "bytes32" }
],
"name": "mintBatch",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
37 changes: 37 additions & 0 deletions src/lib/nftClaimer/spaceFactoryAbi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[
{
"inputs": [
{ "internalType": "address", "name": "implementation", "type": "address" },
{ "internalType": "bytes", "name": "initializer", "type": "bytes" },
{ "internalType": "uint256", "name": "salt", "type": "uint256" },
{ "internalType": "uint8", "name": "v", "type": "uint8" },
{ "internalType": "bytes32", "name": "r", "type": "bytes32" },
{ "internalType": "bytes32", "name": "s", "type": "bytes32" }
],
"name": "deployProxy",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},

{
"inputs": [],
"name": "snapshotFee",
"outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],
"stateMutability": "view",
"type": "function"
},

{
"inputs": [
{ "internalType": "uint8", "name": "_snapshotFee", "type": "uint8" },
{ "internalType": "address", "name": "_snapshotOwner", "type": "address" },
{ "internalType": "address", "name": "_snapshotTreasury", "type": "address" },
{ "internalType": "address", "name": "_verifiedSigner", "type": "address" }
],
"name": "updateFactorySettings",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
1 change: 1 addition & 0 deletions src/lib/nftClaimer/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ export async function snapshotFee() {
['function snapshotFee() public view returns (uint8)'],
provider
);

return contract.snapshotFee();
} catch (e: any) {
console.error(e);
Expand Down

0 comments on commit f01c461

Please sign in to comment.