Skip to content
This repository has been archived by the owner on Oct 6, 2023. It is now read-only.

Commit

Permalink
Closes AP-727, AP-791: EndowmentMultiSig proxy admin update & update …
Browse files Browse the repository at this point in the history
…EndowmentMultiSigFactory's registrar on new Registrar deployment (#377)

* Validate addresses using Validator

* Move events to IEndowmentMultiSigFactory

* Use InvalidAddress error instead of requires

* Use OnlyAccountsContract error in onlyAccountsContract

* Add updateRegistrar function

* Add Initialized event

* Add missing getInstantiationCount function to interface

* Remove unused factory param in upgrade:endowmentMultiSig:emitter

* Add getRegistrarAddress function

* Add manage:endowmentMultiSigFactory:updateRegistrar task

* Add call to manage:endowmentMultiSigFactory:updateRegistrar to deploy:Registrar task

* Remove unused errors from IterableMappingAddr

* Remove unused IterableMappingAddr import from LibAccounts

* Remove endowmentIdToMultisig mapping

* Remove getInstantiationCount

* Add endowmentMultiSigs IterableMappingAddr.Map

* Add back isInstantiation function

* Refactor constructor + remove Initialized event

* Rename register > endowmentMultiSigProxy to instantiation

* Update comments

* Implement getInstantiations function

* Rename getRegistrarAddress -> getRegistrar (+ add comment)

* Update EndowmentMultiSig Proxies' addresses in manage:changeProxyAdmin task

* Update comment for newProxyAdmin

* Make proxyAdmin field internal and access through getProxyAdmin

* Rename changeProxyAdmin->changeProxyAdminForAll and fix logic

* Create manage:changeProxyAdmin task

* Update comment in updateRegistrar

* Update logging logic

* Refactor tasks/manage/changeProxyAdmin.ts

* Update manage:changeProxyAdminForAll to use changeProxyAdmin task

* Add manage:endowmentMultiSigFactory:updateProxyAdmin task

* Call manage:endowmentMultiSigFactory:updateProxyAdmin in changeProxyAdminForAll

* Update log 'Submitting Tx...' to comment

* Make 'to' optional, read from contract-address.json if null

* Fix old proxyAdmin checking logic

* Target curAdmin when submitting Tx to changeProxyAdmin

* submitMultiSigTx > owner -> msOwner

* Remove redundant log in update reg. config

* Fix tasks/manage/changeProxyAdmin.ts

* Fix tasks/manage/changeProxyAdminForAll.ts

* Add divider to changeProxyAdminForAll > changeProxiesAdmin

* Remove temp_task import

* Revert contract-address.json

* Remove isInstantiation

* Refactor manage:endowmentMultiSigFactory:updateProxyAdmin

* Minor refactor manage:registrar:updateConfig

* Add comment to updateEndowmentMultiSigFactory

* Remove mention in EndowmentMultiSigFactory

* Revert "Remove unused errors from IterableMappingAddr"

This reverts commit 81e414d.

* Revert "Remove unused IterableMappingAddr import from LibAccounts"

This reverts commit 4b7c78f.

* Revert "Revert "Remove unused IterableMappingAddr import from LibAccounts""

This reverts commit 9c6a062.

* Revert "Revert "Remove unused errors from IterableMappingAddr""

This reverts commit 98756ce.

* Add basic checkIfProxyAdmin to changeProxyAdmin

* Move checkIfProxyAdmin to checkIfManagedByProxyAdmin

* Fix issues after rebase
  • Loading branch information
Nenad Misic authored Sep 20, 2023
1 parent 3970403 commit 3ba7eb4
Show file tree
Hide file tree
Showing 17 changed files with 569 additions and 170 deletions.
1 change: 0 additions & 1 deletion contracts/core/accounts/lib/LibAccounts.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {IterableMappingAddr} from "../../../lib/IterableMappingAddr.sol";
import {AccountStorage} from "../storage.sol";

