Skip to content
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
760 changes: 0 additions & 760 deletions packages/contracts-test/tests/unit/l2/l2Curation.test.ts

This file was deleted.

22 changes: 22 additions & 0 deletions packages/subgraph-discovery/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[profile.default]
src = 'test'
out = 'forge-artifacts'
test = 'test'
libs = ["node_modules"]
cache_path = 'cache_forge'
auto_detect_remappings = false
remappings = [
"@graphprotocol/=node_modules/@graphprotocol/",
"forge-std/=node_modules/forge-std/src/",
]
solc_version = '0.8.35'
evm_version = 'cancun'
fs_permissions = [{ access = "read", path = "node_modules/@graphprotocol/contracts/artifacts" }]
ignored_warnings_from = ["node_modules"]

[lint]
# Disable lint-on-build: forge's lint walker follows symlinks without cycle detection and
# infinite-loops on this package's pnpm-hoisted node_modules.
lint_on_build = false
exclude_lints = ["mixed-case-function", "mixed-case-variable", "block-timestamp"]
ignore = ["node_modules/**", "**/node_modules/**"]
19 changes: 19 additions & 0 deletions packages/subgraph-discovery/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "@graphprotocol/subgraph-discovery",
"version": "0.0.0",
"private": true,
"description": "The Graph subgraph discovery and curation contracts",
"license": "GPL-2.0-or-later",
"scripts": {
"build": "pnpm build:dep",
"build:dep": "pnpm --filter '@graphprotocol/subgraph-discovery^...' run build:self",
"clean": "rm -rf forge-artifacts/ cache_forge/",
"test": "pnpm build && pnpm test:self",
"test:self": "forge test"
},
"devDependencies": {
"@graphprotocol/contracts": "workspace:^",
"@graphprotocol/interfaces": "workspace:^",
"forge-std": "catalog:"
}
}
12 changes: 12 additions & 0 deletions packages/subgraph-discovery/test/unit/Setup.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

import { DiscoveryTest } from "./shared/DiscoveryTest.t.sol";

