Skip to content

Commit

Permalink
Merge pull request #9 from juliopavila/feature/zodiac-core
Browse files Browse the repository at this point in the history
Feat: Migration to Zodiac Core and Task Improvements in the Connext Mod
  • Loading branch information
samepant authored Sep 16, 2024
2 parents b29f5d8 + 4634aed commit 9cc1fe3
Show file tree
Hide file tree
Showing 20 changed files with 3,903 additions and 8,142 deletions.
6 changes: 3 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
ETHERSCAN_API_KEY=ABC123ABC123ABC123ABC123ABC123ABC1
RINKEBY_URL=https://eth-ropsten.alchemyapi.io/v2/<YOUR ALCHEMY KEY>
PRIVATE_KEY=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1
MNEMONIC=
INFURA_KEY=
ETHERSCAN_API_KEY=
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16
node-version: 20
- uses: actions/cache@v2
with:
path: "**/node_modules"
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ typechain
.devcontainer
out
.vscode

build
#Hardhat files
cache
artifacts
Expand Down
19 changes: 10 additions & 9 deletions contracts/ConnextModule.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.15;

import "@gnosis.pm/zodiac/contracts/core/Module.sol";
import "@gnosis-guild/zodiac-core/contracts/core/Module.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IXReceiver} from "./interfaces/IXReceiver.sol";

