Skip to content
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

Feature: Add support for erc1155 tokens #443

Merged
merged 8 commits into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/subgraph/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [UPCOMING]
### Added
- Add suport for `ERC1155` tokens.

## [1.2.1]
### Changed

- Fixed wrong interface for indexing GovernanceWrappedERC20.
Expand Down
2 changes: 2 additions & 0 deletions packages/subgraph/manifest/subgraph.placeholder.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ templates:
file: $ARAGON_OSX_MODULE/artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.json
- name: ERC721
file: $ARAGON_OSX_MODULE/artifacts/@openzeppelin/contracts/token/ERC721/ERC721.sol/ERC721.json
- name: ERC1155
file: $ARAGON_OSX_MODULE/artifacts/@openzeppelin/contracts/token/ERC1155/ERC1155.sol/ERC1155.json
- name: ERC165
file: $ARAGON_OSX_MODULE/artifacts/@openzeppelin/contracts/utils/introspection/ERC165.sol/ERC165.json
- name: TokenVoting
Expand Down
38 changes: 38 additions & 0 deletions packages/subgraph/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ type ERC721Contract implements Token @entity(immutable: true) {
symbol: String
}

type ERC1155Contract implements Token @entity(immutable: true) {
id: ID! # use address as id
name: String
symbol: String
}

