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

Commit

Permalink
Merge pull request #569 from keep-network/fully-backed-member-ban
Browse files Browse the repository at this point in the history
Ban members of FullyBackedBondedECDSAKeep in case of signature fraud

Added functionality of banning keep members in case of a signature fraud 
for FullyBackedECDSAKeeps.

Once a signature fraud is discovered a keep will call the associated factory to 
ban its members. The factory will ban all members in a sortition pool the given keep
has been created for.
  • Loading branch information
pdyraga authored Nov 2, 2020
2 parents 40a0631 + 33a47a9 commit 6ad79be
Show file tree
Hide file tree
Showing 8 changed files with 288 additions and 97 deletions.
7 changes: 5 additions & 2 deletions solidity/contracts/fully-backed/FullyBackedECDSAKeep.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,12 @@ contract FullyBackedECDSAKeep is AbstractBondedECDSAKeep {
bonding.claimDelegatedAuthority(_keepFactory);
}

/// @notice Punishes keep members after proving a signature fraud.
/// @dev Calls the keep factory to ban members of the keep. The owner of the
/// keep is able to seize the members bonds, so no action is necessary to be
/// taken from perspective of this function.
function slashForSignatureFraud() internal {
// TODO: We don't need to do anything as keep owner is able to seize the bonds
// TODO: Ban members (remove from sortition pool and don't let to rejoin)
keepFactory.banKeepMembers();
}

/// @notice Gets the beneficiary for the specified member address.
Expand Down
46 changes: 44 additions & 2 deletions solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,18 @@ contract FullyBackedECDSAKeepFactory is
// in `FullyBackedBonding` contract. Minimum delegation deposit determines
// a minimum value of ether that should be transferred to the bonding contract
// by an owner when delegating to an operator.
uint256 public constant minimumBond = 20 ether;
uint256 public constant defaultMinimumBond = 20 ether;

// Signer candidates in bonded sortition pool are weighted by their eligible
// stake divided by a constant divisor. The divisor is set to 1 ETH so that
// all ETHs in available unbonded value matter when calculating operator's
// eligible weight for signer selection.
uint256 public constant bondWeightDivisor = 1 ether;

// Maps a keep to an application for which the keep was created.
// keep address -> application address
mapping(address => address) keepApplication;

// Notification that a new keep has been created.
event FullyBackedECDSAKeepCreated(
address indexed keepAddress,
Expand All @@ -85,6 +89,10 @@ contract FullyBackedECDSAKeepFactory is
uint256 honestThreshold
);

// Notification when an operator gets banned in a sortition pool for
// an application.
event OperatorBanned(address indexed operator, address indexed application);

constructor(
address _masterKeepAddress,
address _sortitionPoolFactoryAddress,
Expand Down Expand Up @@ -194,6 +202,8 @@ contract FullyBackedECDSAKeepFactory is
);
}

keepApplication[keepAddress] = application;

emit FullyBackedECDSAKeepCreated(
keepAddress,
members,
Expand Down Expand Up @@ -236,11 +246,34 @@ contract FullyBackedECDSAKeepFactory is
return bonding.isAuthorizedForOperator(_operator, address(this));
}

/// @notice Bans members of a calling keep in a sortition pool associated
/// with the application for which the keep was created.
/// @dev The function can be called only by a keep created by this factory.
function banKeepMembers() public onlyKeep() {
FullyBackedECDSAKeep keep = FullyBackedECDSAKeep(msg.sender);

address[] memory members = keep.getMembers();

address application = keepApplication[address(keep)];

FullyBackedSortitionPool sortitionPool = FullyBackedSortitionPool(
getSortitionPool(application)
);

for (uint256 i = 0; i < members.length; i++) {
address operator = members[i];

sortitionPool.ban(operator);

emit OperatorBanned(operator, application);
}
}

function newSortitionPool(address _application) internal returns (address) {
return
sortitionPoolFactory.createSortitionPool(
IFullyBackedBonding(address(bonding)),
minimumBond,
defaultMinimumBond,
bondWeightDivisor
);
}
Expand All @@ -262,4 +295,13 @@ contract FullyBackedECDSAKeepFactory is
// Ex. (100 + 3 - 1) / 3 = 34
return (_keepBond.add(_groupSize).sub(1)).div(_groupSize);
}

/// @notice Checks if caller is a keep created by this factory.
modifier onlyKeep() {
require(
keepOpenedTimestamp[msg.sender] > 0,
"Caller is not a keep created by the factory"
);
_;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ contract FullyBackedECDSAKeepCloneFactoryStub is
{
address public masterKeepAddress;

mapping(address => uint256) public banKeepMembersCalledCount;

constructor(address _masterKeepAddress) public {
masterKeepAddress = _masterKeepAddress;
}
Expand Down Expand Up @@ -49,4 +51,8 @@ contract FullyBackedECDSAKeepCloneFactoryStub is
{
return true;
}

function banKeepMembers() public {
banKeepMembersCalledCount[msg.sender]++;
}
}
4 changes: 4 additions & 0 deletions solidity/contracts/test/FullyBackedECDSAKeepStub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ contract FullyBackedECDSAKeepStub is FullyBackedECDSAKeep {
markAsTerminated();
}

function publicSlashForSignatureFraud() public {
slashForSignatureFraud();
}

function isFradulentPreimageSet(bytes memory preimage)
public
view
Expand Down
2 changes: 2 additions & 0 deletions solidity/test/BondedECDSAKeepFactoryTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ chai.use(require("bn-chai")(BN))
const expect = chai.expect
const assert = chai.assert

// TODO: Refactor tests by pulling common parts of BondedECDSAKeepFactory and
// FullyBackedBondedECDSAKeepFactory to one file.
describe("BondedECDSAKeepFactory", function () {
let registry
let tokenStaking
Expand Down
2 changes: 2 additions & 0 deletions solidity/test/BondedECDSAKeepTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ chai.use(require("bn-chai")(BN))
const expect = chai.expect
const assert = chai.assert

// TODO: Refactor tests by pulling common parts of BondedECDSAKeep and
// FullyBackedBondedECDSAKeep to one file.
describe("BondedECDSAKeep", function () {
const bondCreator = accounts[0]
const owner = accounts[1]
Expand Down
Loading

0 comments on commit 6ad79be

Please sign in to comment.