Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Hardhat Tutorials to Use Hardhat Ignition Modules #902

Merged
merged 30 commits into from Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b6c27bb
update builders hardhat docs
themacexpert Apr 9, 2024
1b941e1
additions
themacexpert Apr 9, 2024
1ae93dd
tutorial revisions
themacexpert Apr 9, 2024
3dda7c9
additions and more
themacexpert Apr 9, 2024
2dce2a5
rev
themacexpert Apr 9, 2024
eef1773
run grammarly
themacexpert Apr 9, 2024
52f4e38
update all terminal screenshots
themacexpert Apr 9, 2024
53b9843
remove old images
themacexpert Apr 10, 2024
c559890
updates to hardhat tut
themacexpert Apr 10, 2024
159c803
Update tutorials/eth-api/hardhat-start-to-end.md
themacexpert Apr 11, 2024
93f8a4c
Update .snippets/code/builders/pallets-precompiles/precompiles/stakin…
themacexpert Apr 11, 2024
def827c
Update builders/build/eth-api/dev-env/hardhat.md
themacexpert Apr 11, 2024
414fb8f
Update builders/build/eth-api/dev-env/hardhat.md
themacexpert Apr 11, 2024
7d1080c
Update builders/build/eth-api/dev-env/hardhat.md
themacexpert Apr 11, 2024
44d6ced
feedback revs
themacexpert Apr 11, 2024
f51400d
restore images to not break CN site
themacexpert Apr 11, 2024
3d88f09
remove punctuation
themacexpert Apr 11, 2024
ae1e304
feedback revisions
themacexpert Apr 11, 2024
a9bd7b9
clarifications:
themacexpert Apr 11, 2024
5faf427
update hardhat tutorial
themacexpert Apr 13, 2024
f410b46
Update .snippets/code/tutorials/eth-api/hardhat-start-to-end/terminal…
themacexpert Apr 18, 2024
6eed3e9
Update .snippets/code/tutorials/eth-api/hardhat-start-to-end/terminal…
themacexpert Apr 18, 2024
6864789
Update tutorials/eth-api/hardhat-start-to-end.md
themacexpert Apr 18, 2024
eef0a71
insert your name
themacexpert Apr 18, 2024
b0af360
additions
themacexpert Apr 18, 2024
2afac6a
rev
themacexpert Apr 18, 2024
57fbaf5
run prettier on everything
themacexpert Apr 18, 2024
329986c
Update .snippets/code/tutorials/eth-api/hardhat-start-to-end/dao-js-t…
themacexpert Apr 22, 2024
836bf87
Update tutorials/eth-api/hardhat-start-to-end.md
themacexpert Apr 22, 2024
d4c8265
remove prettier
themacexpert Apr 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,13 @@
<div id="termynal" data-termynal>
<span data-ty="input"><span class="file-path"></span>npx hardhat compile</span>
<span data-ty>Compiled 1 Solidity files successfully (evm target: paris).</span>
<span data-ty="input"><span class="file-path"></span>ls -l</span>
<span data-ty>artifacts</span>
<span data-ty>cache</span>
<span data-ty>contracts</span>
<span data-ty>hardhat.config.js</span>
<span data-ty>node_modules</span>
<span data-ty>package.json</span>
<span data-ty>package-lock.json</span>
<span data-ty="input"><span class="file-path"></span></span>
</div>
@@ -0,0 +1,18 @@
<div id="termynal" data-termynal>
<span data-ty="input"><span class="file-path"></span> npx hardhat ignition deploy ./ignition/modules/Box.js --network moonbase</span>
<br>
<span data-ty>✅ Confirm deploy to network moonbase (1287)? … yes</span>
<span data-ty>Hardhat Ignition 🚀</span>
<br>
<span data-ty>Deploying [ BoxModule ]</span>
<br>
<span data-ty>Batch #1</span>
<span data-ty>Executed BoxModule#Box</span>
<br>
<span data-ty>[ BoxModule ] successfully deployed 🚀</span>
<br>
<span data-ty>Deployed Addresses</span>
<br>
<span data-ty>BoxModule#Box - 0xfBD78CE8C9E1169851119754C4Ea2f70AB159289</span>
<span data-ty="input"><span class="file-path"></span></span>
</div>
@@ -0,0 +1,20 @@
<div id="termynal" data-termynal>
<span data-ty="input"><span class="file-path"></span>npx hardhat init</span>
<span data-ty>888&nbsp;&nbsp;&nbsp;&nbsp;888&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;888&nbsp;888&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;888</span>
<span data-ty>888&nbsp;&nbsp;&nbsp;&nbsp;888&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;888&nbsp;888&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;888</span>
<span data-ty>888&nbsp;&nbsp;&nbsp;&nbsp;888&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;888&nbsp;888&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;888</span>
<span data-ty>8888888888&nbsp;&nbsp;8888b.&nbsp;&nbsp;888d888&nbsp;.d88888&nbsp;88888b.&nbsp;&nbsp;&nbsp;8888b.&nbsp;&nbsp;888888</span>
<span data-ty>888&nbsp;&nbsp;&nbsp;&nbsp;888&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"88b&nbsp;888P"&nbsp;&nbsp;d88"&nbsp;888&nbsp;888&nbsp;"88b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"88b&nbsp;888</span>
<span data-ty>888&nbsp;&nbsp;&nbsp;&nbsp;888&nbsp;.d888888&nbsp;888&nbsp;&nbsp;&nbsp;&nbsp;888&nbsp;&nbsp;888&nbsp;888&nbsp;&nbsp;888&nbsp;.d888888&nbsp;888</span>
<span data-ty>888&nbsp;&nbsp;&nbsp;&nbsp;888&nbsp;888&nbsp;&nbsp;888&nbsp;888&nbsp;&nbsp;&nbsp;&nbsp;Y88b&nbsp;888&nbsp;888&nbsp;&nbsp;888&nbsp;888&nbsp;&nbsp;888&nbsp;Y88b.</span>
<span data-ty>888&nbsp;&nbsp;&nbsp;&nbsp;888&nbsp;"Y888888&nbsp;888&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Y88888&nbsp;888&nbsp;&nbsp;888&nbsp;"Y888888&nbsp;&nbsp;"Y888</span>
<br>
<span data-ty>👷 Welcome to Hardhat v2.22.2 👷‍</span>
<br>
<span data-ty="input" data-ty-prompt="?">&nbsp;What do you want to do? …</span>
<span data-ty>&nbsp;&nbsp;Create a JavaScript project </span>
<span data-ty>&nbsp;&nbsp;Create a TypeScript project </span>
<span data-ty>&nbsp;&nbsp;Create a TypeScript project (with Viem) </span>
<span data-ty="input" data-ty-prompt="❯ Create an empty hardhat.config.js"></span>
<span data-ty>&nbsp;&nbsp;Quit </span>
</div>
@@ -0,0 +1,36 @@
<div id="termynal" data-termynal>
<span data-ty="input">npx hardhat console --network moonbase</span>
<br>
<span data-ty>Welcome to Node.js v20.9.0.</span>
<span data-ty>Type ".help" for more information.</span>
<span data-ty="input" data-ty-prompt=">"> const Box = await ethers.getContractFactory('Box');</span>
<span data-ty>undefined</span>
<br>
<span data-ty="input" data-ty-prompt=">"> const box = await Box.attach('0xfBD78CE8C9E1169851119754C4Ea2f70AB159289');</span>
<span data-ty>undefined</span>
<br>
<span data-ty="input" data-ty-prompt=">"> await box.store(5);</span>
<span data-ty>ContractTransactionResponse {<br>
provider: HardhatEthersProvider { ... },<br>
blockNumber: null,<br>
blockHash: null,<br>
index: undefined,<br>
hash: '0x1c49a64a601fc5dd184f0a368a91130cb49203ec0f533c6fcf20445c68e20264',<br>
type: 2,<br>
to: '0xa84caB60db6541573a091e5C622fB79e175E17be',<br>
from: '0x3B939FeaD1557C741Ff06492FD0127bd287A421e',<br>
nonce: 87,<br>
gasLimit: 45881n,<br>
gasPrice: 1107421875n,<br>
maxPriorityFeePerGas: 1n,<br>
maxFeePerGas: 1107421875n,<br>
data: '0x6057361d0000000000000000000000000000000000000000000000000000000000000005',<br>
value: 0n,<br>
chainId: 5678n,<br>
signature: Signature { r: "0x9233b9cc4ae6879b7e08b9f1a4bfb175c8216eee0099966eca4a305c7f369ecc", s: "0x7663688633006b5a449d02cb08311569fadf2f9696bd7fe65417860a3b5fc57d", yParity: 0, networkV: null },<br>
accessList: [],<br>
blobVersionedHashes: null<br>}</span>
<span data-ty="input" data-ty-prompt=">"> await box.retrieve();</span>
<span data-ty>5n</span>
<br>
</div>
@@ -0,0 +1,26 @@
<div id="termynal" data-termynal>
<span data-ty>Private Key: Oxdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97</span>
<span data-ty>Account #9: Oxa0Ee7A142d267C1f36714E4a8F75612F20a79720 (10000 ETH)</span>
<span data-ty>Private Key: 0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6</span>
<span data-ty>Account #10: OxBcd4042DE499D14e55001CcbB24a551F3b954096 (10000 ETH)</span>
<span data-ty>Private Key: Oxf214f2b2cd398c806f84e317254e0f0b801d0643303237d97a22a48e01628897</span>
<span data-ty>Account #11: 0x71bE63f3384f5fb98995898A86B02Fb2426c5788 (10000 ETH)</span>
<span data-ty>Private Key: 0x701b615bbdfb9de65240bc28bd21bbc0d996645a3dd57e7b12bc2bdf6f192c82</span>
<span data-ty>Account #12: OxFABBOac9d68B0B445fB7357272F202C5651694a (10000 ETH)</span>
<span data-ty>Private Key: Oxa267530f49f8280200edf313ee7af6b827f2a8bce2897751d06a843f644967b1</span>
<span data-ty>Account #13: 0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec (10000 ETH)</span>
<span data-ty>Private Key: 0x47c99abed3324a2707c28affff1267e45918ec8c3f20b8aa892e8b065d2942dd</span>
<span data-ty>Account #14: OxdF3e18d64BC6A983f673Ab319CCaE4f1a5707097 (10000 ETH)</span>
<span data-ty>Private Key: Oxc526ee95bf44d8fc405a158bb884d9d1238d990612e9f33d006bb0789009aaa</span>
<span data-ty>Account #15: Oxcd3B766CCDd6AE721141F452C550Ca635964ce71 (10000 ETH)</span>
<span data-ty>Private Key: 0x8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61</span>
<span data-ty>Account #16: 0×2546BcD3c84621e976D8185a91A922aE77ECEc30 (10000 ETH)</span>
<span data-ty>Private Key: Oxea6c44ac03bff858b476bba40716402b03e41b8e97e276d1baec7c37d42484a0</span>
<span data-ty>Account #17: OxbDA5747bFD65F08deb54cb465eB87D40e51B197E (10000 ETH)</span>
<span data-ty>Private Key: 0x689af8efa8c651a91ad287602527f3af2fe9f6501a7ac4b06166765a93e037fd</span>
<span data-ty>Account #18: OxdD2FD4581271e230360230F9337D5c0430Bf44C0 (10000 ETH)</span>
<span data-ty>Private Key: Oxde9be858da4a475276426320d5e9262ecfc3ba460bfac56360bfa6c4c28b4ee0</span>
<span data-ty>Account #19: 0×8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199 (10000 ETH)</span>
<span data-ty>Private Key: Oxdf57089febbacf7ba0bc227dafbffa9fc08a93fdc68e1e42411a14efcf23656e</span>
<span data-ty>WARNING: These accounts, and their private keys, are publicly known.<br>Any funds sent to them on Mainnet or any other live network WILL BE LOST.</span>
</div>
@@ -0,0 +1,6 @@
<div id="termynal" data-termynal>
<span data-ty="input"><span class="file-path"></span>npx hardhat run --network moonbase scripts/set-value.js</span>
<br>
<span data-ty>The new value is: 2</span>
<span data-ty="input"><span class="file-path"></span></span>
</div>
Expand Up @@ -4,11 +4,10 @@ pragma solidity >=0.8.0;