# Token Balances
interface TokenBalance {
id: ID! # dao address + token address
Expand Down Expand Up @@ -59,6 +65,23 @@ type ERC721Balance implements TokenBalance @entity {
lastUpdated: BigInt!
}

type ERC1155Balance implements TokenBalance @entity {
id: ID!
token: ERC1155Contract!
dao: Dao!
balances: [ERC1155TokenIdBalance!]! @derivedFrom(field: "balance")
metadataUri: String!
lastUpdated: BigInt!
}

type ERC1155TokenIdBalance @entity {
id: ID!
balance: ERC1155Balance!
tokenId: BigInt!
amount: BigInt!
lastUpdated: BigInt!
}

# Token Transfers

enum TransferType {
Expand Down Expand Up @@ -104,6 +127,21 @@ type ERC721Transfer implements TokenTransfer @entity(immutable: true) {
createdAt: BigInt!
}

type ERC1155Transfer implements TokenTransfer @entity(immutable: true) {
id: ID!
dao: Dao!
token: ERC1155Contract!
tokenId: BigInt!
amount: BigInt!
operator: Bytes!
from: Bytes!
to: Bytes!
proposal: IProposal
type: TransferType!
txHash: Bytes!
createdAt: BigInt!
}

type NativeTransfer implements TokenTransfer @entity(immutable: true) {
id: ID!
dao: Dao!
Expand Down
28 changes: 26 additions & 2 deletions packages/subgraph/src/dao/dao_v1_0_0.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {BigInt, Bytes, log, store} from '@graphprotocol/graph-ts';
import {BigInt, Bytes, store} from '@graphprotocol/graph-ts';

import {
MetadataSet,
Expand Down Expand Up @@ -26,8 +26,16 @@ import {ADDRESS_ZERO} from '../utils/constants';
import {handleERC721Received} from '../utils/tokens/erc721';
import {handleERC20Deposit} from '../utils/tokens/erc20';
import {handleNativeDeposit} from '../utils/tokens/eth';
import {onERC721Received} from '../utils/tokens/common';
import {
onERC1155BatchReceived,
onERC1155Received,
onERC721Received
} from '../utils/tokens/common';
import {handleAction, updateProposalWithFailureMap} from './utils';
import {
handleERC1155BatchReceived,
handleERC1155Received
} from '../utils/tokens/erc1155';

export function handleMetadataSet(event: MetadataSet): void {
let daoId = event.address.toHexString();
Expand All @@ -54,6 +62,22 @@ export function handleCallbackReceived(event: CallbackReceived): void {
event
);
}
if (functionSig.equals(Bytes.fromHexString(onERC1155Received))) {
handleERC1155Received(
event.params.sender,
event.address,
event.params.data,
event
);
}
if (functionSig.equals(Bytes.fromHexString(onERC1155BatchReceived))) {
handleERC1155BatchReceived(
event.params.sender,
event.address,
event.params.data,
event
);
}
}

export function handleExecuted(event: Executed): void {
Expand Down
18 changes: 17 additions & 1 deletion packages/subgraph/src/dao/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ import {
ERC721_safeTransferFromNoData,
ERC721_safeTransferFromWithData,
ERC20_transfer,
ERC20_transferFrom
ERC20_transferFrom,
ERC1155_safeBatchTransferFrom,
ERC1155_safeTransferFrom
} from '../utils/tokens/common';
import {handleERC20Action} from '../utils/tokens/erc20';
import {handleERC721Action} from '../utils/tokens/erc721';
import {handleNativeAction} from '../utils/tokens/eth';
import {handleERC1155Action} from '../utils/tokens/erc1155';

// AssemblyScript struggles having mutliple return types. Due to this,
// The below seems most effective way.
Expand Down Expand Up @@ -114,6 +117,19 @@ export function handleAction<
event
);
}
if (
methodSig == ERC1155_safeBatchTransferFrom ||
methodSig == ERC1155_safeTransferFrom
) {
handleERC1155Action(
action.to,
event.address,
action.data,
proposalId,
index,
event
);
}

if (methodSig == ERC20_transfer || methodSig == ERC20_transferFrom) {
handleERC20Action(
Expand Down
46 changes: 46 additions & 0 deletions packages/subgraph/src/utils/tokens/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ export const ERC721_transferFrom = '0x23b872dd';
export const ERC20_transfer = '0xa9059cbb';
export const ERC20_transferFrom = '0x23b872dd';

export const onERC1155Received = '0xf23a6e61'; // `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` (i.e. 0xf23a6e61) if it accepts the transfer.
export const onERC1155BatchReceived = '0xbc197c81'; // `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (i.e. 0xbc197c81) if it accepts the transfer(s).
export const ERC1155_safeTransferFrom = '0xf242432a'; // `bytes4(keccak256("safeTransferFrom(address,address,uint256,uint256,bytes)"))` (i.e. 0xf242432a).
export const ERC1155_safeBatchTransferFrom = '0x2eb2c2d6'; // `bytes4(keccak256("safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)"))` (i.e. 0x2eb2c2d6).

export enum TransferType {
Withdraw,
Deposit
Expand All @@ -16,6 +21,9 @@ export enum TransferType {
export const DECODE_OFFSET =
'0x0000000000000000000000000000000000000000000000000000000000000020';

export const ERC165_INTERFACE_ID = '01ffc9a7';
export const ERC1155_INTERFACE_ID = 'd9b67a26';

// Unique ID generation for token transfer entities
export function getTransferId(
txHash: Bytes,
Expand All @@ -29,3 +37,41 @@ export function getTransferId(
.concat('_')
.concat(actionIndex.toString());
}

// Unique ID generation for token balance entities
export function getBalanceId(daoId: string, token: string): string {
return daoId.concat('_').concat(token);
}

// Unique ID generation for token balance entities
export function getTokenIdBalanceId(
daoId: string,
token: string,
tokenId: BigInt
): string {
return daoId
.concat('_')
.concat(token)
.concat('_')
.concat(tokenId.toString());
}

// Unique ID generation for ERC1155 transfers
export function getERC1155TransferId(
txHash: Bytes,
logIndex: BigInt,
actionIndex: number,
batchIndex: number
): string {
return (
txHash
.toHexString()
.concat('_')
.concat(logIndex.toString())
.concat('_')
.concat(actionIndex.toString())
.concat('_')
// add iteration for supporting batch transfers
.concat(batchIndex.toString())
);
}
Loading
Loading