Added cancellation of the upgrading if there are errors

pull/270/head
szotov 2018-05-07 11:15:52 +03:00 committed by Kieran R Prasch
parent 060b0b5084
commit f9eb10de60
8 changed files with 287 additions and 62 deletions

View File

@ -15,7 +15,6 @@ contract MinersEscrowInterface {
/**
* @notice Contract for version voting
**/
// TODO there must be a way to cancel upgrade if there are errors
contract Government is Upgradeable {
using SafeMath for uint256;
@ -27,7 +26,8 @@ contract Government is Upgradeable {
event UpgradeCommitted(
uint256 indexed votingNumber,
VotingType indexed votingType,
address indexed newAddress
address indexed newAddress,
bool successful
);
enum VotingState {
@ -104,7 +104,17 @@ contract Government is Upgradeable {
address _newAddress
) public {
require(getVotingState() == VotingState.Finished &&
MinersEscrowInterface(escrow).getLockedTokens(msg.sender) != 0);
MinersEscrowInterface(escrow).getLockedTokens(msg.sender) != 0 &&
(_newAddress != 0x0 &&
(_votingType == VotingType.UpgradeGovernment ||
_votingType == VotingType.UpgradeEscrow ||
_votingType == VotingType.UpgradePolicyManager) ||
_votingType == VotingType.RollbackGovernment &&
previousTarget != 0x0 ||
_votingType == VotingType.RollbackEscrow &&
escrow.previousTarget() != 0x0 ||
_votingType == VotingType.RollbackPolicyManager &&
policyManager.previousTarget() != 0x0));
votingNumber = votingNumber.add(1);
endVotingTimestamp = block.timestamp.add(votingDurationSeconds);
upgradeFinished = false;
@ -136,20 +146,31 @@ contract Government is Upgradeable {
function commitUpgrade() public {
require(getVotingState() == VotingState.UpgradeWaiting);
upgradeFinished = true;
bool upgrade = true;
address callAddress;
if (votingType == VotingType.UpgradeGovernment) {
Dispatcher(address(this)).upgrade(newAddress);
callAddress = address(this);
} else if (votingType == VotingType.UpgradeEscrow) {
escrow.upgrade(newAddress);
callAddress = address(escrow);
} else if (votingType == VotingType.UpgradePolicyManager) {
policyManager.upgrade(newAddress);
callAddress = address(policyManager);
} else if (votingType == VotingType.RollbackGovernment) {
Dispatcher(address(this)).rollback();
upgrade = false;
callAddress = address(this);
} else if (votingType == VotingType.RollbackEscrow) {
escrow.rollback();
upgrade = false;
callAddress = address(escrow);
} else if (votingType == VotingType.RollbackPolicyManager) {
policyManager.rollback();
upgrade = false;
callAddress = address(policyManager);
}
emit UpgradeCommitted(votingNumber, votingType, newAddress);
bool result;
if (upgrade) {
result = callAddress.call(bytes4(keccak256("upgrade(address)")), newAddress);
} else {
result = callAddress.call(bytes4(keccak256("rollback()")));
}
emit UpgradeCommitted(votingNumber, votingType, newAddress, result);
}
function verifyState(address _testTarget) public onlyOwner {

View File

@ -86,15 +86,15 @@ contract MinersEscrowForPolicyMock {
/**
* @notice Emulate getDowntimeLength
**/
function getDowntimeLength(address _miner) public returns (uint256) {
function getDowntimeLength(address) public view returns (uint256) {
return downtime.length;
}
/**
* @notice Emulate getDowntime
**/
function getDowntime(address _miner, uint256 _index)
public returns (uint256 startPeriod, uint256 endPeriod)
function getDowntime(address, uint256 _index)
public view returns (uint256 startPeriod, uint256 endPeriod)
{
Downtime storage data = downtime[_index];
startPeriod = data.startPeriod;
@ -104,8 +104,8 @@ contract MinersEscrowForPolicyMock {
/**
* @notice Emulate minerInfo
**/
function minerInfo(address _miner)
public returns (uint256, uint256, uint256, uint256, uint256 result)
function minerInfo(address)
public view returns (uint256, uint256, uint256, uint256, uint256 result)
{
result = lastActivePeriod;
}

View File

@ -13,8 +13,7 @@ contract PolicyManagerBad is PolicyManager {
constructor(MinersEscrow _escrow) public PolicyManager(_escrow) {
}
function getNodeRewardDelta(address _node, uint256 _period)
public view returns (int256)
function getNodeRewardDelta(address, uint256) public view returns (int256)
{
}

View File

@ -29,4 +29,8 @@ contract GovernmentV2Mock is Government {
super.verifyState(_testTarget);
require(uint256(delegateGet(_testTarget, "valueToCheck()")) == valueToCheck);
}
function setPreviousTarget(address _target) public {
previousTarget = _target;
}
}

View File

@ -43,4 +43,8 @@ contract MinersEscrowV1Mock is Upgradeable {
lockedTokens[node] = escrow.lockedTokens(node);
}
}
function setPreviousTarget(address _target) public {
previousTarget = _target;
}
}

View File

@ -9,8 +9,10 @@ import "proxy/Upgradeable.sol";
**/
contract PolicyManagerV1Mock is Upgradeable {
constructor() public {}
function verifyState(address) public {}
function finishUpgrade(address) public {}
function setPreviousTarget(address _target) public {
previousTarget = _target;
}
}

View File

@ -0,0 +1,18 @@
pragma solidity ^0.4.23;
import "proxy/Upgradeable.sol";
/**
* @notice Contract for testing government contract
**/
contract UpgradeableBad is Upgradeable {
function verifyState(address) public {
revert();
}
function finishUpgrade(address) public {}
}

View File

@ -19,7 +19,6 @@ ROLLBACK_POLICY_MANAGER = 5
@pytest.fixture()
def escrow(web3, chain):
creator = web3.eth.accounts[0]
node1 = web3.eth.accounts[1]
node2 = web3.eth.accounts[2]
node3 = web3.eth.accounts[3]
@ -32,28 +31,28 @@ def escrow(web3, chain):
escrow_dispatcher, _ = chain.provider.deploy_contract(
'Dispatcher', escrow_library.address
)
escrow = web3.eth.contract(
contract = web3.eth.contract(
abi=escrow_library.abi,
address=escrow_dispatcher.address,
ContractFactoryClass=Contract)
return escrow
return contract
@pytest.fixture()
def policy_manager(web3, chain):
creator = web3.eth.accounts[0]
# Creator deploys the escrow
policy_manager, _ = chain.provider.deploy_contract('PolicyManagerV1Mock')
dispatcher, _ = chain.provider.deploy_contract('Dispatcher', policy_manager.address)
return dispatcher
contract, _ = chain.provider.deploy_contract('PolicyManagerV1Mock')
dispatcher, _ = chain.provider.deploy_contract('Dispatcher', contract.address)
contract = web3.eth.contract(
abi=contract.abi,
address=dispatcher.address,
ContractFactoryClass=Contract)
return contract
@pytest.mark.slow
def test_voting(web3, chain, escrow, policy_manager):
creator = web3.eth.accounts[0]
node1 = web3.eth.accounts[1]
node2 = web3.eth.accounts[2]
node3 = web3.eth.accounts[3]
creator, node1, node2, node3, *everyone_else = web3.eth.accounts
# Deploy contract
government_library, _ = chain.provider.deploy_contract(
@ -72,13 +71,13 @@ def test_voting(web3, chain, escrow, policy_manager):
upgrade_committed_log = government.events.UpgradeCommitted.createFilter(fromBlock='latest')
# Transfer ownership
tx = government.functions.transferOwnership(government.address).transact({'from': creator})
tx = government.functions.transferOwnership(government.address).transact({'from': creator})
chain.wait_for_receipt(tx)
# Check that there are no voting before it's creation
assert FINISHED_STATE == government.functions.getVotingState().call()
with pytest.raises((TransactionFailed, ValueError)):
tx = government.functions.vote(True).transact({'from': node1})
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = government.functions.commitUpgrade().transact({'from': creator})
@ -116,11 +115,11 @@ def test_voting(web3, chain, escrow, policy_manager):
chain.wait_for_receipt(tx)
# Nodes vote against update
tx = government.functions.vote(True).transact({'from': node1})
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
assert 1 == government.functions.votesFor().call()
assert 0 == government.functions.votesAgainst().call()
tx = government.functions.vote(False).transact({'from': node2})
tx = government.functions.vote(False).transact({'from': node2})
chain.wait_for_receipt(tx)
assert 1 == government.functions.votesFor().call()
assert 2 == government.functions.votesAgainst().call()
@ -128,7 +127,7 @@ def test_voting(web3, chain, escrow, policy_manager):
# Can't vote again
with pytest.raises((TransactionFailed, ValueError)):
tx = government.functions.vote(False).transact({'from': node2})
tx = government.functions.vote(False).transact({'from': node2})
chain.wait_for_receipt(tx)
# Wait until the end of voting
@ -139,7 +138,7 @@ def test_voting(web3, chain, escrow, policy_manager):
# Can't vote after the ending
with pytest.raises((TransactionFailed, ValueError)):
tx = government.functions.vote(False).transact({'from': node3})
tx = government.functions.vote(False).transact({'from': node3})
chain.wait_for_receipt(tx)
# Can't commit upgrade because nodes votes against upgrade
with pytest.raises((TransactionFailed, ValueError)):
@ -178,8 +177,8 @@ def test_voting(web3, chain, escrow, policy_manager):
chain.wait_for_receipt(tx)
# Can't create new voting before upgrading
with pytest.raises((TransactionFailed, ValueError)):
tx = government.transact({'from': creator}).createVoting(
UPGRADE_GOVERNMENT, government_library_v2.address)
tx = government.functions.createVoting(UPGRADE_GOVERNMENT, government_library_v2.address)\
.transact({'from': creator})
chain.wait_for_receipt(tx)
# Commit upgrade
@ -189,8 +188,7 @@ def test_voting(web3, chain, escrow, policy_manager):
assert government_library_v2.address == government_dispatcher.functions.target().call()
# Create voting for update Government contract again without voting
tx = government.transact({'from': node2}).createVoting(
UPGRADE_GOVERNMENT, government_library.address)
tx = government.functions.createVoting(UPGRADE_GOVERNMENT, government_library.address).transact({'from': node2})
chain.wait_for_receipt(tx)
assert 3 == government.functions.votingNumber().call()
assert ACTIVE_STATE == government.functions.getVotingState().call()
@ -207,11 +205,11 @@ def test_voting(web3, chain, escrow, policy_manager):
assert 4 == government.functions.votingNumber().call()
assert ACTIVE_STATE == government.functions.getVotingState().call()
tx = government.functions.vote(False).transact({'from': node1})
tx = government.functions.vote(False).transact({'from': node1})
chain.wait_for_receipt(tx)
tx = government.functions.vote(False).transact({'from': node2})
tx = government.functions.vote(False).transact({'from': node2})
chain.wait_for_receipt(tx)
tx = government.functions.vote(True).transact({'from': node3})
tx = government.functions.vote(True).transact({'from': node3})
chain.wait_for_receipt(tx)
assert 3 == government.functions.votesFor().call()
assert 3 == government.functions.votesAgainst().call()
@ -266,13 +264,34 @@ def test_upgrade(web3, chain, escrow, policy_manager):
policy_manager_library_v2 = policy_manager_library_v2.address
# Transfer ownership
tx = government.functions.transferOwnership(government.address).transact({'from': creator})
tx = government.functions.transferOwnership(government.address).transact({'from': creator})
chain.wait_for_receipt(tx)
tx = escrow.functions.transferOwnership(government.address).transact({'from': creator})
tx = escrow.functions.transferOwnership(government.address).transact({'from': creator})
chain.wait_for_receipt(tx)
tx = policy_manager.functions.transferOwnership(government.address).transact({'from': creator})
tx = policy_manager.functions.transferOwnership(government.address).transact({'from': creator})
chain.wait_for_receipt(tx)
# Can't create upgrade to the zero address
with pytest.raises((TransactionFailed, ValueError)):
tx = government.functions.createVoting(UPGRADE_GOVERNMENT, NULL_ADDR).transact({'from': node1})
chain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = government.functions.createVoting(UPGRADE_ESCROW, NULL_ADDR).transact({'from': node1})
chain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = government.functions.createVoting(UPGRADE_POLICY_MANAGER, NULL_ADDR).transact({'from': node1})
chain.wait_for_receipt(tx)
# Can't rollback if no previous version
with pytest.raises((TransactionFailed, ValueError)):
tx = government.functions.createVoting(ROLLBACK_GOVERNMENT, NULL_ADDR).transact({'from': node1})
chain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = government.functions.createVoting(ROLLBACK_ESCROW, NULL_ADDR).transact({'from': node1})
chain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = government.functions.createVoting(ROLLBACK_POLICY_MANAGER, NULL_ADDR).transact({'from': node1})
chain.wait_for_receipt(tx)
# Vote and upgrade government contract
tx = government.functions.createVoting(UPGRADE_GOVERNMENT, government_library_v2.address).transact({'from': node1})
chain.wait_for_receipt(tx)
@ -284,23 +303,23 @@ def test_upgrade(web3, chain, escrow, policy_manager):
assert UPGRADE_GOVERNMENT == event_args['votingType']
assert government_library_v2.address == event_args['newAddress']
tx = government.functions.vote(True).transact({'from': node1})
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
chain.time_travel(1)
tx = government.functions.commitUpgrade().transact({'from': node1})
chain.wait_for_receipt(tx)
assert government_library_v2.address == government_dispatcher.functions.target().call()
assert government_library_v2.address == government.functions.target().call()
events = government.events.UpgradeCommitted()
events = upgrade_committed_log.get_all_entries()
assert 1 == len(events)
event_args = events[0]['args']
assert 1 == event_args['votingNumber']
assert UPGRADE_GOVERNMENT == event_args['votingType']
assert government_library_v2.address == event_args['newAddress']
assert event_args['successful']
# Vote and rollback government contract
tx = government.functions.createVoting(ROLLBACK_GOVERNMENT, NULL_ADDR).transact({'from': node1})
tx = government.functions.createVoting(ROLLBACK_GOVERNMENT, NULL_ADDR).transact({'from': node1})
chain.wait_for_receipt(tx)
events = voting_created_log.get_all_entries()
@ -310,7 +329,7 @@ def test_upgrade(web3, chain, escrow, policy_manager):
assert ROLLBACK_GOVERNMENT == event_args['votingType']
assert NULL_ADDR == event_args['newAddress']
tx = government.functions.vote(True).transact({'from': node1})
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
chain.time_travel(1)
tx = government.functions.commitUpgrade().transact({'from': node1})
@ -323,6 +342,7 @@ def test_upgrade(web3, chain, escrow, policy_manager):
assert 2 == event_args['votingNumber']
assert ROLLBACK_GOVERNMENT == event_args['votingType']
assert NULL_ADDR == event_args['newAddress']
assert event_args['successful']
# Vote and upgrade escrow contract
tx = government.functions.createVoting(UPGRADE_ESCROW, escrow_library_v2).transact({'from': node1})
@ -335,7 +355,7 @@ def test_upgrade(web3, chain, escrow, policy_manager):
assert UPGRADE_ESCROW == event_args['votingType']
assert escrow_library_v2 == event_args['newAddress']
tx = government.functions.vote(True).transact({'from': node1})
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
chain.time_travel(1)
tx = government.functions.commitUpgrade().transact({'from': node1})
@ -348,9 +368,10 @@ def test_upgrade(web3, chain, escrow, policy_manager):
assert 3 == event_args['votingNumber']
assert UPGRADE_ESCROW == event_args['votingType']
assert escrow_library_v2 == event_args['newAddress']
assert event_args['successful']
# Vote and rollback escrow contract
tx = government.functions.createVoting(ROLLBACK_ESCROW, NULL_ADDR).transact({'from': node1})
tx = government.functions.createVoting(ROLLBACK_ESCROW, NULL_ADDR).transact({'from': node1})
chain.wait_for_receipt(tx)
events = voting_created_log.get_all_entries()
@ -360,7 +381,7 @@ def test_upgrade(web3, chain, escrow, policy_manager):
assert ROLLBACK_ESCROW == event_args['votingType']
assert NULL_ADDR == event_args['newAddress']
tx = government.functions.vote(True).transact({'from': node1})
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
chain.time_travel(1)
tx = government.functions.commitUpgrade().transact({'from': node1})
@ -374,6 +395,7 @@ def test_upgrade(web3, chain, escrow, policy_manager):
assert 4 == event_args['votingNumber']
assert ROLLBACK_ESCROW == event_args['votingType']
assert NULL_ADDR == event_args['newAddress']
assert event_args['successful']
# Vote and upgrade policy manager contract
tx = government.functions.createVoting(UPGRADE_POLICY_MANAGER, policy_manager_library_v2).transact({'from': node1})
@ -386,7 +408,7 @@ def test_upgrade(web3, chain, escrow, policy_manager):
assert UPGRADE_POLICY_MANAGER == event_args['votingType']
assert policy_manager_library_v2 == event_args['newAddress']
tx = government.functions.vote(True).transact({'from': node1})
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
chain.time_travel(1)
tx = government.functions.commitUpgrade().transact({'from': node1})
@ -399,9 +421,10 @@ def test_upgrade(web3, chain, escrow, policy_manager):
assert 5 == event_args['votingNumber']
assert UPGRADE_POLICY_MANAGER == event_args['votingType']
assert policy_manager_library_v2 == event_args['newAddress']
assert event_args['successful']
# Vote and rollback policy manager contract
tx = government.functions.createVoting(ROLLBACK_POLICY_MANAGER, NULL_ADDR).transact({'from': node1})
tx = government.functions.createVoting(ROLLBACK_POLICY_MANAGER, NULL_ADDR).transact({'from': node1})
chain.wait_for_receipt(tx)
events = voting_created_log.get_all_entries()
@ -411,7 +434,7 @@ def test_upgrade(web3, chain, escrow, policy_manager):
assert ROLLBACK_POLICY_MANAGER == event_args['votingType']
assert NULL_ADDR == event_args['newAddress']
tx = government.functions.vote(True).transact({'from': node1})
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
chain.time_travel(1)
tx = government.functions.commitUpgrade().transact({'from': node1})
@ -424,6 +447,160 @@ def test_upgrade(web3, chain, escrow, policy_manager):
assert 6 == event_args['votingNumber']
assert ROLLBACK_POLICY_MANAGER == event_args['votingType']
assert NULL_ADDR == event_args['newAddress']
assert event_args['successful']
def test_cancel_upgrading(web3, chain, escrow, policy_manager):
creator = web3.eth.accounts[0]
node1 = web3.eth.accounts[1]
# Deploy contract
government_library, _ = chain.provider.deploy_contract(
'GovernmentV2Mock', escrow.address, policy_manager.address, 1,
)
government_dispatcher, _ = chain.provider.deploy_contract(
'Dispatcher', government_library.address
)
government = web3.eth.contract(
abi=government_library.abi,
address=government_dispatcher.address,
ContractFactoryClass=Contract
)
escrow_library = escrow.functions.target().call()
policy_manager_library = policy_manager.functions.target().call()
upgradeable_bad, _ = chain.provider.deploy_contract('UpgradeableBad')
upgrade_committed_log = government.events.UpgradeCommitted.createFilter(fromBlock=0)
tx = government.functions.transferOwnership(government.address).transact({'from': creator})
chain.wait_for_receipt(tx)
# Vote to upgrade to the bad government contract
tx = government.functions.createVoting(UPGRADE_GOVERNMENT, upgradeable_bad.address).transact({'from': node1})
chain.wait_for_receipt(tx)
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
chain.time_travel(1)
# Upgrading failed and canceled
tx = government.functions.commitUpgrade().transact({'from': node1})
chain.wait_for_receipt(tx)
assert FINISHED_STATE == government.functions.getVotingState().call()
assert government_library.address == government_dispatcher.functions.target().call()
events = upgrade_committed_log.get_all_entries()
assert 1 == len(events)
event_args = events[0]['args']
assert 1 == event_args['votingNumber']
assert UPGRADE_GOVERNMENT == event_args['votingType']
assert upgradeable_bad.address == event_args['newAddress']
assert not event_args['successful']
# Vote to bad rollback
tx = government.functions.setPreviousTarget(upgradeable_bad.address).transact({'from': node1})
chain.wait_for_receipt(tx)
tx = government.functions.createVoting(ROLLBACK_GOVERNMENT, NULL_ADDR).transact({'from': node1})
chain.wait_for_receipt(tx)
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
chain.time_travel(1)
# Rollback failed and canceled
tx = government.functions.commitUpgrade().transact({'from': node1})
chain.wait_for_receipt(tx)
assert FINISHED_STATE == government.functions.getVotingState().call()
assert government_library.address == government.functions.target().call()
events = upgrade_committed_log.get_all_entries()
assert 2 == len(events)
event_args = events[1]['args']
assert 2 == event_args['votingNumber']
assert ROLLBACK_GOVERNMENT == event_args['votingType']
assert not event_args['successful']
# Vote to upgrade to the bad escrow contract
tx = government.functions.createVoting(UPGRADE_ESCROW, upgradeable_bad.address).transact({'from': node1})
chain.wait_for_receipt(tx)
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
chain.time_travel(1)
# Upgrading failed and canceled
tx = government.functions.commitUpgrade().transact({'from': node1})
chain.wait_for_receipt(tx)
assert FINISHED_STATE == government.functions.getVotingState().call()
assert escrow_library == escrow.functions.target().call()
events = upgrade_committed_log.get_all_entries()
assert 3 == len(events)
event_args = events[2]['args']
assert 3 == event_args['votingNumber']
assert UPGRADE_ESCROW == event_args['votingType']
assert upgradeable_bad.address == event_args['newAddress']
assert not event_args['successful']
# Vote to bad rollback
tx = escrow.functions.setPreviousTarget(upgradeable_bad.address).transact({'from': node1})
chain.wait_for_receipt(tx)
tx = government.functions.createVoting(ROLLBACK_ESCROW, NULL_ADDR).transact({'from': node1})
chain.wait_for_receipt(tx)
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
chain.time_travel(1)
# Rollback failed and canceled
tx = government.functions.commitUpgrade().transact({'from': node1})
chain.wait_for_receipt(tx)
assert FINISHED_STATE == government.functions.getVotingState().call()
assert escrow_library == escrow.functions.target().call()
events = upgrade_committed_log.get_all_entries()
assert 4 == len(events)
event_args = events[3]['args']
assert 4 == event_args['votingNumber']
assert ROLLBACK_ESCROW == event_args['votingType']
assert not event_args['successful']
# Vote to upgrade to the bad policy manager contract
tx = government.functions.createVoting(UPGRADE_POLICY_MANAGER, upgradeable_bad.address).transact({'from': node1})
chain.wait_for_receipt(tx)
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
chain.time_travel(1)
# Upgrading failed and canceled
tx = government.functions.commitUpgrade().transact({'from': node1})
chain.wait_for_receipt(tx)
assert FINISHED_STATE == government.functions.getVotingState().call()
assert policy_manager_library == policy_manager.functions.target().call()
events = upgrade_committed_log.get_all_entries()
assert 5 == len(events)
event_args = events[4]['args']
assert 5 == event_args['votingNumber']
assert UPGRADE_POLICY_MANAGER == event_args['votingType']
assert upgradeable_bad.address == event_args['newAddress']
assert not event_args['successful']
# Vote to bad rollback
tx = policy_manager.functions.setPreviousTarget(upgradeable_bad.address).transact({'from': node1})
chain.wait_for_receipt(tx)
tx = government.functions.createVoting(ROLLBACK_POLICY_MANAGER, NULL_ADDR).transact({'from': node1})
chain.wait_for_receipt(tx)
tx = government.functions.vote(True).transact({'from': node1})
chain.wait_for_receipt(tx)
chain.time_travel(1)
# Rollback failed and canceled
tx = government.functions.commitUpgrade().transact({'from': node1})
chain.wait_for_receipt(tx)
assert FINISHED_STATE == government.functions.getVotingState().call()
assert policy_manager_library == policy_manager.functions.target().call()
events = upgrade_committed_log.get_all_entries()
assert 6 == len(events)
event_args = events[5]['args']
assert 6 == event_args['votingNumber']
assert ROLLBACK_POLICY_MANAGER == event_args['votingType']
assert not event_args['successful']
@pytest.mark.slow
@ -450,23 +627,23 @@ def test_verifying_state(web3, chain):
ContractFactoryClass=Contract)
# Upgrade to the second version
tx = government_dispatcher.functions.upgrade(government_library_v2.address).transact({'from': creator})
tx = government_dispatcher.functions.upgrade(government_library_v2.address).transact({'from': creator})
chain.wait_for_receipt(tx)
assert government_library_v2.address == government_dispatcher.functions.target().call()
assert address2 == government.functions.escrow().call()
assert address1 == government.functions.policyManager().call()
assert 2 * 60 * 60 == government.functions.votingDurationSeconds().call()
tx = government.functions.setValueToCheck(3).transact({'from': creator})
tx = government.functions.setValueToCheck(3).transact({'from': creator})
chain.wait_for_receipt(tx)
assert 3 == government.functions.valueToCheck().call()
# Can't upgrade to the previous version or to the bad version
government_library_bad, _ = chain.provider.deploy_contract('GovernmentBad')
with pytest.raises((TransactionFailed, ValueError)):
tx = government_dispatcher.functions.upgrade(government_library_v1.address).transact({'from': creator})
tx = government_dispatcher.functions.upgrade(government_library_v1.address).transact({'from': creator})
chain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = government_dispatcher.functions.upgrade(government_library_bad.address).transact({'from': creator})
tx = government_dispatcher.functions.upgrade(government_library_bad.address).transact({'from': creator})
chain.wait_for_receipt(tx)
# But can rollback
@ -477,10 +654,10 @@ def test_verifying_state(web3, chain):
assert address2 == government.functions.policyManager().call()
assert 60 * 60 == government.functions.votingDurationSeconds().call()
with pytest.raises((TransactionFailed, ValueError)):
tx = government.functions.setValueToCheck(2).transact({'from': creator})
tx = government.functions.setValueToCheck(2).transact({'from': creator})
chain.wait_for_receipt(tx)
# Try to upgrade to the bad version
with pytest.raises((TransactionFailed, ValueError)):
tx = government_dispatcher.functions.upgrade(government_library_bad.address).transact({'from': creator})
tx = government_dispatcher.functions.upgrade(government_library_bad.address).transact({'from': creator})
chain.wait_for_receipt(tx)