chore: integrate proxy (#8)
* forge install: openzeppelin-foundry-upgrades
v0.3.1
* forge install: openzeppelin-contracts-upgradeable
v5.0.2
* test: integrate transparent proxy
* test: patch
* fix ✅
* fix: adorno
* fix: add cardona deployment
* fix: broken test for upgrade
* fix: cleanup
* fix: cleanup
* fix: lint
* fix: remove upgrade from Deploy.s.sol
* fix: envCheck
This commit is contained in:
parent
5f0d62d52e
commit
48542f3f04
|
@ -8,4 +8,5 @@ export API_KEY_OPTIMISTIC_ETHERSCAN="YOUR_API_KEY_OPTIMISTIC_ETHERSCAN"
|
|||
export API_KEY_POLYGONSCAN="YOUR_API_KEY_POLYGONSCAN"
|
||||
export API_KEY_SNOWTRACE="YOUR_API_KEY_SNOWTRACE"
|
||||
export MNEMONIC="YOUR_MNEMONIC"
|
||||
export ETH_FROM="YOUR_ETH_ADDRESS"
|
||||
export FOUNDRY_PROFILE="default"
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
WakuRlnV2Test:test__IdCommitmentToMetadata__DoesntExist() (gas: 8299)
|
||||
WakuRlnV2Test:test__InvalidPaginationQuery__EndIndexGTIdCommitmentIndex() (gas: 13351)
|
||||
WakuRlnV2Test:test__InvalidPaginationQuery__StartIndexGTEndIndex() (gas: 11184)
|
||||
WakuRlnV2Test:test__InvalidRegistration__DuplicateIdCommitment() (gas: 111313)
|
||||
WakuRlnV2Test:test__InvalidRegistration__FullTree() (gas: 97043)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidIdCommitment__LargerThanField() (gas: 9926)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidIdCommitment__Zero() (gas: 9139)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidUserMessageLimit__LargerThanMax() (gas: 10147)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidUserMessageLimit__Zero() (gas: 9242)
|
||||
WakuRlnV2Test:test__ValidPaginationQuery(uint32) (runs: 1002, μ: 402088, ~: 136269)
|
||||
WakuRlnV2Test:test__ValidPaginationQuery__OneElement() (gas: 128461)
|
||||
WakuRlnV2Test:test__ValidRegistration(uint256,uint32) (runs: 1001, μ: 133518, ~: 133518)
|
||||
WakuRlnV2Test:test__ValidRegistration__kats() (gas: 108906)
|
||||
WakuRlnV2Test:test__IdCommitmentToMetadata__DoesntExist() (gas: 16723)
|
||||
WakuRlnV2Test:test__InvalidPaginationQuery__EndIndexGTIdCommitmentIndex() (gas: 18260)
|
||||
WakuRlnV2Test:test__InvalidPaginationQuery__StartIndexGTEndIndex() (gas: 16083)
|
||||
WakuRlnV2Test:test__InvalidRegistration__DuplicateIdCommitment() (gas: 99824)
|
||||
WakuRlnV2Test:test__InvalidRegistration__FullTree() (gas: 14343)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidIdCommitment__LargerThanField() (gas: 15258)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidIdCommitment__Zero() (gas: 14046)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidUserMessageLimit__LargerThanMax() (gas: 17639)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidUserMessageLimit__Zero() (gas: 14126)
|
||||
WakuRlnV2Test:test__Upgrade() (gas: 3668443)
|
||||
WakuRlnV2Test:test__ValidPaginationQuery(uint32) (runs: 1000, μ: 446587, ~: 159861)
|
||||
WakuRlnV2Test:test__ValidPaginationQuery__OneElement() (gas: 120064)
|
||||
WakuRlnV2Test:test__ValidRegistration(uint256,uint32) (runs: 1000, μ: 124674, ~: 124674)
|
||||
WakuRlnV2Test:test__ValidRegistration__kats() (gas: 96917)
|
|
@ -2,3 +2,9 @@
|
|||
branch = "v1"
|
||||
path = lib/forge-std
|
||||
url = https://github.com/foundry-rs/forge-std
|
||||
[submodule "lib/openzeppelin-foundry-upgrades"]
|
||||
path = lib/openzeppelin-foundry-upgrades
|
||||
url = https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades
|
||||
[submodule "lib/openzeppelin-contracts-upgradeable"]
|
||||
path = lib/openzeppelin-contracts-upgradeable
|
||||
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
# This script is used to assert if require env vars are present for deployment
|
||||
# RPC_URL: RPC URL for the network
|
||||
# ACCOUNT: Accessed with `cast wallet` command
|
||||
# ETH_FROM: Address to send transactions from
|
||||
# we need ETH_FROM because of the following bug:
|
||||
# https://github.com/foundry-rs/foundry/issues/7255
|
||||
|
||||
|
||||
if [ -z "$RPC_URL" ]; then
|
||||
echo "RPC_URL is required"
|
||||
|
@ -11,3 +15,8 @@ if [ -z "$ACCOUNT" ]; then
|
|||
echo "ACCOUNT is required"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$ETH_FROM" ]; then
|
||||
echo "ETH_FROM is required"
|
||||
exit 1
|
||||
fi
|
||||
|
|
12
foundry.toml
12
foundry.toml
|
@ -5,7 +5,7 @@
|
|||
block_timestamp = 1_680_220_800 # March 31, 2023 at 00:00 GMT
|
||||
bytecode_hash = "none"
|
||||
cbor_metadata = false
|
||||
evm_version = "paris"
|
||||
evm_version = "cancun"
|
||||
fuzz = { runs = 1_000 }
|
||||
gas_reports = ["*"]
|
||||
libs = ["lib"]
|
||||
|
@ -13,7 +13,7 @@
|
|||
optimizer_runs = 10_000
|
||||
out = "out"
|
||||
script = "script"
|
||||
solc = "0.8.19"
|
||||
solc = "0.8.24"
|
||||
src = "src"
|
||||
test = "test"
|
||||
|
||||
|
@ -27,6 +27,7 @@ max_test_rejects = 128_000
|
|||
[etherscan]
|
||||
mainnet = { key = "${API_KEY_ETHERSCAN}" }
|
||||
sepolia = { key = "${API_KEY_ETHERSCAN}" }
|
||||
2442 = { key = "${API_KEY_CARDONA}", url = "https://api-cardona-zkevm.polygonscan.com/api" }
|
||||
|
||||
[fmt]
|
||||
bracket_spacing = true
|
||||
|
@ -41,3 +42,10 @@ max_test_rejects = 128_000
|
|||
[rpc_endpoints]
|
||||
localhost = "http://localhost:8545"
|
||||
sepolia = "https://eth-sepolia.g.alchemy.com/v2/${API_KEY_ALCHEMY}"
|
||||
2442 = "https://rpc.cardona.zkevm-rpc.com"
|
||||
|
||||
[profile.sepolia]
|
||||
libraries = ["node_modules/@zk-kit/imt.sol/contracts/LazyIMT.sol:LazyIMT:0x22317F732AE9f9015b0866d03319a441FB42cd7f", "node_modules/poseidon-solidity/PoseidonT3.sol:PoseidonT3:0x4CF6285AC1E3ddAD6E1E378146CbCd3A6CA3Ed60"]
|
||||
|
||||
[profile.cardona]
|
||||
libraries = ["node_modules/@zk-kit/imt.sol/contracts/LazyIMT.sol:LazyIMT:0x8176F5f2A49cDBcCB46487D9C839c45D0200A270", "node_modules/poseidon-solidity/PoseidonT3.sol:PoseidonT3:0x99419DF6428Bad6Fe117513129FACaD4864afdcF"]
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 74cfb77e308dd188d2f58864aaf44963ae6b88b1
|
||||
Subproject commit 978ac6fadb62f5f0b723c996f64be52eddba6801
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 0a71a5ebfbf4136cae3176e5cc9bcc5efc23f76b
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 4cd15fc50b141c77d8cc9ff8efb44d00e841a299
|
|
@ -34,7 +34,8 @@
|
|||
"gas-report": "forge test --gas-report 2>&1 | (tee /dev/tty | awk '/Test result:/ {found=1; buffer=\"\"; next} found && !/Ran/ {buffer=buffer $0 ORS} /Ran/ {found=0} END {printf \"%s\", buffer}' > .gas-report)",
|
||||
"release": "commit-and-tag-version",
|
||||
"adorno": "pnpm prettier:write && forge fmt && forge snapshot && pnpm gas-report",
|
||||
"deploy:sepolia": "./envCheck.sh && forge script --chain sepolia script/Deploy.s.sol:Deploy --rpc-url $RPC_URL --broadcast --verify -vv --account $ACCOUNT --legacy",
|
||||
"deploy:localhost": "./envCheck.sh && forge script script/Deploy.s.sol:Deploy --rpc-url $RPC_URL --broadcast -vv --account $ACCOUNT"
|
||||
"deploy:sepolia": "./envCheck.sh && FOUNDRY_PROFILE=sepolia forge script --chain sepolia script/Deploy.s.sol:Deploy --rpc-url $RPC_URL --broadcast --verify -vv --account $ACCOUNT --legacy --sender $ETH_FROM",
|
||||
"deploy:cardona": "./envCheck.sh && FOUNDRY_PROFILE=cardona forge script --chain 2442 script/Deploy.s.sol:Deploy --rpc-url https://rpc.cardona.zkevm-rpc.com --broadcast --verify -vv --account $ACCOUNT --legacy --sender $ETH_FROM",
|
||||
"deploy:localhost": "./envCheck.sh && forge script script/Deploy.s.sol:Deploy --rpc-url $RPC_URL --broadcast -vv --account $ACCOUNT --sender $ETH_FROM"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
forge-std/=lib/forge-std/src/
|
||||
@zk-kit/imt.sol/=node_modules/@zk-kit/imt.sol/contracts
|
||||
poseidon-solidity/=node_modules/poseidon-solidity/
|
||||
@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/
|
||||
@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/
|
||||
|
|
|
@ -2,11 +2,33 @@
|
|||
pragma solidity >=0.8.19 <=0.9.0;
|
||||
|
||||
import { WakuRlnV2 } from "../src/WakuRlnV2.sol";
|
||||
import { PoseidonT3 } from "poseidon-solidity/PoseidonT3.sol";
|
||||
import { LazyIMT } from "@zk-kit/imt.sol/LazyIMT.sol";
|
||||
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
|
||||
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
||||
|
||||
import { BaseScript } from "./Base.s.sol";
|
||||
import { DeploymentConfig } from "./DeploymentConfig.s.sol";
|
||||
|
||||
contract Deploy is BaseScript {
|
||||
function run() public broadcast returns (WakuRlnV2 w) {
|
||||
w = new WakuRlnV2(20);
|
||||
function run() public broadcast returns (WakuRlnV2 w, address impl) {
|
||||
impl = address(new WakuRlnV2());
|
||||
bytes memory data = abi.encodeCall(WakuRlnV2.initialize, (msg.sender, 20));
|
||||
address proxy = address(new ERC1967Proxy(impl, data));
|
||||
w = WakuRlnV2(proxy);
|
||||
}
|
||||
}
|
||||
|
||||
contract DeployLibs is BaseScript {
|
||||
function run() public broadcast returns (address poseidonT3, address lazyImt) {
|
||||
bytes memory poseidonT3Bytecode = type(PoseidonT3).creationCode;
|
||||
assembly {
|
||||
poseidonT3 := create(0, add(poseidonT3Bytecode, 0x20), mload(poseidonT3Bytecode))
|
||||
}
|
||||
|
||||
bytes memory lazyImtBytecode = type(LazyIMT).creationCode;
|
||||
assembly {
|
||||
lazyImt := create(0, add(lazyImtBytecode, 0x20), mload(lazyImtBytecode))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity 0.8.19;
|
||||
pragma solidity 0.8.24;
|
||||
|
||||
import { LazyIMT, LazyIMTData } from "@zk-kit/imt.sol/LazyIMT.sol";
|
||||
import { PoseidonT3 } from "poseidon-solidity/PoseidonT3.sol";
|
||||
|
||||
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
|
||||
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
||||
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
||||
|
||||
/// The tree is full
|
||||
error FullTree();
|
||||
|
||||
|
@ -20,22 +23,22 @@ error InvalidUserMessageLimit(uint32 messageLimit);
|
|||
/// Invalid pagination query
|
||||
error InvalidPaginationQuery(uint256 startIndex, uint256 endIndex);
|
||||
|
||||
contract WakuRlnV2 {
|
||||
contract WakuRlnV2 is Initializable, OwnableUpgradeable, UUPSUpgradeable {
|
||||
/// @notice The Field
|
||||
uint256 public constant Q =
|
||||
21_888_242_871_839_275_222_246_405_745_257_275_088_548_364_400_416_034_343_698_204_186_575_808_495_617;
|
||||
|
||||
/// @notice The max message limit per epoch
|
||||
uint32 public immutable MAX_MESSAGE_LIMIT;
|
||||
uint32 public MAX_MESSAGE_LIMIT;
|
||||
|
||||
/// @notice The depth of the merkle tree
|
||||
uint8 public constant DEPTH = 20;
|
||||
|
||||
/// @notice The size of the merkle tree, i.e 2^depth
|
||||
uint32 public immutable SET_SIZE;
|
||||
uint32 public SET_SIZE;
|
||||
|
||||
/// @notice The index of the next member to be registered
|
||||
uint32 public idCommitmentIndex = 0;
|
||||
uint32 public idCommitmentIndex;
|
||||
|
||||
/// @notice the membership metadata of the member
|
||||
struct MembershipInfo {
|
||||
|
@ -49,7 +52,7 @@ contract WakuRlnV2 {
|
|||
mapping(uint256 => MembershipInfo) public memberInfo;
|
||||
|
||||
/// @notice the deployed block number
|
||||
uint32 public immutable deployedBlockNumber;
|
||||
uint32 public deployedBlockNumber;
|
||||
|
||||
/// @notice the stored imt data
|
||||
LazyIMTData public imtData;
|
||||
|
@ -74,14 +77,22 @@ contract WakuRlnV2 {
|
|||
_;
|
||||
}
|
||||
|
||||
/// @notice the constructor of the contract
|
||||
constructor(uint32 maxMessageLimit) {
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
}
|
||||
|
||||
function initialize(address initialOwner, uint32 maxMessageLimit) public initializer {
|
||||
__Ownable_init(initialOwner);
|
||||
__UUPSUpgradeable_init();
|
||||
MAX_MESSAGE_LIMIT = maxMessageLimit;
|
||||
SET_SIZE = uint32(1 << DEPTH);
|
||||
deployedBlockNumber = uint32(block.number);
|
||||
LazyIMT.init(imtData, DEPTH);
|
||||
idCommitmentIndex = 0;
|
||||
}
|
||||
|
||||
function _authorizeUpgrade(address newImplementation) internal override onlyOwner { } // solhint-disable-line
|
||||
|
||||
/// @notice Checks if a commitment is valid
|
||||
/// @param idCommitment The idCommitment of the member
|
||||
/// @return true if the commitment is valid, false otherwise
|
||||
|
|
|
@ -2,25 +2,22 @@
|
|||
pragma solidity >=0.8.19 <0.9.0;
|
||||
|
||||
import { Test } from "forge-std/Test.sol";
|
||||
import { stdStorage, StdStorage } from "forge-std/Test.sol";
|
||||
|
||||
import { Deploy } from "../script/Deploy.s.sol";
|
||||
import { DeploymentConfig } from "../script/DeploymentConfig.s.sol";
|
||||
import "../src/WakuRlnV2.sol";
|
||||
import "../src/WakuRlnV2.sol"; // solhint-disable-line
|
||||
import { PoseidonT3 } from "poseidon-solidity/PoseidonT3.sol";
|
||||
import { LazyIMT } from "@zk-kit/imt.sol/LazyIMT.sol";
|
||||
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
||||
|
||||
contract WakuRlnV2Test is Test {
|
||||
using stdStorage for StdStorage;
|
||||
|
||||
WakuRlnV2 internal w;
|
||||
address internal impl;
|
||||
DeploymentConfig internal deploymentConfig;
|
||||
|
||||
address internal deployer;
|
||||
|
||||
function setUp() public virtual {
|
||||
Deploy deployment = new Deploy();
|
||||
w = deployment.run();
|
||||
(w, impl) = deployment.run();
|
||||
}
|
||||
|
||||
function test__ValidRegistration__kats() external {
|
||||
|
@ -90,7 +87,7 @@ contract WakuRlnV2Test is Test {
|
|||
assertEq(fetchedRateCommitment, rateCommitment);
|
||||
}
|
||||
|
||||
function test__IdCommitmentToMetadata__DoesntExist() external {
|
||||
function test__IdCommitmentToMetadata__DoesntExist() external view {
|
||||
uint256 idCommitment = 2;
|
||||
(uint32 userMessageLimit, uint32 index, uint256 rateCommitment) = w.idCommitmentToMetadata(idCommitment);
|
||||
assertEq(userMessageLimit, 0);
|
||||
|
@ -137,7 +134,18 @@ contract WakuRlnV2Test is Test {
|
|||
function test__InvalidRegistration__FullTree() external {
|
||||
uint32 userMessageLimit = 2;
|
||||
// we progress the tree to the last leaf
|
||||
stdstore.target(address(w)).sig("idCommitmentIndex()").checked_write(1 << w.DEPTH());
|
||||
/*| Name | Type | Slot | Offset | Bytes |
|
||||
|---------------------|-----------------------------------------------------|------|--------|-------|
|
||||
| MAX_MESSAGE_LIMIT | uint32 | 0 | 0 | 4 |
|
||||
| SET_SIZE | uint32 | 0 | 4 | 4 |
|
||||
| idCommitmentIndex | uint32 | 0 | 8 | 4 |
|
||||
| memberInfo | mapping(uint256 => struct WakuRlnV2.MembershipInfo) | 1 | 0 | 32 |
|
||||
| deployedBlockNumber | uint32 | 2 | 0 | 4 |
|
||||
| imtData | struct LazyIMTData | 3 | 0 | 64 |*/
|
||||
// we set MAX_MESSAGE_LIMIT to 20 (unaltered)
|
||||
// we set SET_SIZE to 4294967295 (1 << 20) (unaltered)
|
||||
// we set idCommitmentIndex to 4294967295 (1 << 20) (altered)
|
||||
vm.store(address(w), bytes32(0), 0x0000000000000000000000000000000000000000ffffffffffffffff00000014);
|
||||
vm.expectRevert(FullTree.selector);
|
||||
w.register(1, userMessageLimit);
|
||||
}
|
||||
|
@ -179,4 +187,18 @@ contract WakuRlnV2Test is Test {
|
|||
assertEq(commitments[i], rateCommitment);
|
||||
}
|
||||
}
|
||||
|
||||
function test__Upgrade() external {
|
||||
address newImplementation = address(new WakuRlnV2());
|
||||
bytes memory data;
|
||||
UUPSUpgradeable(address(w)).upgradeToAndCall(newImplementation, data);
|
||||
// ensure that the implementation is set correctly
|
||||
// ref:
|
||||
// solhint-disable-next-line
|
||||
// https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades/blob/4cd15fc50b141c77d8cc9ff8efb44d00e841a299/src/internal/Core.sol#L289
|
||||
address fetchedImpl = address(
|
||||
uint160(uint256(vm.load(address(w), 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc)))
|
||||
);
|
||||
assertEq(fetchedImpl, newImplementation);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue