Skip to content

Commit

Permalink
Add ArcUpgradeScheme (#718)
Browse files Browse the repository at this point in the history
* Add ArcUpgradeScheme

* Remove .DS_Store

* Size limits and fixes

* lint

* Rename UpgradeScheme -> ControllerUpgradeScheme

* Bump version

* Use loop for test max contracts upgrade

* Fix test

* Update execute upgrade scheme

* Fix execute

* fix tests
  • Loading branch information
ben-kaufman authored Mar 22, 2020
1 parent 9078a97 commit cc6be2f
Show file tree
Hide file tree
Showing 13 changed files with 815 additions and 299 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ node_modules/
.vscode/
site/
yarn*
.DS_Store
21 changes: 21 additions & 0 deletions contracts/libs/Bytes32ToStr.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
pragma solidity ^0.5.16;

library Bytes32ToStr {
function toStr(bytes32 x) internal pure returns (string memory) {
bytes memory bytesString = new bytes(32);
uint charCount = 0;
uint j;
for (j = 0; j < 32; j++) {
byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
if (char != 0) {
bytesString[charCount] = char;
charCount++;
}
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (j = 0; j < charCount; j++) {
bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}
}
166 changes: 166 additions & 0 deletions contracts/schemes/ControllerUpgradeScheme.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
pragma solidity ^0.5.16;

import "@daostack/infra-experimental/contracts/votingMachines/IntVoteInterface.sol";
import "@daostack/infra-experimental/contracts/votingMachines/ProposalExecuteInterface.sol";
import "../votingMachines/VotingMachineCallbacks.sol";
import "@openzeppelin/upgrades/contracts/Initializable.sol";

/**
* @title A scheme to manage the upgrade of an organization.
* @dev The scheme is used to upgrade the controller of an organization to a new controller.
*/

contract ControllerUpgradeScheme is Initializable, VotingMachineCallbacks, ProposalExecuteInterface {

event NewControllerUpgradeProposal(
address indexed _avatar,
bytes32 indexed _proposalId,
address indexed _intVoteInterface,
address _newController,
string _descriptionHash
);

event ChangeControllerUpgradeSchemeProposal(
address indexed _avatar,
bytes32 indexed _proposalId,
address indexed _intVoteInterface,
address _newControllerUpgradeScheme,
string _descriptionHash
);

event ProposalExecuted(address indexed _avatar, bytes32 indexed _proposalId, int256 _param);
event ProposalDeleted(address indexed _avatar, bytes32 indexed _proposalId);

// Details of an upgrade proposal:
struct UpgradeProposal {
address upgradeContract; // Either the new controller we upgrade to, or the new upgrading scheme.
uint256 proposalType; // 1: Upgrade controller, 2: change upgrade scheme.
}

mapping(bytes32=>UpgradeProposal) public organizationProposals;

IntVoteInterface public votingMachine;
bytes32 public voteParams;
Avatar public avatar;

/**
* @dev initialize
* @param _avatar the avatar this scheme referring to.
* @param _votingMachine the voting machines address to
* @param _voteParams voting machine parameters.
*/
function initialize(
Avatar _avatar,
IntVoteInterface _votingMachine,
bytes32 _voteParams
)
external
initializer
{
require(_avatar != Avatar(0), "avatar cannot be zero");
avatar = _avatar;
votingMachine = _votingMachine;
voteParams = _voteParams;
}

/**
* @dev execution of proposals, can only be called by the voting machine in which the vote is held.
* @param _proposalId the ID of the voting in the voting machine
* @param _param a parameter of the voting result, 1 yes and 2 is no.
*/
function executeProposal(bytes32 _proposalId, int256 _param) external onlyVotingMachine(_proposalId) returns(bool) {
UpgradeProposal memory proposal = organizationProposals[_proposalId];
require(proposal.proposalType != 0);
delete organizationProposals[_proposalId];
emit ProposalDeleted(address(avatar), _proposalId);
// Check if vote was successful:
if (_param == 1) {

// Define controller and get the params:
Controller controller = Controller(avatar.owner());
// Upgrading controller:
if (proposal.proposalType == 1) {
require(controller.upgradeController(proposal.upgradeContract));
}

// Changing upgrade scheme:
if (proposal.proposalType == 2) {
bytes4 permissions = controller.schemesPermissions(address(this));
require(
controller.registerScheme(proposal.upgradeContract, permissions)
);
if (proposal.upgradeContract != address(this)) {
require(controller.unregisterSelf());
}
}
}
emit ProposalExecuted(address(avatar), _proposalId, _param);
return true;
}

/**
* @dev propose an upgrade of the organization's controller
* @param _newController address of the new controller that is being proposed
* @param _descriptionHash proposal description hash
* @return an id which represents the proposal
*/
function proposeUpgrade(address _newController, string memory _descriptionHash)
public
returns(bytes32)
{
bytes32 proposalId = votingMachine.propose(2, voteParams, msg.sender, address(avatar));
UpgradeProposal memory proposal = UpgradeProposal({
proposalType: 1,
upgradeContract: _newController
});
organizationProposals[proposalId] = proposal;
emit NewControllerUpgradeProposal(
address(avatar),
proposalId,
address(votingMachine),
_newController,
_descriptionHash
);
proposalsInfo[address(votingMachine)][proposalId] = ProposalInfo({
blockNumber:block.number,
avatar:avatar
});
return proposalId;
}

/**
* @dev propose to replace this scheme by another controller upgrading scheme
* @param _scheme address of the new upgrading scheme
* @param _descriptionHash proposal description hash
* @return an id which represents the proposal
*/
function proposeChangeControllerUpgradingScheme(
address _scheme,
string memory _descriptionHash
)
public
returns(bytes32)
{
bytes32 proposalId = votingMachine.propose(2, voteParams, msg.sender, address(avatar));
require(organizationProposals[proposalId].proposalType == 0);

UpgradeProposal memory proposal = UpgradeProposal({
proposalType: 2,
upgradeContract: _scheme
});
organizationProposals[proposalId] = proposal;

emit ChangeControllerUpgradeSchemeProposal(
address(avatar),
proposalId,
address(votingMachine),
_scheme,
_descriptionHash
);
proposalsInfo[address(votingMachine)][proposalId] = ProposalInfo({
blockNumber:block.number,
avatar:avatar
});
return proposalId;
}
}
Loading

0 comments on commit cc6be2f

Please sign in to comment.