Skip to content

Commit fa8c1de

Browse files
authored
feat(protocol-contracts): add upgradeable ERC7984 wrapper extension (#1628)
1 parent 2223651 commit fa8c1de

34 files changed

+14362
-341
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Run tests
2+
name: protocol-contracts-confidential-wrapper-upgradeable-tests
3+
4+
on:
5+
pull_request:
6+
7+
push:
8+
branches:
9+
- main
10+
workflow_dispatch:
11+
12+
permissions: {}
13+
14+
concurrency:
15+
group: ci-protocol-contracts-confidential-wrapper-upgradeable-tests-${{ github.ref }}
16+
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
17+
18+
jobs:
19+
check-changes:
20+
name: protocol-contracts-confidential-wrapper-upgradeable-tests/check-changes
21+
permissions:
22+
actions: 'read' # Required to read workflow run information
23+
contents: 'read' # Required to checkout repository code
24+
pull-requests: 'read' # Required to read pull request information
25+
runs-on: ubuntu-latest
26+
outputs:
27+
changes-protocol-contracts-confidential-wrapper-upgradeable: ${{ steps.filter.outputs.protocol-contracts-confidential-wrapper-upgradeable }}
28+
steps:
29+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
30+
with:
31+
persist-credentials: 'false'
32+
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
33+
id: filter
34+
with:
35+
filters: |
36+
protocol-contracts-confidential-wrapper-upgradeable:
37+
- .github/workflows/protocol-contracts-confidential-wrapper-upgradeable-tests.yml
38+
- protocol-contracts/confidential-wrapper-upgradeable/**
39+
tests:
40+
name: protocol-contracts-confidential-wrapper-upgradeable-tests/tests (bpr)
41+
needs: check-changes
42+
if: ${{ needs.check-changes.outputs.changes-protocol-contracts-confidential-wrapper-upgradeable == 'true' }}
43+
runs-on: ubuntu-latest
44+
permissions:
45+
contents: 'read' # Required to checkout repository code
46+
steps:
47+
- name: Checkout project
48+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
49+
with:
50+
persist-credentials: 'false'
51+
52+
- name: Install dependencies
53+
working-directory: protocol-contracts/confidential-wrapper-upgradeable
54+
run: npm ci
55+
56+
- name: Run lint
57+
working-directory: protocol-contracts/confidential-wrapper-upgradeable
58+
run: make conformance
59+
60+
- name: Run unit tests
61+
working-directory: protocol-contracts/confidential-wrapper-upgradeable
62+
run: make test
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Authentication (use one of these)
2+
MNEMONIC=
3+
PRIVATE_KEY=
4+
5+
# RPC URLs
6+
MAINNET_RPC_URL=
7+
SEPOLIA_RPC_URL=
8+
9+
# API Keys
10+
ETHERSCAN_API_KEY=
11+
12+
# Gas Reporter
13+
REPORT_GAS=false
14+
15+
# ----------------------------------------------------------------------------
16+
# ConfidentialWrapper deployment
17+
# ----------------------------------------------------------------------------
18+
19+
NUM_CONFIDENTIAL_WRAPPERS=1
20+
21+
# Confidential Wrapper 1
22+
CONFIDENTIAL_WRAPPER_NAME_0="Confidential Token Test 1" # (string)
23+
CONFIDENTIAL_WRAPPER_SYMBOL_0="cTEST1" # (string)
24+
CONFIDENTIAL_WRAPPER_CONTRACT_URI_0='data:application/json;utf8,{"name":"Confidential Token Test 1","symbol":"cTEST1","description":"Confidential wrapper of TEST1 shielding it into a confidential token"}' # (string)
25+
CONFIDENTIAL_WRAPPER_UNDERLYING_ADDRESS_0=0x0000111122223333444455556666777788889999 # (address)
26+
CONFIDENTIAL_WRAPPER_OWNER_ADDRESS_0=0x70997970C51812dc3A010C7d01b50e0d17dc79C8 # accounts[1] (address)
27+
28+
# Confidential Wrapper 2
29+
CONFIDENTIAL_WRAPPER_NAME_0="Confidential Token Test 2" # (string)
30+
CONFIDENTIAL_WRAPPER_SYMBOL_0="cTEST2" # (string)
31+
CONFIDENTIAL_WRAPPER_CONTRACT_URI_0='data:application/json;utf8,{"name":"Confidential Token Test 2","symbol":"cTEST2","description":"Confidential wrapper of TEST2 shielding it into a confidential token"}' # (string)
32+
CONFIDENTIAL_WRAPPER_UNDERLYING_ADDRESS_0=0x0000111122223333444455556666777788889999 # (address)
33+
CONFIDENTIAL_WRAPPER_OWNER_ADDRESS_0=0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC # accounts[2] (address)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Dependencies
2+
node_modules/
3+
4+
# Build artifacts
5+
artifacts/
6+
cache/
7+
cache_forge/
8+
out/
9+
types/
10+
contracts-exposed/
11+
12+
# Coverage
13+
coverage/
14+
coverage.json
15+
16+
# Environment
17+
.env
18+
.env.local
19+
.env.*.local
20+
21+
# IDE
22+
.idea/
23+
.vscode/
24+
*.swp
25+
*.swo
26+
.DS_Store
27+
28+
# Logs
29+
*.log
30+
npm-debug.log*
31+
32+
# Deployment artifacts (keep deployments folder but ignore specific networks if needed)
33+
# deployments/
34+
35+
# Typechain
36+
typechain-types/
37+
38+
# Hardhat
39+
.openzeppelin/
40+
41+
# Foundry
42+
broadcast/
43+
44+
# Fhevm
45+
fhevmTemp/
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# directories
2+
.coverage_artifacts
3+
.coverage_cache
4+
.coverage_contracts
5+
artifacts
6+
build
7+
cache
8+
coverage
9+
dist
10+
node_modules
11+
types
12+
lib
13+
14+
# files
15+
*.env
16+
*.log
17+
.DS_Store
18+
.pnp.*
19+
coverage.json
20+
package-lock.json
21+
yarn.lock
22+
README.md
23+
fhevmTemp
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"printWidth": 120,
3+
"singleQuote": true,
4+
"trailingComma": "all",
5+
"arrowParens": "avoid",
6+
"overrides": [
7+
{
8+
"files": "*.sol",
9+
"options": {
10+
"singleQuote": false
11+
}
12+
}
13+
],
14+
"plugins": ["prettier-plugin-solidity"]
15+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
include .env.example
2+
3+
ENV_PATH=.env.example
4+
5+
prettier:
6+
npx prettier . --write
7+
8+
lint:
9+
npm run lint
10+
11+
compile:
12+
npx hardhat compile
13+
14+
clean:
15+
npx hardhat clean
16+
17+
get-accounts:
18+
DOTENV_CONFIG_PATH=$(ENV_PATH) npx hardhat get-accounts
19+
20+
# Define it as a phony target to avoid conflicts with the test directory
21+
.PHONY: test
22+
test: clean
23+
DOTENV_CONFIG_PATH=$(ENV_PATH) npx hardhat test --network hardhat $(if $(GREP),--grep '$(GREP)',)
24+
25+
test-tasks: clean
26+
DOTENV_CONFIG_PATH=$(ENV_PATH) npx hardhat test:tasks --network hardhat $(if $(GREP),--grep '$(GREP)',)
27+
28+
# Conform to pre-commit checks
29+
conformance: prettier lint
30+
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// SPDX-License-Identifier: BSD-3-Clause-Clear
2+
pragma solidity ^0.8.27;
3+
4+
import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
5+
import {ERC7984ERC20WrapperUpgradeable} from "./extensions/ERC7984ERC20WrapperUpgradeable.sol";
6+
import {ZamaEthereumConfigUpgradeable} from "./fhevm/ZamaEthereumConfigUpgradeable.sol";
7+
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
8+
import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
9+
10+
/**
11+
* @title ConfidentialWrapper
12+
* @dev An upgradeable wrapper contract built on top of {ERC7984Upgradeable} that allows wrapping an `ERC20` token
13+
* into an `ERC7984` token. The wrapper contract implements the `IERC1363Receiver` interface
14+
* which allows users to transfer `ERC1363` tokens directly to the wrapper with a callback to wrap the tokens.
15+
*
16+
* WARNING: Minting assumes the full amount of the underlying token transfer has been received, hence some non-standard
17+
* tokens such as fee-on-transfer or other deflationary-type tokens are not supported by this wrapper.
18+
*/
19+
contract ConfidentialWrapper is
20+
ERC7984ERC20WrapperUpgradeable,
21+
ZamaEthereumConfigUpgradeable,
22+
UUPSUpgradeable,
23+
Ownable2StepUpgradeable
24+
{
25+
/// @custom:oz-upgrades-unsafe-allow constructor
26+
constructor() {
27+
_disableInitializers();
28+
}
29+
30+
function initialize(
31+
string memory name_,
32+
string memory symbol_,
33+
string memory contractURI_,
34+
IERC20 underlying_,
35+
address owner_
36+
) public initializer {
37+
__ERC7984_init(name_, symbol_, contractURI_);
38+
__ERC7984ERC20Wrapper_init(underlying_);
39+
__ZamaEthereumConfig_init();
40+
__Ownable_init(owner_);
41+
__Ownable2Step_init();
42+
}
43+
44+
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
45+
}

0 commit comments

Comments
 (0)