contract ConnextModule is Module, IXReceiver {
using SafeERC20 for IERC20;

event ModuleSetUp(
address owner,
address avatar,
Expand Down Expand Up @@ -54,7 +54,6 @@ contract ConnextModule is Module, IXReceiver {
/// @param initializeParams ABI encoded initialization params, in the same order as the parameters for this contract's constructor.
/// @notice Only callable once.
function setUp(bytes memory initializeParams) public override initializer {
__Ownable_init();
(
address _owner,
address _avatar,
Expand All @@ -64,12 +63,16 @@ contract ConnextModule is Module, IXReceiver {
address _connext
) = abi.decode(initializeParams, (address, address, address, address, uint32, address));

require(_avatar != address(0), "Avatar can not be zero address");
require(_target != address(0), "Target can not be zero address");

__Ownable_init(msg.sender);
setAvatar(_avatar);
setTarget(_target);
setOriginSender(_originSender);
setOrigin(_origin);
setConnext(_connext);
transferOwnership(_owner);
_transferOwnership(_owner);

emit ModuleSetUp(owner(), avatar, target, originSender, origin, connext);
}
Expand Down Expand Up @@ -98,9 +101,7 @@ contract ConnextModule is Module, IXReceiver {
address _originSender,
uint32 _origin,
bytes memory _callData
)
external override onlyConnext(_originSender, _origin)
returns (bytes memory) {
) external override onlyConnext(_originSender, _origin) returns (bytes memory) {
// Decode message
(address _to, uint256 _value, bytes memory _data, Enum.Operation _operation) = abi.decode(
_callData,
Expand All @@ -109,11 +110,11 @@ contract ConnextModule is Module, IXReceiver {

// Approve token transfer if tokens were passed in
IERC20 _token = IERC20(_asset);
if(_amount > 0) _token.safeTransfer(avatar, _amount);
if (_amount > 0) _token.safeTransfer(avatar, _amount);

// Execute transaction against target
(bool success, bytes memory returnData) = execAndReturnData(_to, _value, _data, _operation);
if(!success) revert ModuleTransactionFailed();
if (!success) revert ModuleTransactionFailed();
return returnData;
}

Expand Down
3 changes: 2 additions & 1 deletion contracts/test/Button.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.15;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract Button is Ownable {
event ButtonPushed(uint8 pushes, address pusher);

uint8 public pushes;

constructor() Ownable(msg.sender) {}

// UpdateGreeting updates the public greeting variable if test tokens are paid to the contract
function push() public {
Expand Down
2 changes: 1 addition & 1 deletion contracts/test/TestFactory.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0;

import "@gnosis.pm/zodiac/contracts/factory/ModuleProxyFactory.sol";
import "@gnosis-guild/zodiac-core/contracts/factory/ModuleProxyFactory.sol";
64 changes: 42 additions & 22 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,52 @@
import * as dotenv from "dotenv"

import { HardhatUserConfig } from "hardhat/config"
import "@nomiclabs/hardhat-etherscan"
import "@nomiclabs/hardhat-ethers"
import "@nomiclabs/hardhat-waffle"
import "@typechain/hardhat"
import "hardhat-gas-reporter"
import "solidity-coverage"
import "hardhat-deploy"
import "./tasks/setup"
import "@nomicfoundation/hardhat-toolbox"
import "@nomicfoundation/hardhat-verify"
import "@nomicfoundation/hardhat-ethers"
import 'hardhat-gas-reporter'

import dotenv from 'dotenv'
import { HttpNetworkUserConfig } from 'hardhat/types'

dotenv.config()

import "./tasks/extract-mastercopy"
import "./tasks/deploy-mastercopies"
import "./tasks/deploy-mastercopy"
import "./tasks/verify-mastercopies"
import "./tasks/verify-mastercopy"

const { MNEMONIC } = process.env

const sharedNetworkConfig: HttpNetworkUserConfig = {
accounts: {
mnemonic: MNEMONIC || "candy maple cake sugar pudding cream honey rich smooth crumble sweet treat",
},
}

const config: HardhatUserConfig = {
solidity: "0.8.15",
paths: {
artifacts: "build/artifacts",
cache: "build/cache",
sources: "contracts",
},
solidity: {
compilers: [{ version: "0.8.20" }, { version: "0.8.15" }, { version: "0.8.0" }],
},
networks: {
rinkeby: {
url: process.env.RINKEBY_URL || "",
accounts: process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [],
deploy: ["deploy/mastercopy-proxy"], // deploy via mastercopy and a proxy
hardhat: {
allowUnlimitedContractSize: true,
blockGasLimit: 100000000,
gas: 100000000,
},
mainnet: {
...sharedNetworkConfig,
url: `https://mainnet.infura.io/v3/${process.env.INFURA_KEY}`,
},
sepolia: {
...sharedNetworkConfig,
url: `https://sepolia.infura.io/v3/${process.env.INFURA_KEY}`,
},
},
namedAccounts: {
deployer: 0,
dependenciesDeployer: 1,
tester: 2,
},
gasReporter: {
enabled: process.env.REPORT_GAS !== undefined,
Expand All @@ -32,9 +55,6 @@ const config: HardhatUserConfig = {
etherscan: {
apiKey: process.env.ETHERSCAN_API_KEY,
},
paths: {
deploy: "deploy/raw", // normal deployment
},
}

export default config
1,199 changes: 1,199 additions & 0 deletions mastercopies.json

Large diffs are not rendered by default.

65 changes: 36 additions & 29 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zodiac-module-connext",
"version": "1.0.0",
"version": "1.1.0",
"description": "A module for controlling safes via connext.",
"repository": {
"type": "git",
Expand All @@ -9,7 +9,11 @@
"scripts": {
"build": "hardhat compile",
"coverage": "hardhat coverage",
"deployMasterCopy": "hardhat deployMasterCopy",
"extract:mastercopy": "yarn run build && yarn hardhat extract:mastercopy",
"deploy:mastercopies": "yarn hardhat deploy:mastercopies --network",
"deploy:mastercopy": "yarn hardhat deploy:mastercopy --network",
"verify:mastercopies": "yarn hardhat verify:mastercopies --network",
"verify:mastercopy": "yarn hardhat verify:mastercopy --network",
"test": "hardhat test",
"setup": "hardhat setup"
},
Expand All @@ -25,40 +29,43 @@
},
"homepage": "https://github.com/gnosis/zodiac-module-connext",
"devDependencies": {
"@gnosis.pm/zodiac": "^2.0.1",
"@nomiclabs/hardhat-ethers": "^2.2.0",
"@nomiclabs/hardhat-etherscan": "^3.1.1",
"@nomiclabs/hardhat-waffle": "^2.0.3",
"@typechain/ethers-v5": "^10.1.1",
"@typechain/hardhat": "^6.1.4",
"@gnosis-guild/zodiac-core": "^2.0.3",
"@nomicfoundation/hardhat-chai-matchers": "^2.0.7",
"@nomicfoundation/hardhat-ethers": "^3.0.6",
"@nomicfoundation/hardhat-ignition": "^0.15.5",
"@nomicfoundation/hardhat-ignition-ethers": "^0.15.5",
"@nomicfoundation/hardhat-network-helpers": "^1.0.11",
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
"@nomicfoundation/hardhat-verify": "^2.0.0",
"@nomicfoundation/ignition-core": "^0.15.5",
"@typechain/ethers-v6": "^0.5.1",
"@typechain/hardhat": "^9.1.0",
"@types/chai": "^4.3.3",
"@types/mocha": "^10.0.0",
"@types/node": "^18.8.5",
"@typescript-eslint/eslint-plugin": "^5.12.0",
"@typescript-eslint/parser": "^5.16.0",
"chai": "^4.3.6",
"@types/mocha": "^10.0.7",
"@types/node": "^22.1.0",
"@typescript-eslint/eslint-plugin": "^8.0.1",
"@typescript-eslint/parser": "^8.0.1",
"chai": "^4.3.7",
"dotenv": "^16.0.3",
"eslint": "^8.12.0",
"eslint-config-prettier": "^8.5.0",
"eslint": "^9.8.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard": "^16.0.3",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-promise": "^6.0.0",
"ethereum-waffle": "^3.4.4",
"ethers": "^5.7.1",
"hardhat": "^2.9.2",
"hardhat-deploy": "^0.11.4",
"hardhat-gas-reporter": "^1.0.8",
"prettier": "^2.6.1",
"prettier-plugin-solidity": "^1.0.0-beta.19",
"solhint": "^3.3.7",
"solidity-coverage": "^0.7.20",
"ts-node": "^10.7.0",
"typechain": "^8.0.0",
"typescript": "^4.6.3"
"ethers": "^6.13.2",
"hardhat": "^2.22.8",
"hardhat-gas-reporter": "^2.2.0",
"prettier": "^3.3.3",
"prettier-plugin-solidity": "^1.3.1",
"solhint": "^5.0.3",
"solidity-coverage": "^0.8.12",
"ts-node": "^10.9.2",
"typechain": "^8.3.2",
"typescript": "^5.5.4"
},
"dependencies": {
"@openzeppelin/contracts": "^4.3.2"
"@openzeppelin/contracts": "^5.0.2"
}
}
16 changes: 16 additions & 0 deletions tasks/create-EIP1193.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { EIP1193Provider } from "@gnosis-guild/zodiac-core"
import { Signer } from "ethers"
import { EthereumProvider } from "hardhat/types"

export function createEIP1193(provider: EthereumProvider, signer: Signer): EIP1193Provider {
return {
request: async ({ method, params }) => {
if (method == "eth_sendTransaction") {
const { hash } = await signer.sendTransaction((params as any[])[0])
return hash
}

return provider.request({ method, params })
},
}
}
44 changes: 44 additions & 0 deletions tasks/deploy-mastercopies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { task } from 'hardhat/config'

import { readMastercopies, deployMastercopy } from '@gnosis-guild/zodiac-core'
import { createEIP1193 } from './create-EIP1193'

task(
'deploy:mastercopies',
'For every version entry on the artifacts file, deploys a mastercopy into the current network'
).setAction(async (_, hre) => {
const [signer] = await hre.ethers.getSigners()
const provider = createEIP1193(hre.network.provider, signer)
for (const mastercopy of readMastercopies()) {
const {
contractName,
contractVersion,
factory,
bytecode,
constructorArgs,
salt,
} = mastercopy

const { address, noop } = await deployMastercopy({
factory,
bytecode,
constructorArgs,
salt,
provider,
onStart: () => {
console.log(
`⏳ ${contractName}@${contractVersion}: Deployment starting...`
)
},
})
if (noop) {
console.log(
`🔄 ${contractName}@${contractVersion}: Already deployed at ${address}`
)
} else {
console.log(
`🚀 ${contractName}@${contractVersion}: Successfully deployed at ${address}`
)
}
}
})
38 changes: 38 additions & 0 deletions tasks/deploy-mastercopy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { task, types } from "hardhat/config"

import { deployMastercopy, readMastercopies } from "@gnosis-guild/zodiac-core"
import { createEIP1193 } from "./create-EIP1193"

task(
"deploy:mastercopy",
"For every version entry on the artifacts file, deploys a mastercopy into the current network",
)
.addOptionalParam(
"contractVersion",
"The specific version of the contract to deploy",
"latest", // Default value
types.string,
)
.setAction(async ({ contractVersion }, hre) => {
const [signer] = await hre.ethers.getSigners()
const provider = createEIP1193(hre.network.provider, signer)

for (const mastercopy of readMastercopies({ contractVersion })) {
const { contractName, contractVersion, factory, bytecode, constructorArgs, salt } = mastercopy
const { address, noop } = await deployMastercopy({
factory,
bytecode,
constructorArgs,
salt,
provider,
onStart: () => {
console.log(`⏳ ${contractName}@${contractVersion}: Deployment starting...`)
},
})
if (noop) {
console.log(`🔄 ${contractName}@${contractVersion}: Already deployed at ${address}`)
} else {
console.log(`🚀 ${contractName}@${contractVersion}: Successfully deployed at ${address}`)
}
}
})
Loading

0 comments on commit 9cc1fe3

Please sign in to comment.