Skip to content

Commit

Permalink
feat: diamond bond with foundry
Browse files Browse the repository at this point in the history
  • Loading branch information
bl0up committed Apr 30, 2024
1 parent 4353add commit fd69ee2
Show file tree
Hide file tree
Showing 41 changed files with 4,642 additions and 107 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ jobs:
with:
# list of Docker images to use as base name for tags
images: |
ghcr.io/settlemint/solidity-empty
ghcr.io/settlemint/solidity-diamond-bond
# generate Docker tags based on the following events/attributes
tags: |
type=schedule
Expand Down
23 changes: 22 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,30 @@ docs/
# Subgraphs
deployment.txt
deployment-anvil.txt
selectors-bond.txt
selectors-erc1155.txt
selectors-loupe.txt
selectors-ownership.txt
subgraph/subgraph.config.json
subgraph/node_modules
subgraph/generated
subgraph/build

.pnpm
.pnpm
node_modules
.env

# Hardhat files
/cache
/artifacts

# TypeChain files
/typechain
/typechain-types

# solidity-coverage files
/coverage
/coverage.json

# Hardhat Ignition default folder for deployments against a local node
ignition/deployments/chain-31337
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/openzeppelin/openzeppelin-contracts
[submodule "lib/prb-math"]
path = lib/prb-math
url = https://github.com/PaulRBerg/prb-math
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ WORKDIR /

RUN git config --global user.email "[email protected]" && \
git config --global user.name "SettleMint" && \
forge init usecase --template settlemint/solidity-empty && \
forge init usecase --template settlemint/solidity-diamond-bond && \
cd usecase && \
forge build

USER root

FROM busybox
FROM cgr.dev/chainguard/busybox:latest

COPY --from=build /usecase /usecase
COPY --from=build /root/.svm /usecase-svm
56 changes: 36 additions & 20 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ anvil:
@anvil

deploy-anvil:
@echo "Deploying with Forge to Anvil..."
@forge create ./src/Counter.sol:Counter --rpc-url anvil --interactive | tee deployment-anvil.txt
@echo "Deploying to Anvil..."
@forge script script/DeployDiamond.s.sol --sender 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --rpc-url anvil --broadcast --unlocked

deploy-btp:
@eval $$(curl -H "x-auth-token: $${BTP_SERVICE_TOKEN}" -s $${BTP_CLUSTER_MANAGER_URL}/ide/foundry/$${BTP_SCS_ID}/env | sed 's/^/export /'); \
args=""; \
if [ ! -z "$${BTP_FROM}" ]; then \
args="--unlocked --from $${BTP_FROM}"; \
args="--unlocked --sender $${BTP_FROM} --broadcast"; \
else \
echo "\033[1;33mWARNING: No keys are activated on the node, falling back to interactive mode...\033[0m"; \
echo ""; \
Expand All @@ -43,27 +43,43 @@ deploy-btp:
if [ "$${BTP_EIP_1559_ENABLED}" = "false" ]; then \
args="$$args --legacy"; \
fi; \
forge create ./src/Counter.sol:Counter $${EXTRA_ARGS} --rpc-url $${BTP_RPC_URL} $$args --constructor-args "GenericToken" "GT" | tee deployment.txt;
forge script script/DeployDiamond.s.sol $${args} --rpc-url $${BTP_RPC_URL} --json

