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

DAO Improvements #12

Merged
merged 15 commits into from
Jul 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 96 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

- hardhat gas-reporter: run test `npx hardhat test`

*For DAO with Openzeppelin Governance Release [v0.2-dev](http://github.com/DuBento/Thesis/releases/tag/v0.2-dev)*
_For DAO with Openzeppelin Governance Release [v0.2-dev](http://github.com/DuBento/Thesis/releases/tag/v0.2-dev)_

```
·-------------------------------------------------------|----------------------------|-------------|-----------------------------·
Expand Down Expand Up @@ -89,6 +89,97 @@
·-------------------------------------------------------|--------------|-------------|-------------|---------------|-------------·
```

_Afte DAO improvements and simplifications [v0.3-dev](http://github.com/DuBento/Thesis/releases/tag/v0.3-dev)_

Deployment cost improvement of around 59%.
Not considering SupplychainFactory contract for cost calculations (cost has increased but is unrelated with DAO).

Calculations on 28/07/2023 with: avg gas 30 gwei/gas and 1700 eur/eth

- old deployment cost: 15477559 gas (around 789 eur)
- new deployment cost: 6382115 gas (around 358 eur)
- difference of 463 eur

```
·-------------------------------------------------------|----------------------------|-------------|-----------------------------·
| Solc version: 0.8.19 · Optimizer enabled: false · Runs: 200 · Block limit: 30000000 gas │
························································|····························|·············|······························
| Methods · 21 gwei/gas · 1702.34 eur/eth │
·······················|································|··············|·············|·············|···············|··············
| Contract · Method · Min · Max · Avg · # calls · eur (avg) │
·······················|································|··············|·············|·············|···············|··············
| Executor · transferOwnership · - · - · 32967 · 1 · 1.18 │
·······················|································|··············|·············|·············|···············|··············
| GovernorContract · castVoteWithReason · 68720 · 88620 · 86313 · 18 · 3.09 │
·······················|································|··············|·············|·············|···············|··············
| GovernorContract · execute · 87720 · 187487 · 168805 · 14 · 6.03 │
·······················|································|··············|·············|·············|···············|··············
| GovernorContract · propose · 91130 · 95456 · 93267 · 22 · 3.33 │
·······················|································|··············|·············|·············|···············|··············
| Supplychain · handleTransaction · - · - · 150162 · 1 · 5.37 │
·······················|································|··············|·············|·············|···············|··············
| Supplychain · handleUpdate · - · - · 133863 · 1 · 4.79 │
·······················|································|··············|·············|·············|···············|··············
| Supplychain · newBatch · 198913 · 201108 · 200742 · 12 · 7.18 │
·······················|································|··············|·············|·············|···············|··············
| SupplychainFactory · create · - · - · 138435 · 1 · 4.95 │
·······················|································|··············|·············|·············|···············|··············
| SupplychainFactory · transferOwnership · - · - · 32967 · 2 · 1.18 │
·······················|································|··············|·············|·············|···············|··············
| UserRegistry · addActor · - · - · 93895 · 6 · 3.36 │
·······················|································|··············|·············|·············|···············|··············
| UserRegistry · addContractToActor · 52163 · 73731 · 67633 · 5 · 2.42 │
·······················|································|··············|·············|·············|···············|··············
| UserRegistry · addMember · 127628 · 144704 · 139012 · 3 · 4.97 │
·······················|································|··············|·············|·············|···············|··············
| UserRegistry · setSupplychainFactoryAddress · - · - · 51989 · 2 · 1.86 │
·······················|································|··············|·············|·············|···············|··············
| UserRegistry · transferOwnership · - · - · 33011 · 2 · 1.18 │
·······················|································|··············|·············|·············|···············|··············
| Deployments · · % of limit · │
························································|··············|·············|·············|···············|··············
| Executor · - · - · 1334736 · 4.4 % · 47.72 │
························································|··············|·············|·············|···············|··············
| GovernorContract · - · - · 2702432 · 9 % · 96.61 │
························································|··············|·············|·············|···············|··············
| SupplychainFactory · - · - · 2767602 · 9.2 % · 98.94 │
························································|··············|·············|·············|···············|··············
| UserRegistry · - · - · 2344947 · 7.8 % · 83.83 │
·-------------------------------------------------------|--------------|-------------|-------------|---------------|-------------·
```

Method gas comparison:

```
CONSTANTS gas/gwei 30
eth/eur 1700

| Contract Method avg gas: avg eur: diff %
OZ DAO our DAO OZ DAO our DAO
| GovernorContract castVoteWithReason 88961 86313 €4.54 €4.40 2.98%
| GovernorContract execute 298326 168805 €15.21 €8.61 43.42%
| GovernorContract propose 111769 93267 €5.70 €4.76 16.55%
| GovernorContract queue 143551 - €7.32 - -
| GovernorTimelock grantRole 40804 - €2.08 - -
| GovernorTimelock revokeRole 27746 - €1.42 - -
| GovernorToken delegate 96883 - €4.94 - -
| GovernorToken transferOwnership 32992 32967 €1.68 €1.68 0.08%
| SupplychainFactory create 155491 138435 €7.93 €7.06 10.97%
| SupplychainFactory transferOwnership 32967 32967 €1.68 €1.68 0.00%
| Supplychain handleTransaction 149951 150162 €7.65 €7.66 -0.14%
| Supplychain handleUpdate 133635 133863 €6.82 €6.83 -0.17%
| Supplychain newBatch 200508 200742 €10.23 €10.24 -0.12%
| UserRegistry addActor 93851 93895 €4.79 €4.79 -0.05%
| UserRegistry addContractToActor 67611 67633 €3.45 €3.45 -0.03%
| UserRegistry addMember 118547 139012 €6.05 €7.09 -17.26%
| UserRegistry setGovernorTokenAddress 51988 - €2.65 - -
| UserRegistry setSupplychainFactoryAddress 52078 51989 €2.66 €2.65 0.17%
| UserRegistry transferOwnership 33011 33011 €1.68 €1.68 0.00%
SUM 1930670 1423061 €98.46 €72.58 26.29%
DIFF 507609 €25.89

```

---

## Resources
Expand All @@ -105,6 +196,7 @@
**Blockchain**

_Hardhat_ as development framework, using extensions:

- hardhat-ethers, for integration with ethersjs
- hardhat-deploy, for deployment scripts
- gas-reporter, for reports on gas cost (usage and deployment)
Expand All @@ -117,15 +209,16 @@ Developed for EVM compatible blockchains (Ethereum).
**Frontend**

_Next.js_ as development framework, using:

- React, library for building frontend
- TailwindCSS, a CSS styling framework
- Ethers, a library for interacting with Ethereum and Ethereum-like blockchains.
- swr, a React library for remote data fetching and caching.
- react-hot-toast, a toast notification library for React.
- react-hot-toast, a toast notification library for React.

All files written with Typescript.

**IPFS**

- For development, using a Docker container running [Kubo](https://hub.docker.com/r/ipfs/kubo/) (default IPFS implementation in Go)
- For production or other, possible to use external pining services and gateways like [pinata](https://www.pinata.cloud/)
- For production or other, possible to use external pining services and gateways like [pinata](https://www.pinata.cloud/)
111 changes: 111 additions & 0 deletions blockchain/contracts/DAO/Executor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// SPDX-License-Identifier: Apache-2.0
// Based on Openzeppelin Contracts (last updated v4.9.0)

pragma solidity ^0.8.19;

import "../custom/Ownable.sol";
import "../OpenZeppelin/utils/Address.sol";
import "./IExecutor.sol";

contract Executor is IExecutor, Ownable {
// Type declarations
// State variables
bool private locked;

// Modifiers
modifier nonReentrant() {
if (locked) revert ReentrantCall();
locked = true;
_;
locked = false;
}

// Functions
//* constructor
//* receive function
/**
* @dev Contract might receive/hold ETH as part of the maintenance process.
*/
receive() external payable override {}

//* fallback function (if exists)
//* external
//* public
/**
* @dev Execute an (ready) operation containing a single transaction.
*
* Emits a {CallExecuted} event.
*
* Only owner can execute, usually Governor Contract.
*/
function execute(
address target,
uint256 value,
bytes calldata payload,
bytes32 predecessor,
bytes32 salt
) public payable override nonReentrant onlyOwner {
bytes32 id = hashOperation(target, value, payload, predecessor, salt);

_execute(target, value, payload);
emit CallExecuted(id, 0, target, value, payload);
}

/**
* @dev Execute an (ready) operation containing a batch of transactions.
*
* Emits one {CallExecuted} event per transaction in the batch.
*
* Only owner can execute, usually Governor Contract.
*/
function executeBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata payloads,
bytes32 predecessor,
bytes32 salt
) public payable override nonReentrant onlyOwner {
if (
targets.length != values.length || targets.length != payloads.length
) {
revert ExecutorInvalidOperationLength(
targets.length,
payloads.length,
values.length
);
}

bytes32 id = hashOperationBatch(
targets,
values,
payloads,
predecessor,
salt
);

for (uint256 i = 0; i < targets.length; ++i) {
address target = targets[i];
uint256 value = values[i];
bytes calldata payload = payloads[i];
_execute(target, value, payload);
emit CallExecuted(id, i, target, value, payload);
}
}

//* internal
/**
* @dev Execute an operation's call.
*/
function _execute(
address target,
uint256 value,
bytes calldata data
) internal {
(bool success, bytes memory returndata) = target.call{value: value}(
data
);
Address.verifyCallResult(success, returndata);
}
//* private
//* asserts
}
120 changes: 20 additions & 100 deletions blockchain/contracts/DAO/GovernorContract.sol
Original file line number Diff line number Diff line change
@@ -1,44 +1,38 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.19;

import "../OpenZeppelin/governance/Governor.sol";
import "../OpenZeppelin/governance/extensions/GovernorCountingSimple.sol";
import "../OpenZeppelin/governance/extensions/GovernorVotes.sol";
import "../OpenZeppelin/governance/extensions/GovernorVotesQuorumFraction.sol";
import "../OpenZeppelin/governance/extensions/GovernorTimelockControl.sol";
import "../OpenZeppelin/governance/extensions/GovernorSettings.sol";
import "./governance/extensions/GovernorCountingSimple.sol";
import "./governance/extensions/GovernorVotes.sol";
import "./governance/extensions/GovernorSettings.sol";
import "./governance/Governor.sol";
import "./IExecutor.sol";
import "./IUserRegistry.sol";

contract GovernorContract is
Governor,
GovernorSettings,
GovernorCountingSimple,
GovernorVotes,
GovernorVotesQuorumFraction,
GovernorTimelockControl
GovernorVotes
{
/** @dev Set low value during development, should be adjusted in production.
* Possible value 51 for majority.
*/
uint8 constant QUORUM = 25;

constructor(
IVotes _token,
TimelockController _timelock,
uint256 _votingDelay,
uint256 _votingPeriod,
uint256 _quorumFraction
IExecutor executor_,
IUserRegistry userRegistry_,
uint256 votingPeriod_
)
Governor("GovernorContract")
GovernorSettings(_votingDelay, _votingPeriod, 0)
GovernorVotes(_token)
GovernorVotesQuorumFraction(_quorumFraction)
GovernorTimelockControl(_timelock)
Governor("TracerDAO", executor_)
GovernorSettings(votingPeriod_)
GovernorVotes(userRegistry_)
{}

// The following functions are overrides required by Solidity.

function votingDelay()
public
view
override(IGovernor, GovernorSettings)
returns (uint256)
{
return super.votingDelay();
function quorum() public pure override returns (uint8) {
return QUORUM;
}

function votingPeriod()
Expand All @@ -49,78 +43,4 @@ contract GovernorContract is
{
return super.votingPeriod();
}

function quorum(
uint256 blockNumber
)
public
view
override(IGovernor, GovernorVotesQuorumFraction)
returns (uint256)
{
return super.quorum(blockNumber);
}

function state(
uint256 proposalId
)
public
view
override(Governor, GovernorTimelockControl)
returns (ProposalState)
{
return super.state(proposalId);
}

function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public override(Governor, IGovernor) returns (uint256) {
return super.propose(targets, values, calldatas, description);
}

function proposalThreshold()
public
view
override(Governor, GovernorSettings)
returns (uint256)
{
return super.proposalThreshold();
}

function _execute(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(Governor, GovernorTimelockControl) {
super._execute(proposalId, targets, values, calldatas, descriptionHash);
}

function _cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(Governor, GovernorTimelockControl) returns (uint256) {
return super._cancel(targets, values, calldatas, descriptionHash);
}

function _executor()
internal
view
override(Governor, GovernorTimelockControl)
returns (address)
{
return super._executor();
}

function supportsInterface(
bytes4 interfaceId
) public view override(Governor, GovernorTimelockControl) returns (bool) {
return super.supportsInterface(interfaceId);
}
}
Loading