import "./StakingInterface.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";


contract DelegationDAO is AccessControl {
using SafeMath for uint256;

// Role definition for contract members
bytes32 public constant MEMBER = keccak256("MEMBER");
Expand Down Expand Up @@ -56,20 +55,25 @@ contract DelegationDAO is AccessControl {

// Initialize a new DelegationDao dedicated to delegating to the given collator target.
constructor(address _target, address admin) {
// Directly grant roles
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(MEMBER, admin);

//Sets the collator that this DAO nominating
target = _target;

// Initializes Moonbeam's parachain staking precompile
staking = ParachainStaking(stakingPrecompileAddress);

//Initializes Roles
_setupRole(DEFAULT_ADMIN_ROLE, admin);
_setupRole(MEMBER, admin);

//Initialize the DAO state
currentState = daoState.COLLECTING;
}

// Simple getter to return the target collator of the DAO
function getTarget() public view returns (address) {
return target;
}

// Grant a user the role of admin
function grant_admin(
address newAdmin
Expand Down Expand Up @@ -99,13 +103,13 @@ contract DelegationDAO is AccessControl {
if (!staking.isDelegator(address(this))) {
revert("The DAO is in an inconsistent state.");
}
memberStakes[msg.sender] = memberStakes[msg.sender].add(msg.value);
totalStake = totalStake.add(msg.value);
memberStakes[msg.sender] = memberStakes[msg.sender] + msg.value;
totalStake = totalStake + msg.value;
emit deposit(msg.sender, msg.value);
staking.delegatorBondMore(target, msg.value);
} else if (currentState == daoState.COLLECTING) {
memberStakes[msg.sender] = memberStakes[msg.sender].add(msg.value);
totalStake = totalStake.add(msg.value);
memberStakes[msg.sender] = memberStakes[msg.sender] + msg.value;
totalStake = totalStake + msg.value;
emit deposit(msg.sender, msg.value);
if (totalStake < minDelegationStk) {
return;
Expand Down Expand Up @@ -144,16 +148,13 @@ contract DelegationDAO is AccessControl {
}
require(totalStake != 0, "Cannot divide by zero.");
//Calculate the withdrawal amount including staking rewards
uint amount = address(this)
.balance
.mul(memberStakes[msg.sender])
.div(totalStake);
uint amount = address(this).balance * memberStakes[msg.sender] / totalStake;
require(
check_free_balance() >= amount,
"Not enough free balance for withdrawal."
);
Address.sendValue(account, amount);
totalStake = totalStake.sub(memberStakes[msg.sender]);
totalStake = totalStake - (memberStakes[msg.sender]);
memberStakes[msg.sender] = 0;
emit withdrawal(msg.sender, account, amount);
}
Expand Down Expand Up @@ -210,4 +211,9 @@ contract DelegationDAO is AccessControl {
function reset_dao() public onlyRole(DEFAULT_ADMIN_ROLE) {
currentState = daoState.COLLECTING;
}

// Override _setupRole to use grantRole as _setupRole does not exist in AccessControl anymore
function _setupRole(bytes32 role, address account) internal virtual {
grantRole(role, account);
}
}
Expand Up @@ -4,76 +4,90 @@ const { ethers } = require('hardhat');
const { expect } = require('chai');

// Indicate the collator the DAO wants to delegate to
const targetCollator = '0x4c5A56ed5A4FF7B09aA86560AfD7d383F4831Cce';
// For Moonbase Local Node, use: 0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac
// For Moonbase Alpha, use: 0x12E7BCCA9b1B15f33585b5fc898B967149BDb9a5
const targetCollator = 'INSERT_COLLATOR_ADDRESS';

// The describe function receives the name of a section of your test suite, and a
// callback. The callback must define the tests of that section. This callback
// can't be an async function
describe('Dao contract', function () {
async function deployDao() {
// Get the contract factory and signers here
const [deployer, member1] = await ethers.getSigners();
const delegationDao = await ethers.getContractFactory('DelegationDAO');
let wallet1, wallet2;

// Deploy the staking DAO and wait for the deployment transaction to be confirmed
const deployedDao = await delegationDao.deploy(
targetCollator,
deployer.address
before(async function () {
// Get signers we defined in Hardhat config
const signers = await ethers.getSigners();
wallet1 = signers[0];
wallet2 = signers[1];
});

async function deployDao() {
const delegationDaoFactory = await ethers.getContractFactory(
'DelegationDAO',
wallet2
);
await deployedDao.waitForDeployment();

// Return the deployed DAO and the first member of the DAO to allow the tests to
// access and interact with them
return { deployedDao, member1 };
// Deploy the staking DAO and wait for the deployment transaction to be confirmed
try {
const deployedDao = await delegationDaoFactory.deploy(
targetCollator,
wallet2.address
);
await deployedDao.waitForDeployment(); // Correct way to wait for the transaction to be mined
return { deployedDao };
} catch (error) {
console.error('Failed to deploy contract:', error);
return null; // Return null to indicate failure
}
}

// You can nest calls to create subsections
describe('Deployment', function () {
// Mocha's it function is used to define each of your tests.
// It receives the test name, and a callback function
//
// If the callback function is async, Mocha will await it
// Test case to check that the correct target collator is stored
it('should store the correct target collator in the DAO', async function () {
// Set up our test environment by calling deployDao
const { deployedDao } = await deployDao();

// The expect function receives a value and wraps it in an assertion object.
// This test will pass if the DAO stored the correct target collator
expect(await deployedDao.target()).to.equal(targetCollator);
const deployment = await deployDao();
if (!deployment || !deployment.deployedDao) {
throw new Error('Deployment failed; DAO contract was not deployed.');
}
const { deployedDao } = deployment;
expect(await deployedDao.getTarget()).to.equal(
'0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac'
);
});

// The following test cases should be added here
// Test case to check that the DAO has 0 funds at inception
it('should initially have 0 funds in the DAO', async function () {
const { deployedDao } = await deployDao();

// This test will pass if the DAO has no funds as expected before any contributions
expect(await deployedDao.totalStake()).to.equal(0);
});

// Test case to check that non-admins cannot grant membership
it('should not allow non-admins to grant membership', async function () {
const { deployedDao, member1 } = await deployDao();
const { deployedDao } = await deployDao();
// Connect the non-admin wallet to the deployed contract
const deployedDaoConnected = deployedDao.connect(wallet1);
const tx = deployedDaoConnected.grant_member(
'0x0000000000000000000000000000000000000000'
);

// We use connect to call grant_member from member1's account instead of admin.
// This test will succeed if the function call reverts and fails if the call succeeds
await expect(
deployedDao
.connect(member1)
.grant_member('0x0000000000000000000000000000000000000000')
).to.be.reverted;
// Check that the transaction reverts, not specifying any particular reason
await expect(tx).to.be.reverted;
});

// Test case to check that members can access member only functions
it('should only allow members to access member-only functions', async function () {
const { deployedDao, member1 } = await deployDao();
const { deployedDao } = await deployDao();

// Add a new member to the DAO
const transaction = await deployedDao.grant_member(member1.address);
await transaction.wait();
// Connect the wallet1 to the deployed contract and grant membership
const deployedDaoConnected = deployedDao.connect(wallet2);
const grantTx = await deployedDaoConnected.grant_member(wallet1.address);
await grantTx.wait();

// This test will succeed if the DAO member can call the member-only function.
// We use connect here to call the function from the account of the new member
expect(await deployedDao.connect(member1).check_free_balance()).to.equal(
0
);
// Check the free balance using the member's credentials
const checkTx = deployedDaoConnected.check_free_balance();

// Since check_free_balance() does not modify state, we expect it not to be reverted and check the balance
await expect(checkTx).to.not.be.reverted;
expect(await checkTx).to.equal(0);
});
});
});
@@ -0,0 +1,5 @@
<div id="termynal" data-termynal>
<span data-ty="input"><span class="file-path"></span>npx hardhat compile</span>
<span data-ty>Compiled 8 Solidity files successfully (evm target: paris).</span>
<span data-ty="input"><span class="file-path"></span></span>
</div>
@@ -0,0 +1,18 @@
<div id="termynal" data-termynal>
<span data-ty="input"><span class="file-path"></span> npx hardhat ignition deploy ./ignition/modules/DelegationDao.js --network moonbase --deployment-id INSERT_YOUR_NAME</span>
<br>
<span data-ty>✅ Confirm deploy to network moonbase (1287)? … yes</span>
<span data-ty>Hardhat Ignition 🚀</span>
<br>
<span data-ty>Deploying [ DelegationDAOModule ]</span>
<br>
<span data-ty>Batch #1</span>
<span data-ty>Executed DelegationDAOModule#DelegationDAO</span>
<br>
<span data-ty>[ DelegationDAOModule ] successfully deployed 🚀</span>
<br>
<span data-ty>Deployed Addresses</span>
<br>
<span data-ty>DelegationDAOModule#DelegationDAO - 0x69c555fE1A8D0916E6dab0629bd7530D4d2Be4D1</span>
<span data-ty="input"><span class="file-path"></span></span>
</div>
@@ -0,0 +1,18 @@
<div id="termynal" data-termynal>
<span data-ty="input"><span class="file-path"></span> npx hardhat ignition deploy ./ignition/modules/DelegationDao.js --network moonbeam --deployment-id INSERT_YOUR_NAME</span>
<br>
<span data-ty>✅ Confirm deploy to network moonbeam (1284)? … yes</span>
<span data-ty>Hardhat Ignition 🚀</span>
<br>
<span data-ty>Deploying [ DelegationDAOModule ]</span>
<br>
<span data-ty>Batch #1</span>
<span data-ty>Executed DelegationDAOModule#DelegationDAO</span>
<br>
<span data-ty>[ DelegationDAOModule ] successfully deployed 🚀</span>
<br>
<span data-ty>Deployed Addresses</span>
<br>
<span data-ty>DelegationDAOModule#DelegationDAO - 0x6D895A55F5ba31e582bCEe71cae394266F240e9b</span>
<span data-ty="input"><span class="file-path"></span></span>
</div>