Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bookkeeping and querying around mining stakes #1016

Merged
merged 2 commits into from
Feb 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions contracts/colonyNetwork/ColonyNetworkMining.sol
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ contract ColonyNetworkMining is ColonyNetworkStorage, MultiChain {

ITokenLocking(tokenLocking).deposit(clnyToken, 0, true); // Faux deposit to clear any locks
for (uint256 i = 0; i < _stakers.length; i++) {
lostStake = min(ITokenLocking(tokenLocking).getObligation(_stakers[i], clnyToken, address(this)), _amount);
lostStake = min(miningStakes[_stakers[i]].amount, _amount);
miningStakes[_stakers[i]].amount = sub(miningStakes[_stakers[i]].amount, lostStake);
ITokenLocking(tokenLocking).transferStake(_stakers[i], lostStake, clnyToken, address(this));
// TODO: Lose rep?
emit ReputationMinerPenalised(_stakers[i], lostStake);
Expand All @@ -243,12 +244,11 @@ contract ColonyNetworkMining is ColonyNetworkStorage, MultiChain {

function stakeForMining(uint256 _amount) public stoppable {
address clnyToken = IMetaColony(metaColony).getToken();
uint256 existingObligation = ITokenLocking(tokenLocking).getObligation(msg.sender, clnyToken, address(this));

ITokenLocking(tokenLocking).approveStake(msg.sender, _amount, clnyToken);
ITokenLocking(tokenLocking).obligateStake(msg.sender, _amount, clnyToken);

miningStakes[msg.sender].timestamp = getNewTimestamp(existingObligation, _amount, miningStakes[msg.sender].timestamp, block.timestamp);
miningStakes[msg.sender].timestamp = getNewTimestamp(miningStakes[msg.sender].amount, _amount, miningStakes[msg.sender].timestamp, block.timestamp);
miningStakes[msg.sender].amount = add(miningStakes[msg.sender].amount, _amount);
}

Expand Down
4 changes: 2 additions & 2 deletions contracts/reputationMiningCycle/ReputationMiningCycle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ contract ReputationMiningCycle is ReputationMiningCycleCommon {
/// @param _jrh The justification root hash for the application of the log being processed.
/// @param _entryIndex The number of the entry the submitter hash asked us to consider.
function checkEntryQualifies(address _minerAddress, bytes32 _newHash, uint256 _nLeaves, bytes32 _jrh, uint256 _entryIndex) internal {
uint256 lockBalance = ITokenLocking(tokenLockingAddress).getObligation(_minerAddress, clnyTokenAddress, colonyNetworkAddress);
require(_entryIndex <= lockBalance / MIN_STAKE, "colony-reputation-mining-stake-minimum-not-met-for-index");
uint256 stakedForMining = IColonyNetwork(colonyNetworkAddress).getMiningStake(_minerAddress).amount;
require(_entryIndex <= stakedForMining / MIN_STAKE, "colony-reputation-mining-stake-minimum-not-met-for-index");
require(_entryIndex > 0, "colony-reputation-mining-zero-entry-index-passed");

uint256 stakeTimestamp = IColonyNetwork(colonyNetworkAddress).getMiningStake(_minerAddress).timestamp;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ contract ReputationMiningCycleCommon is ReputationMiningCycleStorage, PatriciaTr

function getMinerAddressIfStaked() internal view returns (address) {
// Is msg.sender a miner themselves? See if they have stake.
uint256 lockBalance = ITokenLocking(tokenLockingAddress).getObligation(msg.sender, clnyTokenAddress, colonyNetworkAddress);
if (lockBalance > 0) {
uint256 stakedForMining = IColonyNetwork(colonyNetworkAddress).getMiningStake(msg.sender).amount;
if (stakedForMining > 0) {
// If so, they we don't let them mine on someone else's behalf
return msg.sender;
}
Expand Down
6 changes: 3 additions & 3 deletions packages/reputation-miner/ReputationMinerClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -557,12 +557,12 @@ class ReputationMinerClient {
const addr = await this._miner.colonyNetwork.getReputationMiningCycle(true);
const repCycle = new ethers.Contract(addr, this._miner.repCycleContractDef.abi, this._miner.realWallet);

const balance = await this._miner.tokenLocking.getObligation(
const miningStake = await this._miner.colonyNetwork.getMiningStake(
this._miner.minerAddress,
this._miner.clnyAddress,
this._miner.colonyNetwork.address
);

const balance = miningStake.amount;

const reputationMiningWindowOpenTimestamp = await repCycle.getReputationMiningWindowOpenTimestamp();
const rootHash = await this._miner.getRootHash();

Expand Down
9 changes: 9 additions & 0 deletions test/reputation-system/root-hash-submissions.js
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,8 @@ contract("Reputation mining - root hash submissions", (accounts) => {
const userLockMiner1Before = await tokenLocking.getUserLock(clnyToken.address, MINER1);
const userLockMiner2Before = await tokenLocking.getUserLock(clnyToken.address, MINER2);
const userLockMiner3Before = await tokenLocking.getUserLock(clnyToken.address, MINER3);
const user2MiningBalanceBefore = await colonyNetwork.getMiningStake(MINER2);
const user3MiningBalanceBefore = await colonyNetwork.getMiningStake(MINER3);

// We want badClient2 to submit the same hash as badClient for this test.
badClient2 = new MaliciousReputationMinerExtraRep({ loader, minerAddress: MINER3, realProviderPort, useJsTree }, 1, "0xfffffffff");
Expand Down Expand Up @@ -673,9 +675,16 @@ contract("Reputation mining - root hash submissions", (accounts) => {
const userLockMiner2 = await tokenLocking.getUserLock(clnyToken.address, MINER2);
expect(userLockMiner2.balance, "Account was not punished properly").to.eq.BN(new BN(userLockMiner2Before.balance).sub(miner2Loss));

// Rewards for defences, however, aren't automatically staked, so they should have lost MIN_STAKE from mining stake
const userMiningBalance2 = await colonyNetwork.getMiningStake(MINER2);
expect(userMiningBalance2.amount, "Mining stake was not docked properly").to.eq.BN(new BN(user2MiningBalanceBefore.amount).sub(MIN_STAKE));

const userLockMiner3 = await tokenLocking.getUserLock(clnyToken.address, MINER3);
expect(userLockMiner3.balance, "Account was not punished properly").to.eq.BN(new BN(userLockMiner3Before.balance).sub(miner3Loss));

const userMiningBalance3 = await colonyNetwork.getMiningStake(MINER3);
expect(userMiningBalance3.amount, "Mining stake was not docked properly").to.eq.BN(new BN(user3MiningBalanceBefore.amount).sub(MIN_STAKE));

// Reset badClient2 to its default behaviour.
badClient2 = new MaliciousReputationMinerExtraRep({ loader, minerAddress: MINER3, realProviderPort, useJsTree }, 1, "0xeeeeeeeee");
});
Expand Down