Skip to content

Commit

Permalink
Merge pull request #963 from graphprotocol/mde/add-data-edge-contracts
Browse files Browse the repository at this point in the history
chore: add DataEdge contracts
  • Loading branch information
Maikol authored Mar 25, 2024
2 parents 59154f7 + c8331d5 commit ff8f0ed
Show file tree
Hide file tree
Showing 30 changed files with 2,844 additions and 56 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/ci-data-edge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: CI - packages/data-edge

env:
CI: true

on:
push:
branches: "*"
paths:
- packages/data-edge/**
pull_request:
branches: "*"
paths:
- packages/data-edge/**
workflow_dispatch:

jobs:
test-ci:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup
- name: Run tests
run: yarn test
8 changes: 7 additions & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,11 @@
. "$(dirname -- "$0")/_/husky.sh"

# contracts
cd packages/contracts
pushd packages/contracts
npx --no-install lint-staged
popd

# data-edge
pushd packages/data-edge
npx --no-install lint-staged
popd
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"packageManager": "[email protected]",
"workspaces": [
"packages/contracts",
"packages/data-edge",
"packages/eslint-graph-config",
"packages/sdk",
"packages/solhint-graph-config",
Expand Down
4 changes: 4 additions & 0 deletions packages/data-edge/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
MNEMONIC=
INFURA_KEY=
ETHERSCAN_API_KEY=
ARBISCAN_API_KEY=
Empty file.
10 changes: 10 additions & 0 deletions packages/data-edge/.solcover.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const skipFiles = ['']

module.exports = {
providerOptions: {
mnemonic: 'myth like bonus scare over problem client lizard pioneer submit female collect',
network_id: 1337,
},
skipFiles,
istanbulFolder: './reports/coverage',
}
342 changes: 342 additions & 0 deletions packages/data-edge/LICENSE

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions packages/data-edge/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Data Edge

A DataEdge contract is used to store arbitrary data on-chain on any EVM compatible blockchain. A subgraph can then read all the calldata sent to a particular contract, decode it and update the subgraph state accordingly.

The DataEdge accepts any function call by using a fallback function that will not revert. It is up to the implementor to define the calldata format as well as how to decode it.

### Additional Considerations

- Fallback is not payable to avoid anyone sending ETH by mistake as the main purpose is to store calldata.

# Deploying

Setup a `.env` file with the keys you want to use for deployments. You can use `.env.sample` as a guide.
Deploy a `DataEdge` contract by running `yarn deploy -- --network <network-name>`

# Copyright

Copyright &copy; 2022 The Graph Foundation

Licensed under [GPL license](LICENSE).
10 changes: 10 additions & 0 deletions packages/data-edge/addresses.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"421614": {
"DataEdge": "0x17f1fcD16E2A9fF2a55c63C97a778D96Fa473548",
"EventfulDataEdge": "0x9b9402939133F27c6eba81a321dfBFa1feE6714E"
},
"11155111": {
"DataEdge": "0x00C602A72363917Bc30a793593731F93352eB85d",
"EventfulDataEdge": "0xEFC8D47673777b899f2FB597C6FC0E87ecce98Cb"
}
}
13 changes: 13 additions & 0 deletions packages/data-edge/contracts/DataEdge.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.12;

/// @title Data Edge contract is only used to store on-chain data, it does not
/// perform execution. On-chain client services can read the data
/// and decode the payload for different purposes.
contract DataEdge {
/// @dev Fallback function, accepts any payload
fallback() external payable {
// no-op
}
}
16 changes: 16 additions & 0 deletions packages/data-edge/contracts/EventfulDataEdge.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.12;

/// @title Data Edge contract is only used to store on-chain data, it does not
/// perform execution. On-chain client services can read the data
/// and decode the payload for different purposes.
/// NOTE: This version emits an event with the calldata.
contract EventfulDataEdge {
event Log(bytes data);

/// @dev Fallback function, accepts any payload
fallback() external payable {
emit Log(msg.data);
}
}
17 changes: 17 additions & 0 deletions packages/data-edge/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const config = require('eslint-graph-config')

module.exports = [
...config.default,
{
rules: {
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
},
},
{
ignores: ['**/reports/*'],
},
]
182 changes: 182 additions & 0 deletions packages/data-edge/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import * as dotenv from 'dotenv'
dotenv.config()

import { HardhatUserConfig } from 'hardhat/types'
import { task } from 'hardhat/config'

// Plugins

import '@nomiclabs/hardhat-ethers'
import '@nomiclabs/hardhat-etherscan'
import '@nomiclabs/hardhat-waffle'
import 'hardhat-abi-exporter'
import 'hardhat-gas-reporter'
import 'hardhat-contract-sizer'
import '@tenderly/hardhat-tenderly'
import '@openzeppelin/hardhat-upgrades'
import '@typechain/hardhat'

// Tasks

import './tasks/craft-calldata'
import './tasks/post-calldata'

// Networks

interface NetworkConfig {
network: string
chainId: number
gas?: number | 'auto'
gasPrice?: number | 'auto'
url?: string
}

const networkConfigs: NetworkConfig[] = [
{ network: 'mainnet', chainId: 1 },
{ network: 'ropsten', chainId: 3 },
{ network: 'rinkeby', chainId: 4 },
{ network: 'kovan', chainId: 42 },
{ network: 'sepolia', chainId: 11155111 },
{
network: 'arbitrum-one',
chainId: 42161,
url: 'https://arb1.arbitrum.io/rpc',
},
{
network: 'arbitrum-goerli',
chainId: 421613,
url: 'https://goerli-rollup.arbitrum.io/rpc',
},
{
network: 'arbitrum-sepolia',
chainId: 421614,
url: 'https://sepolia-rollup.arbitrum.io/rpcblock',
},
]

function getAccountMnemonic() {
return process.env.MNEMONIC || ''
}

function getDefaultProviderURL(network: string) {
return `https://${network}.infura.io/v3/${process.env.INFURA_KEY}`
}

function setupDefaultNetworkProviders(buidlerConfig) {
for (const netConfig of networkConfigs) {
buidlerConfig.networks[netConfig.network] = {
chainId: netConfig.chainId,
url: netConfig.url ? netConfig.url : getDefaultProviderURL(netConfig.network),
gas: netConfig.gasPrice || 'auto',
gasPrice: netConfig.gasPrice || 'auto',
accounts: {
mnemonic: getAccountMnemonic(),
},
}
}
}

// Tasks

task('accounts', 'Prints the list of accounts', async (_, bre) => {
const accounts = await bre.ethers.getSigners()
for (const account of accounts) {
console.log(await account.getAddress())
}
})

// Config
const config: HardhatUserConfig = {
paths: {
sources: './contracts',
tests: './test',
artifacts: './build/contracts',
},
solidity: {
compilers: [
{
version: '0.8.12',
settings: {
optimizer: {
enabled: true,
runs: 200,
},
outputSelection: {
'*': {
'*': ['storageLayout'],
},
},
},
},
],
},
defaultNetwork: 'hardhat',
networks: {
hardhat: {
chainId: 1337,
loggingEnabled: false,
gas: 1200000,
gasPrice: 'auto',
blockGasLimit: 12000000,
accounts: {
mnemonic: 'myth like bonus scare over problem client lizard pioneer submit female collect',
},
mining: {
auto: true,
interval: 0,
},
},
ganache: {
chainId: 1337,
url: 'http://localhost:8545',
},
},
etherscan: {
apiKey: {
mainnet: process.env.ETHERSCAN_API_KEY,
goerli: process.env.ETHERSCAN_API_KEY,
sepolia: process.env.ETHERSCAN_API_KEY,
arbitrumOne: process.env.ARBISCAN_API_KEY,
arbitrumGoerli: process.env.ARBISCAN_API_KEY,
arbitrumSepolia: process.env.ARBISCAN_API_KEY,
},
customChains: [
{
network: 'arbitrumSepolia',
chainId: 421614,
urls: {
apiURL: 'https://api-sepolia.arbiscan.io/api',
browserURL: 'https://sepolia.arbiscan.io',
},
},
],
},
gasReporter: {
enabled: process.env.REPORT_GAS ? true : false,
showTimeSpent: true,
currency: 'USD',
outputFile: 'reports/gas-report.log',
},
typechain: {
outDir: 'build/types',
target: 'ethers-v5',
},
abiExporter: {
path: './build/abis',
clear: false,
flat: true,
},
tenderly: {
project: process.env.TENDERLY_PROJECT,
username: process.env.TENDERLY_USERNAME,
},
contractSizer: {
alphaSort: true,
runOnCompile: false,
disambiguatePaths: true,
},
}

setupDefaultNetworkProviders(config)

export default config
Loading

0 comments on commit ff8f0ed

Please sign in to comment.