Skip to content
This repository has been archived by the owner on Nov 27, 2024. It is now read-only.

Commit

Permalink
conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
AustinGreen committed Dec 5, 2023
1 parent fd3eded commit 5e2653b
Show file tree
Hide file tree
Showing 6 changed files with 18 additions and 157 deletions.
23 changes: 0 additions & 23 deletions src/llama-scripts/LlamaBaseScript.sol

This file was deleted.

27 changes: 0 additions & 27 deletions src/llama-scripts/LlamaSingleUseScript.sol

This file was deleted.

3 changes: 2 additions & 1 deletion src/token-voting/ERC721TokenholderActionCreator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ contract ERC721TokenholderActionCreator is TokenholderActionCreator {
TokenholderActionCreator(llamaCore, _creationThreshold)
{
TOKEN = token;
if (!TOKEN.supportsInterface(type(IERC721).interfaceId)) revert InvalidTokenAddress();

uint256 totalSupply = TOKEN.getPastTotalSupply(block.timestamp - 1);
if (totalSupply == 0) revert InvalidTokenAddress();
if (_creationThreshold > totalSupply) revert InvalidCreationThreshold();
if (!TOKEN.supportsInterface(type(IERC721).interfaceId)) revert InvalidTokenAddress();
}

function _getPastVotes(address account, uint256 timestamp) internal view virtual override returns (uint256) {
Expand Down
108 changes: 9 additions & 99 deletions src/token-voting/LlamaTokenVotingFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions src/token-voting/TokenholderActionCreator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions src/token-voting/TokenholderCaster.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
// =========================
Expand Down

0 comments on commit 5e2653b

Please sign in to comment.