contract SetupTest is DiscoveryTest {
function test_Setup_Wired() public view {
assertEq(nft.minter(), address(gns));
assertEq(curation.subgraphService(), subgraphService);
assertEq(gns.counterpartGNSAddress(), l1GNS);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

interface IGraphTokenLike {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
event MinterAdded(address indexed account);
event MinterRemoved(address indexed account);

function totalSupply() external view returns (uint256);

function balanceOf(address account) external view returns (uint256);

function transfer(address to, uint256 amount) external returns (bool);

function transferFrom(address from, address to, uint256 amount) external returns (bool);

function approve(address spender, uint256 amount) external returns (bool);

function allowance(address owner, address spender) external view returns (uint256);

function burn(uint256 amount) external;

function burnFrom(address account, uint256 amount) external;

function mint(address to, uint256 amount) external;

function addMinter(address account) external;

function removeMinter(address account) external;

function renounceMinter() external;

function isMinter(address account) external view returns (bool);

function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;

function nonces(address owner) external view returns (uint256);

function governor() external view returns (address);

function transferOwnership(address newGovernor) external;

function acceptOwnership() external;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

interface IL2CurationLike {
event Signalled(
address indexed curator,
bytes32 indexed subgraphDeploymentID,
uint256 tokens,
uint256 signal,
uint256 curationTax
);
event Burned(address indexed curator, bytes32 indexed subgraphDeploymentID, uint256 tokens, uint256 signal);
event Collected(bytes32 indexed subgraphDeploymentID, uint256 tokens);

function initialize(
address controller,
address curationTokenMaster,
uint32 curationTaxPercentage,
uint256 minimumCurationDeposit
) external;

function pools(
bytes32 subgraphDeploymentID
) external view returns (uint256 tokens, uint32 reserveRatio, address gcs);

function defaultReserveRatio() external view returns (uint32);

function setDefaultReserveRatio(uint32 defaultReserveRatio) external;

function minimumCurationDeposit() external view returns (uint256);

function setMinimumCurationDeposit(uint256 minimumCurationDeposit) external;

function curationTaxPercentage() external view returns (uint32);

function setCurationTaxPercentage(uint32 percentage) external;

function curationTokenMaster() external view returns (address);

function setCurationTokenMaster(address curationTokenMaster) external;

function subgraphService() external view returns (address);

function setSubgraphService(address subgraphService) external;

function mint(
bytes32 subgraphDeploymentID,
uint256 tokensIn,
uint256 signalOutMin
) external returns (uint256 signalOut, uint256 curationTax);

function mintTaxFree(bytes32 subgraphDeploymentID, uint256 tokensIn) external returns (uint256);

function burn(bytes32 subgraphDeploymentID, uint256 signalIn, uint256 tokensOutMin) external returns (uint256);

function collect(bytes32 subgraphDeploymentID, uint256 tokens) external;

function isCurated(bytes32 subgraphDeploymentID) external view returns (bool);

function getCuratorSignal(address curator, bytes32 subgraphDeploymentID) external view returns (uint256);

function getCurationPoolSignal(bytes32 subgraphDeploymentID) external view returns (uint256);

function getCurationPoolTokens(bytes32 subgraphDeploymentID) external view returns (uint256);

function tokensToSignal(bytes32 subgraphDeploymentID, uint256 tokensIn) external view returns (uint256, uint256);

function tokensToSignalNoTax(bytes32 subgraphDeploymentID, uint256 tokensIn) external view returns (uint256);

function tokensToSignalToTokensNoTax(
bytes32 subgraphDeploymentID,
uint256 tokensIn
) external view returns (uint256);

function signalToTokens(bytes32 subgraphDeploymentID, uint256 signalIn) external view returns (uint256);
}
125 changes: 125 additions & 0 deletions packages/subgraph-discovery/test/unit/interfaces/IL2GNSLike.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

interface IL2GNSLike {
event SubgraphMetadataUpdated(uint256 indexed subgraphID, bytes32 subgraphMetadata);
event SubgraphVersionUpdated(
uint256 indexed subgraphID,
bytes32 indexed subgraphDeploymentID,
bytes32 versionMetadata
);
event SignalMinted(
uint256 indexed subgraphID,
address indexed curator,
uint256 nSignalCreated,
uint256 vSignalCreated,
uint256 tokensDeposited
);
event SignalBurned(
uint256 indexed subgraphID,
address indexed curator,
uint256 nSignalBurnt,
uint256 vSignalBurnt,
uint256 tokensReceived
);
event SubgraphPublished(uint256 indexed subgraphID, bytes32 indexed subgraphDeploymentID, uint32 reserveRatio);
event SubgraphUpgraded(
uint256 indexed subgraphID,
uint256 vSignalCreated,
uint256 tokensSignalled,
bytes32 indexed subgraphDeploymentID
);
event SubgraphDeprecated(uint256 indexed subgraphID, uint256 withdrawableGRT);
event SubgraphReceivedFromL1(
uint256 indexed _l1SubgraphID,
uint256 indexed _l2SubgraphID,
address indexed _owner,
uint256 _tokens
);
event SubgraphL2TransferFinalized(uint256 indexed _l2SubgraphID);
event CuratorBalanceReceived(
uint256 indexed _l1SubgraphId,
uint256 indexed _l2SubgraphID,
address indexed _l2Curator,
uint256 _tokens
);
event CuratorBalanceReturnedToBeneficiary(
uint256 indexed _l1SubgraphID,
address indexed _l2Curator,
uint256 _tokens
);

function initialize(address controller, address subgraphNFT) external;

function approveAll() external;

function setCounterpartGNSAddress(address counterpart) external;

function counterpartGNSAddress() external view returns (address);

function ownerTaxPercentage() external view returns (uint32);

function setOwnerTaxPercentage(uint32 ownerTaxPercentage) external;

function nextAccountSeqID(address account) external view returns (uint256);

function publishNewSubgraph(
bytes32 subgraphDeploymentID,
bytes32 versionMetadata,
bytes32 subgraphMetadata
) external;

function publishNewVersion(uint256 subgraphID, bytes32 subgraphDeploymentID, bytes32 versionMetadata) external;

function publishNewVersion(
uint256 subgraphID,
bytes32 subgraphDeploymentID,
bytes32 versionMetadata,
uint256 signalOutMin
) external;

function deprecateSubgraph(uint256 subgraphID) external;

function mintSignal(uint256 subgraphID, uint256 tokensIn, uint256 nSignalOutMin) external;

function burnSignal(uint256 subgraphID, uint256 nSignal, uint256 tokensOutMin) external;

function onTokenTransfer(address from, uint256 amount, bytes calldata data) external;

function finishSubgraphTransferFromL1(
uint256 l2SubgraphID,
bytes32 subgraphDeploymentID,
bytes32 subgraphMetadata,
bytes32 versionMetadata
) external;

function ownerOf(uint256 tokenID) external view returns (address);

function subgraphs(
uint256 subgraphID
)
external
view
returns (
uint256 vSignal,
uint256 nSignal,
bytes32 subgraphDeploymentID,
uint32 reserveRatio,
bool disabled,
uint256 withdrawableGRT
);

function subgraphL2TransferData(
uint256 subgraphID
) external view returns (uint256 tokens, bool l2Done, uint256 subgraphReceivedOnL2BlockNumber);

function getAliasedL2SubgraphID(uint256 l1SubgraphID) external pure returns (uint256);

function getCuratorSignal(uint256 subgraphID, address curator) external view returns (uint256);

function tokensToNSignal(uint256 subgraphID, uint256 tokensIn) external view returns (uint256, uint256, uint256);

function nSignalToTokens(uint256 subgraphID, uint256 nSignalIn) external view returns (uint256, uint256);

function vSignalToNSignal(uint256 subgraphID, uint256 vSignalIn) external view returns (uint256);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

interface ISubgraphNFTLike {
function ownerOf(uint256 tokenId) external view returns (address);

function minter() external view returns (address);

function setMinter(address minter) external;

function setTokenDescriptor(address tokenDescriptor) external;

function tokenURI(uint256 tokenId) external view returns (string memory);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

import { L2CurationSharedTest } from "./L2CurationShared.t.sol";

contract BondingCurveTest is L2CurationSharedTest {
function test_BondingCurve_RevertWhen_SignalToTokensNotCurated() public {
vm.expectRevert(bytes("Subgraph deployment must be curated to perform calculations"));
curation.signalToTokens(SUBGRAPH_DEPLOYMENT_ID, 100 ether);
}

function test_BondingCurve_ConvertSignalToTokens() public {
_mint(CURATOR_TOKENS);

uint256 signal = curation.getCurationPoolSignal(SUBGRAPH_DEPLOYMENT_ID);
assertEq(curation.signalToTokens(SUBGRAPH_DEPLOYMENT_ID, signal), CURATOR_TOKENS);
}

function test_BondingCurve_ConvertSignalToTokensWithCurationTax() public {
uint32 curationTaxPercentage = 50_000; // 5%
vm.prank(governor);
curation.setCurationTaxPercentage(curationTaxPercentage);

uint256 expectedCurationTax = (CURATOR_TOKENS * curationTaxPercentage) / MAX_PPM;
(, uint256 curationTax) = curation.tokensToSignal(SUBGRAPH_DEPLOYMENT_ID, CURATOR_TOKENS);
_mint(CURATOR_TOKENS);

uint256 signal = curation.getCurationPoolSignal(SUBGRAPH_DEPLOYMENT_ID);
assertEq(curation.signalToTokens(SUBGRAPH_DEPLOYMENT_ID, signal), CURATOR_TOKENS - expectedCurationTax);
assertEq(expectedCurationTax, curationTax);
}

function test_BondingCurve_ConvertTokensToSignal() public view {
(uint256 signal, ) = curation.tokensToSignal(SUBGRAPH_DEPLOYMENT_ID, 1000 ether);
assertEq(signal, SIGNAL_AMOUNT_FOR_1000_TOKENS);
}

function test_BondingCurve_RevertWhen_ConvertTokensToSignalBelowMinimum() public {
vm.expectRevert(bytes("Curation deposit is below minimum required"));
curation.tokensToSignal(keccak256("nonCuratedSubgraphDeploymentID"), 0);
}

function test_BondingCurve_TokensToSignalToTokensNoTax() public {
_mint(TOKENS_TO_DEPOSIT);

// Flat curve: depositing tokens and redeeming the resulting signal returns the same tokens
assertEq(curation.tokensToSignalToTokensNoTax(SUBGRAPH_DEPLOYMENT_ID, TOKENS_TO_DEPOSIT), TOKENS_TO_DEPOSIT);
}
}
Loading
Loading