script-anvil:
@if [ ! -f deployment-anvil.txt ]; then \
echo "\033[1;31mERROR: Contract was not deployed or the deployment-anvil.txt went missing.\033[0m"; \
exit 1; \
fi
@DEPLOYED_ADDRESS=$$(grep "Deployed to:" deployment-anvil.txt | awk '{print $$3}') forge script script/Counter.s.sol:CounterScript ${EXTRA_ARGS} --rpc-url anvil -i=1
subgraph:
@echo "Deploying the subgraph..."
@rm -Rf subgraph/subgraph.config.json
@CHAIN_ID=$$(cast chain-id --rpc-url $$BTP_RPC_URL); \
output=$$(jq '.transactions[] | \
select(.transactionType == "CREATE" and \
(.contractName == "GenericToken" or .contractName == "Diamond")) | \
if .contractName == "GenericToken" then \
{contractName: "GenericToken", contractAddress: (.contractAddress // "not available"), transactionHash: (.hash // "not available")} \
elif .contractName == "Diamond" then \
{contractName: "Diamond", contractAddress: (.contractAddress // "not available"), transactionHash: (.hash // "not available")} \
else empty end' broadcast/DeployDiamond.s.sol/$$CHAIN_ID/run-latest.json); \
export DEPLOYED_ERC20_ADDRESS=$$(echo "$$output" | jq -r 'select(.contractName == "GenericToken") | .contractAddress'); \
export TRANSACTION_HASH_ERC20=$$(echo "$$output" | jq -r 'select(.contractName == "GenericToken") | .transactionHash'); \
export DEPLOYED_ADDRESS=$$(echo "$$output" | jq -r 'select(.contractName == "Diamond") | .contractAddress'); \
export TRANSACTION_HASH=$$(echo "$$output" | jq -r 'select(.contractName == "Diamond") | .transactionHash'); \
export BLOCK_NUMBER=$$(cast receipt --rpc-url $${BTP_RPC_URL} $${TRANSACTION_HASH} | grep "^blockNumber" | awk '{print $$2}'); \
export BLOCK_NUMBER_ERC20=$$(cast receipt --rpc-url $${BTP_RPC_URL} $${TRANSACTION_HASH_ERC20} | grep "^blockNumber" | awk '{print $$2}'); \
yq e -p=json -o=json '.datasources[0].address = strenv(DEPLOYED_ADDRESS) | .datasources[0].startBlock = strenv(BLOCK_NUMBER) | .datasources[1].address = strenv(DEPLOYED_ERC20_ADDRESS) | .datasources[1].startBlock = strenv(BLOCK_NUMBER_ERC20) | .chain = strenv(BTP_NODE_UNIQUE_NAME)' subgraph/subgraph.config.template.json > subgraph/subgraph.config.json; \

script:
@if [ ! -f deployment.txt ]; then \
echo "\033[1;31mERROR: Contract was not deployed or the deployment.txt went missing.\033[0m"; \
exit 1; \
fi
@cd subgraph && npx graph-compiler --config subgraph.config.json --include node_modules/@openzeppelin/subgraphs/src/datasources ./datasources --export-schema --export-subgraph
@cd subgraph && yq e '.specVersion = "0.0.4"' -i generated/solidity-diamond-bond.subgraph.yaml
@cd subgraph && yq e '.description = "Solidity Token diamond-bond"' -i generated/solidity-diamond-bond.subgraph.yaml
@cd subgraph && yq e '.repository = "https://github.com/settlemint/solidity-diamond-bond"' -i generated/solidity-diamond-bond.subgraph.yaml
@cd subgraph && yq e '.features = ["nonFatalErrors", "fullTextSearch", "ipfsOnEthereumContracts"]' -i generated/solidity-diamond-bond.subgraph.yaml
@cd subgraph && npx graph codegen generated/solidity-diamond-bond.subgraph.yaml
@cd subgraph && npx graph build generated/solidity-diamond-bond.subgraph.yaml
@eval $$(curl -H "x-auth-token: $${BTP_SERVICE_TOKEN}" -s $${BTP_CLUSTER_MANAGER_URL}/ide/foundry/$${BTP_SCS_ID}/env | sed 's/^/export /'); \
if [ -z "${BTP_FROM}" ]; then \
echo "\033[1;33mWARNING: No keys are activated on the node, falling back to interactive mode...\033[0m"; \
echo ""; \
@DEPLOYED_ADDRESS=$$(grep "Deployed to:" deployment.txt | awk '{print $$3}') forge script script/Counter.s.sol:CounterScript ${EXTRA_ARGS} --rpc-url ${BTP_RPC_URL} -i=1; \
if [ -z "$${BTP_MIDDLEWARE}" ]; then \
echo "\033[1;31mERROR: You have not launched a graph middleware for this smart contract set, aborting...\033[0m"; \
exit 1; \
else \
@DEPLOYED_ADDRESS=$$(grep "Deployed to:" deployment.txt | awk '{print $$3}') forge script script/Counter.s.sol:CounterScript ${EXTRA_ARGS} --rpc-url ${BTP_RPC_URL} --unlocked --froms ${BTP_FROM}; \
cd subgraph; \
npx graph create --node $${BTP_MIDDLEWARE} $${BTP_SCS_NAME}; \
npx graph deploy --version-label v1.0.$$(date +%s) --node $${BTP_MIDDLEWARE} --ipfs $${BTP_IPFS}/api/v0 $${BTP_SCS_NAME} generated/solidity-diamond-bond.subgraph.yaml; \
fi

cast:
Expand Down
34 changes: 17 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ERC20
# Diamond Bond

A basic ERC20 token contract.
A Diamond Bond contract.

## Get started

Expand All @@ -9,7 +9,7 @@ Launch this smart contract set in the SettleMint Blockchain Transformation platf
If you want to use it separately, bootstrap a new project using

```shell
forge init my-erc20-token --template settlemint/solidity-token-erc20
forge init my-diamond-bond --template settlemint/solidity-diamond-bond
```

## DX: Foundry
Expand All @@ -25,77 +25,77 @@ Foundry consists of:

## Documentation

- https://console.settlemint.com/documentation/docs/using-platform/integrated-development-environment/
- https://book.getfoundry.sh/
- <https://console.settlemint.com/documentation/docs/using-platform/integrated-development-environment/>
- <https://book.getfoundry.sh/>

## Usage

### Build

```shell
$ forge build
forge build
```

### Test

```shell
$ forge test
forge test
```

### Format

```shell
$ forge fmt
forge fmt
```

### Gas Snapshots

```shell
$ forge snapshot
forge snapshot
```

### Anvil

Anvil is a local development node, open a terminal in the IDE and launch anvil. You can then deploy to it using `make deploy-anvil`

```shell
$ anvil
anvil
```

### Deploy

Deploy to a local anvil node:

```shell
$ make deploy-anvil
make deploy-anvil
```

When prompted to enter a private key, copy one of the private keys shown in the terminal when you start the anvil node.

Deploy to the connected platform node:

```shell
$ make deploy-btp
make deploy-btp
```

If you have a private key activated on the connected node, it will be used automatically. Else, you will be prompted to enter a private key. You can copy-paste a private key from the platform.

### Cast

```shell
$ cast <subcommand>
cast <subcommand>
```

### Deploy your subgraph

```shell
$ make subgraph
make subgraph
```

### Help

```shell
$ forge --help
$ anvil --help
$ cast --help
forge --help
anvil --help
cast --help
```
1 change: 1 addition & 0 deletions lib/openzeppelin-contracts
Submodule openzeppelin-contracts added at dbb610
1 change: 1 addition & 0 deletions lib/prb-math
Submodule prb-math added at 9dc065
7 changes: 7 additions & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
@prb/test/=lib/prb-math/node_modules/@prb/test/
ds-test/=lib/forge-std/lib/ds-test/src/
erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/
forge-std/=lib/forge-std/src/
openzeppelin-contracts/=lib/openzeppelin-contracts/
prb-math/=lib/prb-math/src/
28 changes: 0 additions & 28 deletions script/Counter.s.sol

This file was deleted.

69 changes: 69 additions & 0 deletions script/DeployDiamond.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "forge-std/Script.sol";
import "../src/facets/BondFacet.sol";
import "../src/facets/ERC1155Facet.sol";
import "../src/facets/DiamondCutFacet.sol";
import "../src/facets/DiamondLoupeFacet.sol";
import "../src/Diamond.sol";
import "../src/upgradeInitializers/DiamondInit.sol";
import {IDiamondCut} from "../src/interfaces/IDiamondCut.sol";
import {BondInitParams} from "../src/libraries/StructBondInit.sol";
import "../src/interfaces/IDiamond.sol";
import "../src/GenericToken.sol";

contract DeployDiamondScript is Script {
function run() public {
vm.startBroadcast();
address owner = msg.sender;
console.log(owner);

DiamondCutFacet diamondCut = new DiamondCutFacet();
address diamondCutAddress = address(diamondCut);

DiamondInit diamondInit = new DiamondInit();
address diamondInitAddress = address(diamondInit);

ERC1155Facet erc1155Facet = new ERC1155Facet();
address erc1155FacetAddress = address(erc1155Facet);

DiamondLoupeFacet diamondLoupeFacet = new DiamondLoupeFacet();
address diamondLoupeFacetAddress = address(diamondLoupeFacet);

BondFacet bondFacet = new BondFacet();
address bondFacetAddress = address(bondFacet);

IDiamond.FacetCut[] memory cuts = new IDiamond.FacetCut[](3);
cuts[0] = IDiamond.FacetCut({
facetAddress: erc1155FacetAddress,
action: IDiamond.FacetCutAction.Add,
functionSelectors: erc1155Facet.getSelectors()
});

cuts[1] = IDiamond.FacetCut({
facetAddress: diamondLoupeFacetAddress,
action: IDiamond.FacetCutAction.Add,
functionSelectors: diamondLoupeFacet.getSelectors()
});

cuts[2] = IDiamond.FacetCut({
facetAddress: bondFacetAddress,
action: IDiamond.FacetCutAction.Add,
functionSelectors: bondFacet.getSelectors()
});

DiamondArgs memory da = DiamondArgs({
owner: owner,
init: diamondInitAddress,
initCalldata: abi.encodeWithSelector(bytes4(keccak256("init()")))
});

Diamond diamond = new Diamond(cuts, da);
address diamondAddress = address(diamond);

new GenericToken("GenericToken", "GT");

vm.stopBroadcast();
}
}
14 changes: 0 additions & 14 deletions src/Counter.sol

This file was deleted.

Loading

0 comments on commit fd69ee2

Please sign in to comment.