library LibAccounts {
Expand Down
3 changes: 0 additions & 3 deletions contracts/lib/IterableMappingAddr.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
pragma solidity ^0.8.19;

contract IterableMappingAddr {
error NonExistentKey(address key);
error DecrAmountExceedsValue(address key, uint256 currVal, uint256 decrVal);

struct Map {
address[] keys;
mapping(address => bool) values;
Expand Down
102 changes: 59 additions & 43 deletions contracts/multisigs/endowment-multisig/EndowmentMultiSigFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,63 +7,68 @@ import {IEndowmentMultiSigFactory} from "./interfaces/IEndowmentMultiSigFactory.
import {ProxyContract} from "../../core/proxy.sol";
import {IRegistrar} from "../../core/registrar/interfaces/IRegistrar.sol";
import {RegistrarStorage} from "../../core/registrar/storage.sol";
import {Validator} from "../../core/validator.sol";
import {IterableMappingAddr} from "../../lib/IterableMappingAddr.sol";

/// @title Multisignature wallet factory - Allows creation of multisigs wallet.
/// @author Stefan George - <[email protected]>
contract EndowmentMultiSigFactory is IEndowmentMultiSigFactory, Ownable {
/*
* Events
*/
event ContractInstantiated(address sender, address instantiation);
event ImplementationUpdated(address implementationAddress);
event ProxyAdminUpdated(address admin);

/*
* Storage
*/
mapping(address => bool) public isInstantiation;
mapping(address => address[]) public instantiations;
mapping(uint256 => address) public endowmentIdToMultisig;
contract EndowmentMultiSigFactory is IEndowmentMultiSigFactory, Ownable, IterableMappingAddr {
/*////////////////////////////////////////////////
STORAGE
*/ ///////////////////////////////////////////////
IterableMappingAddr.Map endowmentMultiSigs;

address public implementationAddress;
address public proxyAdmin;
address proxyAdmin;
IRegistrar registrar;

constructor(address _implementationAddress, address _proxyAdmin, address _registrar) {
require(_implementationAddress != address(0), "Invalid Address");
require(_proxyAdmin != address(0), "Invalid Address");
require(_registrar != address(0), "Invalid Address");

registrar = IRegistrar(_registrar);
implementationAddress = _implementationAddress;
emit ImplementationUpdated(_implementationAddress);

proxyAdmin = _proxyAdmin;
emit ProxyAdminUpdated(_proxyAdmin);
constructor(address _implementationAddress, address _proxyAdmin, address registrarAddress) {
updateImplementation(_implementationAddress);
updateProxyAdmin(_proxyAdmin);
updateRegistrar(registrarAddress);
}

/*////////////////////////////////////////////////
MODIFIERS
*/ ///////////////////////////////////////////////

modifier onlyAccountsContract() {
RegistrarStorage.Config memory registrarConfig = registrar.queryConfig();
require(msg.sender == registrarConfig.accountsContract, "Only Accounts Contract");
if (msg.sender != registrarConfig.accountsContract) {
revert OnlyAccountsContract();
}
_;
}

/*
* Public functions
*/
/// @dev Returns number of instantiations by creator.
/// @param creator Contract creator.
/// @return Returns number of instantiations by creator.
function getInstantiationCount(address creator) public view returns (uint256) {
return instantiations[creator].length;
/*////////////////////////////////////////////////
IMPLEMENTATION
*/ ///////////////////////////////////////////////

/// @notice Get all EndowmentMultiSig proxy contract instantiations.
/// @return Array of instantiation addresses.
function getInstantiations() external view returns (address[] memory) {
return endowmentMultiSigs.keys;
}

/// @notice Get stored registrar address.
/// @return address of the stored registrar.
function getRegistrar() external view returns (address) {
return address(registrar);
}

/// @notice Get proxy admin address.
/// @return address of the proxy admin.
function getProxyAdmin() external view returns (address) {
return proxyAdmin;
}

/**
* @dev Updates the implementation address
* @param _implementationAddress The address of the new implementation
*/
function updateImplementation(address _implementationAddress) public onlyOwner {
require(_implementationAddress != address(0), "Invalid Address");
if (!Validator.addressChecker(_implementationAddress)) {
revert InvalidAddress("_implementationAddress");
}
implementationAddress = _implementationAddress;
emit ImplementationUpdated(_implementationAddress);
}
Expand All @@ -73,11 +78,25 @@ contract EndowmentMultiSigFactory is IEndowmentMultiSigFactory, Ownable {
* @param _proxyAdmin The address of the new proxy admin
*/
function updateProxyAdmin(address _proxyAdmin) public onlyOwner {
require(_proxyAdmin != address(0), "Invalid Address");
if (!Validator.addressChecker(_proxyAdmin)) {
revert InvalidAddress("_proxyAdmin");
}
proxyAdmin = _proxyAdmin;
emit ProxyAdminUpdated(_proxyAdmin);
}

/**
* @dev Updates the registrar address
* @param registrarAddress The address of the new registrar
*/
function updateRegistrar(address registrarAddress) public onlyOwner {
if (!Validator.addressChecker(registrarAddress)) {
revert InvalidAddress("registrarAddress");
}
registrar = IRegistrar(registrarAddress);
emit RegistrarUpdated(registrarAddress);
}

/** @dev Create a new multisig wallet for an endowment
* @param endowmentId the endowment id
* @param emitterAddress the emitter of the multisig
Expand Down Expand Up @@ -113,18 +132,15 @@ contract EndowmentMultiSigFactory is IEndowmentMultiSigFactory, Ownable {
);

register(wallet);
// also store address of multisig in endowmentIdToMultisig
endowmentIdToMultisig[endowmentId] = wallet;
}

/*
* Internal functions
*/
/// @dev Registers contract in factory registry.
/// @param instantiation Address of contract instantiation.
/// @param instantiation Address of EndowmentMultiSig proxy contract instantiation.
function register(address instantiation) internal {
isInstantiation[instantiation] = true;
instantiations[msg.sender].push(instantiation);
IterableMappingAddr.set(endowmentMultiSigs, instantiation, true);
emit ContractInstantiated(msg.sender, instantiation);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@
pragma solidity ^0.8.19;

interface IEndowmentMultiSigFactory {
/*////////////////////////////////////////////////
EVENTS
*/ ///////////////////////////////////////////////
event ContractInstantiated(address sender, address instantiation);
event ImplementationUpdated(address implementationAddress);
event ProxyAdminUpdated(address admin);
event RegistrarUpdated(address registrar);

/*////////////////////////////////////////////////
ERRORS
*/ ///////////////////////////////////////////////
error InvalidAddress(string param);
error OnlyAccountsContract();

/*////////////////////////////////////////////////
EXTERNAL FUNCTIONS
*/ ////////////////////////////////////////////////
function create(
uint256 endowmentId,
address emitterAddress,
Expand All @@ -14,5 +31,17 @@ interface IEndowmentMultiSigFactory {

function updateProxyAdmin(address proxyAdminAddress) external;

function endowmentIdToMultisig(uint256 endowmentId) external returns (address);
function updateRegistrar(address registrarAddress) external;

/// @notice Get all EndowmentMultiSig proxy contract instantiations.
/// @return Array of instantiation addresses.
function getInstantiations() external view returns (address[] memory);

/// @notice Get stored registrar address.
/// @return address of the stored registrar.
function getRegistrar() external view returns (address);

/// @notice Get proxy admin address.
/// @return address of the proxy admin.
function getProxyAdmin() external view returns (address);
}
5 changes: 5 additions & 0 deletions tasks/deploy/deployRegistrar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ task(
apTeamSignerPkey: taskArgs.apTeamSignerPkey,
yes: true,
});
await hre.run("manage:endowmentMultiSigFactory:updateRegistrar", {
registrar: registrar.proxy.contract.address,
apTeamSignerPkey: taskArgs.apTeamSignerPkey,
yes: true,
});

if (!isLocalNetwork(hre) && !taskArgs.skipVerify) {
await verify(hre, registrar.implementation);
Expand Down
6 changes: 3 additions & 3 deletions tasks/helpers/submitMultiSigTx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ import {filterEvents, logger} from "utils";
/**
* Submits a transaction to the designated Multisig contract and executes it if possible.
* @param msAddress address of the Multisig contract
* @param owner signer representing one of the Multisig owners
* @param msOwner signer representing one of the Multisig owners
* @param destination transaction target address
* @param data transaction data payload
* @returns boolean value indicating whether the transaction was executed or not (i.e. is pending confirmation by other owners)
*/
export async function submitMultiSigTx(
msAddress: string,
owner: Signer,
msOwner: Signer,
destination: string,
data: BytesLike
): Promise<boolean> {
logger.out(`Submitting transaction to Multisig at address: ${msAddress}...`);
const multisig = IMultiSigGeneric__factory.connect(msAddress, owner);
const multisig = IMultiSigGeneric__factory.connect(msAddress, msOwner);
const feeData = await multisig.provider.getFeeData();
const tx = await multisig.submitTransaction(destination, 0, data, "0x", {
gasPrice: feeData.gasPrice ?? undefined,
Expand Down
Loading

0 comments on commit 3ba7eb4

Please sign in to comment.