This repository has been archived by the owner on Nov 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fd3eded
commit 5e2653b
Showing
6 changed files
with
18 additions
and
157 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,21 +2,18 @@ | |
pragma solidity ^0.8.23; | ||
|
||
import {ILlamaCore} from "src/interfaces/ILlamaCore.sol"; | ||
import {ILlamaPolicy} from "src/interfaces/ILlamaPolicy.sol"; | ||
import {ILlamaExecutor} from "src/interfaces/ILlamaExecutor.sol"; | ||
import {RoleDescription} from "src/lib/UDVTs.sol"; | ||
import {ERC20TokenholderActionCreator} from "src/token-voting/ERC20TokenholderActionCreator.sol"; | ||
import {ERC20TokenholderCaster} from "src/token-voting/ERC20TokenholderCaster.sol"; | ||
import {ERC20Votes} from "@openzeppelin/token/ERC20/extensions/ERC20Votes.sol"; | ||
import {ERC721TokenholderActionCreator} from "src/token-voting/ERC721TokenholderActionCreator.sol"; | ||
import {ERC721TokenholderCaster} from "src/token-voting/ERC721TokenholderCaster.sol"; | ||
import {ERC721Votes} from "@openzeppelin/token/ERC721/extensions/ERC721Votes.sol"; | ||
import {LlamaBaseScript} from "src/llama-scripts/LlamaBaseScript.sol"; | ||
|
||
/// @title LlamaTokenVotingFactory | ||
/// @author Llama ([email protected]) | ||
/// @notice This contract lets llama instances deploy a token voting module in a single llama action. | ||
contract LlamaTokenVotingFactory is LlamaBaseScript { | ||
contract LlamaTokenVotingFactory { | ||
error NoModulesDeployed(); | ||
|
||
event ERC20TokenholderActionCreatorCreated(address actionCreator, address indexed token); | ||
|
@@ -34,8 +31,6 @@ contract LlamaTokenVotingFactory is LlamaBaseScript { | |
/// a script. | ||
///@param token The address of the token to be used for voting. | ||
///@param isERC20 Whether the token is an ERC20 or ERC721. | ||
///@param deployActionCreator Whether to deploy the action creator. | ||
///@param deployCaster Whether to deploy the caster. | ||
///@param creationThreshold The number of tokens required to create an action (set to 0 if not deploying action | ||
/// creator). | ||
///@param minApprovalPct The minimum percentage of tokens required to approve an action (set to 0 if not deploying | ||
|
@@ -45,109 +40,24 @@ contract LlamaTokenVotingFactory is LlamaBaseScript { | |
function deployTokenVotingModule( | ||
address token, | ||
bool isERC20, | ||
bool deployActionCreator, | ||
bool deployCaster, | ||
uint256 creationThreshold, | ||
uint256 minApprovalPct, | ||
uint256 minDisapprovalPct | ||
) public returns (address, address) { | ||
return _deployTokenVotingModule( | ||
ILlamaExecutor(msg.sender), | ||
token, | ||
isERC20, | ||
deployActionCreator, | ||
deployCaster, | ||
creationThreshold, | ||
minApprovalPct, | ||
minDisapprovalPct | ||
); | ||
} | ||
|
||
///@notice A llama script that deploys a token voting module and inittializes/issues roles to the token voting action | ||
/// creator and caster in a single function so it can be deployed in a single llama action. | ||
///@dev This contract must be authorized as a script in the core contract before it can be used (invoke the | ||
/// `LlamaCore::setScriptAuthorization` function to authorize). | ||
///@dev This method CAN NOT be used in tandem with `deployTokenVotingModule`. You must use one or the other due to | ||
/// this method requring the contract to be authorized as a script. | ||
///@param token The address of the token to be used for voting. | ||
///@param isERC20 Whether the token is an ERC20 or ERC721. | ||
///@param deployActionCreator Whether to deploy the action creator. | ||
///@param deployCaster Whether to deploy the caster. | ||
///@param creationThreshold The number of tokens required to create an action (set to 0 if not deploying action | ||
/// creator). | ||
///@param minApprovalPct The minimum percentage of tokens required to approve an action (set to 0 if not deploying | ||
/// caster). | ||
///@param minDisapprovalPct The minimum percentage of tokens required to disapprove an action (set to 0 if not | ||
/// deploying caster). | ||
function delegateCallDeployTokenVotingModuleWithRoles( | ||
address token, | ||
bool isERC20, | ||
bool deployActionCreator, | ||
bool deployCaster, | ||
uint256 creationThreshold, | ||
uint256 minApprovalPct, | ||
uint256 minDisapprovalPct | ||
) public onlyDelegateCall { | ||
(address actionCreator, address caster) = _deployTokenVotingModule( | ||
ILlamaExecutor(address(this)), | ||
token, | ||
isERC20, | ||
deployActionCreator, | ||
deployCaster, | ||
creationThreshold, | ||
minApprovalPct, | ||
minDisapprovalPct | ||
); | ||
|
||
ILlamaExecutor executor = ILlamaExecutor(address(this)); | ||
ILlamaCore core = ILlamaCore(executor.LLAMA_CORE()); | ||
ILlamaPolicy policy = ILlamaPolicy(core.policy()); | ||
uint8 numRoles = policy.numRoles(); | ||
string memory name; | ||
isERC20 ? name = ERC20Votes(token).name() : name = ERC721Votes(token).name(); | ||
if (actionCreator != address(0)) { | ||
policy.initializeRole(RoleDescription.wrap(bytes32(abi.encodePacked("Action Creator Role: ", name)))); | ||
policy.setRoleHolder(numRoles + 1, actionCreator, 1, type(uint64).max); | ||
} | ||
if (caster != address(0)) { | ||
policy.initializeRole(RoleDescription.wrap(bytes32(abi.encodePacked("Caster Role: ", name)))); | ||
policy.setRoleHolder(actionCreator == address(0) ? numRoles + 1 : numRoles + 2, caster, 1, type(uint64).max); | ||
) external returns (address actionCreator, address caster) { | ||
ILlamaCore core = ILlamaCore(ILlamaExecutor(executor).LLAMA_CORE()); | ||
if (isERC20) { | ||
actionCreator = address(_deployERC20TokenholderActionCreator(ERC20Votes(token), core, creationThreshold)); | ||
caster = address(_deployERC20TokenholderCaster(ERC20Votes(token), core, 0, minApprovalPct, minDisapprovalPct)); | ||
} else { | ||
actionCreator = address(_deployERC721TokenholderActionCreator(ERC721Votes(token), core, creationThreshold)); | ||
caster = address(_deployERC721TokenholderCaster(ERC721Votes(token), core, 0, minApprovalPct, minDisapprovalPct)); | ||
} | ||
} | ||
|
||
// ==================================== | ||
// ======== Internal Functions ======== | ||
// ==================================== | ||
|
||
function _deployTokenVotingModule( | ||
ILlamaExecutor executor, | ||
address token, | ||
bool isERC20, | ||
bool deployActionCreator, | ||
bool deployCaster, | ||
uint256 creationThreshold, | ||
uint256 minApprovalPct, | ||
uint256 minDisapprovalPct | ||
) internal returns (address actionCreator, address caster) { | ||
if (!deployActionCreator && !deployCaster) revert NoModulesDeployed(); | ||
ILlamaCore core = ILlamaCore(executor.LLAMA_CORE()); | ||
if (isERC20) { | ||
if (deployActionCreator) { | ||
actionCreator = address(_deployERC20TokenholderActionCreator(ERC20Votes(token), core, creationThreshold)); | ||
} | ||
if (deployCaster) { | ||
caster = address(_deployERC20TokenholderCaster(ERC20Votes(token), core, 0, minApprovalPct, minDisapprovalPct)); | ||
} | ||
} else { | ||
if (deployActionCreator) { | ||
actionCreator = address(_deployERC721TokenholderActionCreator(ERC721Votes(token), core, creationThreshold)); | ||
} | ||
if (deployCaster) { | ||
caster = address(_deployERC721TokenholderCaster(ERC721Votes(token), core, 0, minApprovalPct, minDisapprovalPct)); | ||
} | ||
} | ||
} | ||
|
||
function _deployERC20TokenholderActionCreator(ERC20Votes token, ILlamaCore llamaCore, uint256 creationThreshold) | ||
internal | ||
returns (ERC20TokenholderActionCreator actionCreator) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,10 +10,10 @@ import {LlamaUtils} from "src/lib/LlamaUtils.sol"; | |
/// @author Llama ([email protected]) | ||
/// @notice This contract lets holders of a given governance token create actions if they have | ||
/// sufficient token balance. | ||
/// @dev This contract can be deployed by anyone, but to actually be able to create an action it | ||
/// will need to hold a Policy from the specified `LlamaCore` instance. That policy encodes what | ||
/// actions this contract is allowed to create, and attempting to create an action that is not | ||
/// allowed by the policy will result in a revert. | ||
/// @dev This contract is deployed by `LlamaTokenVotingFactory`. Anyone can deploy this contract using the factory, but | ||
/// it must hold a Policy from the specified `LlamaCore` instance to actually be able to create an action. The | ||
/// instance's policy encodes what actions this contract is allowed to create, and attempting to create an action that | ||
/// is not allowed by the policy will result in a revert. | ||
abstract contract TokenholderActionCreator { | ||
/// @notice The core contract for this Llama instance. | ||
ILlamaCore public immutable LLAMA_CORE; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,9 +12,9 @@ import {ILlamaRelativeStrategyBase} from "src/interfaces/ILlamaRelativeStrategyB | |
/// @author Llama ([email protected]) | ||
/// @notice This contract lets holders of a given governance token cast approvals and disapprovals | ||
/// on created actions. | ||
/// @dev This contract can be deployed by anyone, but to actually be able to cast on an action it | ||
/// will need to hold the appropriate Policy from the specified `LlamaCore` instance. This contract | ||
/// does not verify that it holds the correct policy when voting, and relies on `LlamaCore` to | ||
/// @dev This contract is deployed by `LlamaTokenVotingFactory`. Anyone can deploy this contract using the factory, but | ||
/// it must hold a Policy from the specified `LlamaCore` instance to actually be able to cast on an action. This | ||
/// contract does not verify that it holds the correct policy when voting and relies on `LlamaCore` to | ||
/// verify that during submission. | ||
abstract contract TokenholderCaster { | ||
// ========================= | ||
|