Skip to content

Commit

Permalink
Cross-chain variable decay
Browse files Browse the repository at this point in the history
  • Loading branch information
area committed Jun 30, 2023
1 parent dbb4e00 commit 22031ec
Show file tree
Hide file tree
Showing 18 changed files with 204 additions and 47 deletions.
10 changes: 7 additions & 3 deletions contracts/colony/Colony.sol
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,9 @@ contract Colony is BasicMetaTransaction, Multicall, ColonyStorage, PatriciaTreeP
bytes memory _skillCreationBefore,
bytes memory _skillCreationAfter,
bytes memory _setReputationRootHashBefore,
bytes memory _setReputationRootHashAfter
bytes memory _setReputationRootHashAfter,
bytes memory _setColonyDecayRateBefore,
bytes memory _setColonyDecayRateAfter
)
external
stoppable
Expand All @@ -241,7 +243,9 @@ contract Colony is BasicMetaTransaction, Multicall, ColonyStorage, PatriciaTreeP
_skillCreationBefore,
_skillCreationAfter,
_setReputationRootHashBefore,
_setReputationRootHashAfter
_setReputationRootHashAfter,
_setColonyDecayRateBefore,
_setColonyDecayRateAfter
);
}

Expand Down Expand Up @@ -346,7 +350,7 @@ contract Colony is BasicMetaTransaction, Multicall, ColonyStorage, PatriciaTreeP
ColonyAuthority colonyAuthority = ColonyAuthority(address(authority));
bytes4 sig;

sig = bytes4(keccak256("setBridgeData(address,uint256,uint256,bytes,bytes,bytes,bytes,bytes,bytes)"));
sig = bytes4(keccak256("setBridgeData(address,uint256,uint256,bytes,bytes,bytes,bytes,bytes,bytes,bytes,bytes)"));
colonyAuthority.setRoleCapability(uint8(ColonyRole.Root), address(this), sig, true);

sig = bytes4(keccak256("setDefaultGlobalClaimDelay(uint256)"));
Expand Down
2 changes: 1 addition & 1 deletion contracts/colony/ColonyAuthority.sol
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ contract ColonyAuthority is CommonAuthority {
addRoleCapability(ARBITRATION_ROLE, "setExpenditurePayout(uint256,uint256,uint256,uint256,address,uint256)");

// Added in colony vxxx
addRoleCapability(ROOT_ROLE, "setBridgeData(address,uint256,uint256,bytes,bytes,bytes,bytes,bytes,bytes)");
addRoleCapability(ROOT_ROLE, "setBridgeData(address,uint256,uint256,bytes,bytes,bytes,bytes,bytes,bytes,bytes,bytes)");
addRoleCapability(ROOT_ROLE, "setDomainReputationScaling(uint256,uint256)");
addRoleCapability(ROOT_ROLE, "setReputationDecayRate(uint256,uint256)");
addRoleCapability(ROOT_ROLE, "setReputationMiningCycleRewardReputationScaling(uint256)");
Expand Down
6 changes: 5 additions & 1 deletion contracts/colony/IMetaColony.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ interface IMetaColony is IColony {
/// @param _skillCreationAfter The tx data after the dynamic part of the tx to brdige skill creation
/// @param _setReputationRootHashBefore The tx data before the dynamic part of the tx to bridge a new reputation root hash
/// @param _setReputationRootHashAfter The tx data after the dynamic part of the tx to bridge a new reputation root hash
/// @param _setColonyDecayRateBefore The tx data before the dynamic part of the tx to set a colony's reputation decay rate
/// @param _setColonyDecayRateAfter The tx data after the dynamic part of the tx to set a colony's reputation decay rate
function setBridgeData(
address _bridgeAddress,
uint256 _chainId,
Expand All @@ -89,6 +91,8 @@ interface IMetaColony is IColony {
bytes memory _skillCreationBefore,
bytes memory _skillCreationAfter,
bytes memory _setReputationRootHashBefore,
bytes memory _setReputationRootHashAfter
bytes memory _setReputationRootHashAfter,
bytes memory _setColonyDecayRateBefore,
bytes memory _setColonyDecayRateAfter
) external;
}
56 changes: 47 additions & 9 deletions contracts/colonyNetwork/ColonyNetwork.sol
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,44 @@ contract ColonyNetwork is ColonyDataTypes, BasicMetaTransaction, ColonyNetworkSt
return payoutWhitelist[_token];
}

function setColonyReputationDecayRate(uint256 _numerator, uint256 _denominator) public calledByColony stoppable {
function setColonyReputationDecayRate(uint256 _numerator, uint256 _denominator) public stoppable calledByColony {
require(_numerator < 10**15, "colony-network-decay-numerator-too-big");
require(_numerator <= _denominator, "colony-network-decay-rate-over-1");

ColonyDecayRate storage decayRate = colonyDecayRates[msgSender()];
if (isMiningChain()){
setColonyReputationDecayRateInternal(0, msgSender(), _numerator, _denominator);
} else {
bridgeColonyDecayRate(_numerator, _denominator);
}
}

function bridgeColonyDecayRate(uint256 _numerator, uint256 _denominator) internal {
// Build the transaction we're going to send to the bridge to register the
// creation of this skill on the home chain

bytes memory payload = abi.encodePacked(
bridgeData[miningBridgeAddress].setColonyDecayRateBefore,
abi.encodeWithSignature("setColonyReputationDecayRateFromBridge(address,uint256,uint256)", msgSender(), _numerator, _denominator),
bridgeData[miningBridgeAddress].setColonyDecayRateAfter
);

// Send bridge transaction
// slither-disable-next-line unchecked-lowlevel
(bool success, ) = miningBridgeAddress.call(payload);
require(success, "colony-network-bridging-transaction-failed");
}

function setColonyReputationDecayRateFromBridge(address _colony, uint256 _numerator, uint256 _denominator) public always
onlyMiningChain
{
uint256 bridgeChainId = bridgeData[msgSender()].chainId;
require(bridgeChainId != 0, "colony-network-not-known-bridge");

setColonyReputationDecayRateInternal(bridgeChainId, _colony, _numerator, _denominator);
}

function setColonyReputationDecayRateInternal(uint256 _chainId, address _colony, uint256 _numerator, uint256 _denominator) internal {
ColonyDecayRate storage decayRate = colonyDecayRates[_chainId][_colony];

if (activeReputationMiningCycle != decayRate.afterMiningCycle) {
// Move the old-next values to current, as they are in effect
Expand All @@ -187,20 +220,25 @@ contract ColonyNetwork is ColonyDataTypes, BasicMetaTransaction, ColonyNetworkSt
decayRate.nextNumerator = _numerator;
decayRate.nextDenominator = _denominator;

emit ColonyReputationDecayRateToChange(msgSender(), activeReputationMiningCycle, _numerator, _denominator);
emit ColonyReputationDecayRateToChange(_chainId, _colony, activeReputationMiningCycle, _numerator, _denominator);
}

function getColonyReputationDecayRate(address _colony) public view returns (uint256, uint256) {
function getColonyReputationDecayRate(uint256 _chainId, address _colony) public view returns (uint256, uint256) {
uint256 numerator;
uint256 denominator;

if (activeReputationMiningCycle != colonyDecayRates[_colony].afterMiningCycle) {
uint256 chainId = _chainId;
if (isMiningChainId(_chainId)){
chainId = 0;
}

if (activeReputationMiningCycle != colonyDecayRates[chainId][_colony].afterMiningCycle) {
// Then the values of interest is whatever's in nextNumerator/nextDenominator
numerator = colonyDecayRates[_colony].nextNumerator;
denominator = colonyDecayRates[_colony].nextDenominator;
numerator = colonyDecayRates[chainId][_colony].nextNumerator;
denominator = colonyDecayRates[chainId][_colony].nextDenominator;
} else {
numerator = colonyDecayRates[_colony].currentNumerator;
denominator = colonyDecayRates[_colony].currentDenominator;
numerator = colonyDecayRates[chainId][_colony].currentNumerator;
denominator = colonyDecayRates[chainId][_colony].currentDenominator;
}

if (denominator == 0) {
Expand Down
6 changes: 5 additions & 1 deletion contracts/colonyNetwork/ColonyNetworkDataTypes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,13 @@ interface ColonyNetworkDataTypes {
event ReputationUpdateStoredFromBridge(uint256 chainId, address colony, uint256 updateNumber);

/// @notice Event logged when a colony sets what its next decay rate is going to be
/// @param chainId The chainId that the colony changing its decay rate is on
/// @dev Note that in the case of the mining chain, this will be 0
/// @param colony The colony changing its decay rate
/// @param fromCycleCompleted When this mining cycle is completed, the new rate will be in effect
/// @param numerator The new numerator of the decay rate
/// @param denominator The new denominator of the decay rate
event ColonyReputationDecayRateToChange(address colony, address fromCycleCompleted, uint256 numerator, uint256 denominator);
event ColonyReputationDecayRateToChange(uint256 chainId, address colony, address fromCycleCompleted, uint256 numerator, uint256 denominator);

struct Skill {
// total number of parent skills
Expand Down Expand Up @@ -235,6 +237,8 @@ interface ColonyNetworkDataTypes {
bytes skillCreationAfter;
bytes setReputationRootHashBefore;
bytes setReputationRootHashAfter;
bytes setColonyDecayRateBefore;
bytes setColonyDecayRateAfter;
}

struct PendingReputationUpdate {
Expand Down
8 changes: 6 additions & 2 deletions contracts/colonyNetwork/ColonyNetworkSkills.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ contract ColonyNetworkSkills is ColonyNetworkStorage, Multicall, ColonyDataTypes
bytes memory _skillCreationBefore,
bytes memory _skillCreationAfter,
bytes memory _setReputationRootHashBefore,
bytes memory _setReputationRootHashAfter
bytes memory _setReputationRootHashAfter,
bytes memory _setColonyDecayRateBefore,
bytes memory _setColonyDecayRateAfter
)
public
always
Expand All @@ -125,7 +127,9 @@ contract ColonyNetworkSkills is ColonyNetworkStorage, Multicall, ColonyDataTypes
_skillCreationBefore,
_skillCreationAfter,
_setReputationRootHashBefore,
_setReputationRootHashAfter
_setReputationRootHashAfter,
_setColonyDecayRateBefore,
_setColonyDecayRateAfter
);

if (networkSkillCounts[_chainId] == 0) {
Expand Down
4 changes: 3 additions & 1 deletion contracts/colonyNetwork/ColonyNetworkStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ contract ColonyNetworkStorage is ColonyNetworkDataTypes, DSMath, CommonStorage,
// networkId -> colonyAddress -> updateCount -> update
mapping(uint256 => mapping( address => mapping(uint256 => PendingReputationUpdate))) pendingReputationUpdates; // Storage slot 48

mapping(address => ColonyDecayRate) colonyDecayRates; // Storage slot 49
// networkId -> colonyAddress -> reputation decay rate
// Note that a network Id of 0 here indicates the mining chain
mapping(uint256 => mapping(address => ColonyDecayRate)) colonyDecayRates; // Storage slot 49

// Modifiers

Expand Down
16 changes: 14 additions & 2 deletions contracts/colonyNetwork/IColonyNetwork.sol
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,8 @@ interface IColonyNetwork is ColonyNetworkDataTypes, IRecovery, IBasicMetaTransac
/// @param _skillCreationAfter The tx data after the dynamic part of the tx to brdige skill creation
/// @param _setReputationRootHashBefore The tx data before the dynamic part of the tx to bridge a new reputation root hash
/// @param _setReputationRootHashAfter The tx data after the dynamic part of the tx to bridge a new reputation root hash
/// @param _setColonyDecayRateBefore The tx data before the dynamic part of the tx to set a colony's reputation decay rate
/// @param _setColonyDecayRateAfter The tx data after the dynamic part of the tx to set a colony's reputation decay rate
function setBridgeData(
address _bridgeAddress,
uint256 _chainId,
Expand All @@ -482,7 +484,9 @@ interface IColonyNetwork is ColonyNetworkDataTypes, IRecovery, IBasicMetaTransac
bytes memory _skillCreationBefore,
bytes memory _skillCreationAfter,
bytes memory _setReputationRootHashBefore,
bytes memory _setReputationRootHashAfter
bytes memory _setReputationRootHashAfter,
bytes memory _setColonyDecayRateBefore,
bytes memory _setColonyDecayRateAfter
) external;

/// @notice Called to get the details about known bridge _bridgeAddress
Expand Down Expand Up @@ -571,11 +575,19 @@ interface IColonyNetwork is ColonyNetworkDataTypes, IRecovery, IBasicMetaTransac
/// @param _denominator The denominator of the fraction reputation does down by every reputation cycle
function setColonyReputationDecayRate(uint256 _numerator, uint256 _denominator) external;

/// @notice Called by a bridge to set the rate at which reputation in a colony on the chain corresponding
/// to that bridge decays
/// @param _colony The colony on the chain in question
/// @param _numerator The numerator of the fraction reputation does down by every reputation cycle
/// @param _denominator The denominator of the fraction reputation does down by every reputation cycle
function setColonyReputationDecayRateFromBridge(address _colony, uint256 _numerator, uint256 _denominator) external;

/// @notice Called to get the rate at which reputation in a colony decays
/// @param _chainId The chainId the colony is deployed on
/// @param _colony The address of the colony in question
/// @return numerator The numerator of the fraction reputation does down by every reputation cycle
/// @return denominator The denominator of the fraction reputation does down by every reputation cycle
function getColonyReputationDecayRate(address _colony) external view returns (uint256 numerator, uint256 denominator);
function getColonyReputationDecayRate(uint256 _chainId, address _colony) external view returns (uint256 numerator, uint256 denominator);

/// @notice Called to get an array containing all parent skill ids of a skill
/// @param _skillId The skill id being queried
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,9 @@ contract ReputationMiningCycleRespond is ReputationMiningCycleCommon {
uint256 numerator;
uint256 denominator;

(numerator, denominator) = IColonyNetwork(colonyNetworkAddress).getColonyReputationDecayRate(logEntry.colony);
// logEntry.skillId >> 128 gives us the chain Id. It's 0 if it's on the mining chain, but that's expected by
// the function.
(numerator, denominator) = IColonyNetwork(colonyNetworkAddress).getColonyReputationDecayRate(logEntry.skillId >> 128, logEntry.colony);
require(uint256(_disagreeStateReputationValue) == (uint256(_agreeStateReputationValue)*numerator)/denominator, "colony-reputation-mining-decay-incorrect");
} else {
if (logEntry.amount >= 0) {
Expand Down
21 changes: 19 additions & 2 deletions docs/interfaces/icolonynetwork.md
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ Get the number of colonies in the network.
|---|---|---|
|_count|uint256|The colony count

### `getColonyReputationDecayRate(address _colony):uint256 numerator, uint256 denominator`
### `getColonyReputationDecayRate(uint256 _chainId, address _colony):uint256 numerator, uint256 denominator`

Called to get the rate at which reputation in a colony decays

Expand All @@ -551,6 +551,7 @@ Called to get the rate at which reputation in a colony decays

|Name|Type|Description|
|---|---|---|
|_chainId|uint256|The chainId the colony is deployed on
|_colony|address|The address of the colony in question

**Return Parameters**
Expand Down Expand Up @@ -1097,7 +1098,7 @@ Used to track that a user is eligible to claim a reward
|_amount|uint256|The amount of CLNY to be awarded


### `setBridgeData(address _bridgeAddress, uint256 _chainId, uint256 _gas, bytes memory _updateLogBefore, bytes memory _updateLogAfter, bytes memory _skillCreationBefore, bytes memory _skillCreationAfter, bytes memory _setReputationRootHashBefore, bytes memory _setReputationRootHashAfter)`
### `setBridgeData(address _bridgeAddress, uint256 _chainId, uint256 _gas, bytes memory _updateLogBefore, bytes memory _updateLogAfter, bytes memory _skillCreationBefore, bytes memory _skillCreationAfter, bytes memory _setReputationRootHashBefore, bytes memory _setReputationRootHashAfter, bytes memory _setColonyDecayRateBefore, bytes memory _setColonyDecayRateAfter)`

Called to set the details about bridge _bridgeAddress

Expand All @@ -1115,6 +1116,8 @@ Called to set the details about bridge _bridgeAddress
|_skillCreationAfter|bytes|The tx data after the dynamic part of the tx to brdige skill creation
|_setReputationRootHashBefore|bytes|The tx data before the dynamic part of the tx to bridge a new reputation root hash
|_setReputationRootHashAfter|bytes|The tx data after the dynamic part of the tx to bridge a new reputation root hash
|_setColonyDecayRateBefore|bytes|The tx data before the dynamic part of the tx to set a colony's reputation decay rate
|_setColonyDecayRateAfter|bytes|The tx data after the dynamic part of the tx to set a colony's reputation decay rate


### `setColonyReputationDecayRate(uint256 _numerator, uint256 _denominator)`
Expand All @@ -1130,6 +1133,20 @@ Called by a colony to set the rate at which reputation in that colony decays
|_denominator|uint256|The denominator of the fraction reputation does down by every reputation cycle


### `setColonyReputationDecayRateFromBridge(address _colony, uint256 _numerator, uint256 _denominator)`

Called by a bridge to set the rate at which reputation in a colony on the chain corresponding to that bridge decays


**Parameters**

|Name|Type|Description|
|---|---|---|
|_colony|address|The colony on the chain in question
|_numerator|uint256|The numerator of the fraction reputation does down by every reputation cycle
|_denominator|uint256|The denominator of the fraction reputation does down by every reputation cycle


### `setFeeInverse(uint256 _feeInverse)`

Set the colony network fee to pay. e.g. if the fee is 1% (or 0.01), pass 100 as `_feeInverse`.
Expand Down
4 changes: 3 additions & 1 deletion docs/interfaces/imetacolony.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Mints CLNY in the Meta Colony and transfers them to the colony network. Only all
|_wad|uint256|Amount to mint and transfer to the colony network


### `setBridgeData(address _bridgeAddress, uint256 _chainId, uint256 _gas, bytes memory _updateLogBefore, bytes memory _updateLogAfter, bytes memory _skillCreationBefore, bytes memory _skillCreationAfter, bytes memory _setReputationRootHashBefore, bytes memory _setReputationRootHashAfter)`
### `setBridgeData(address _bridgeAddress, uint256 _chainId, uint256 _gas, bytes memory _updateLogBefore, bytes memory _updateLogAfter, bytes memory _skillCreationBefore, bytes memory _skillCreationAfter, bytes memory _setReputationRootHashBefore, bytes memory _setReputationRootHashAfter, bytes memory _setColonyDecayRateBefore, bytes memory _setColonyDecayRateAfter)`

Called to set the details about bridge _bridgeAddress

Expand All @@ -91,6 +91,8 @@ Called to set the details about bridge _bridgeAddress
|_skillCreationAfter|bytes|The tx data after the dynamic part of the tx to brdige skill creation
|_setReputationRootHashBefore|bytes|The tx data before the dynamic part of the tx to bridge a new reputation root hash
|_setReputationRootHashAfter|bytes|The tx data after the dynamic part of the tx to bridge a new reputation root hash
|_setColonyDecayRateBefore|bytes|The tx data before the dynamic part of the tx to set a colony's reputation decay rate
|_setColonyDecayRateAfter|bytes|The tx data after the dynamic part of the tx to set a colony's reputation decay rate


### `setNetworkFeeInverse(uint256 _feeInverse)`
Expand Down
5 changes: 3 additions & 2 deletions packages/reputation-miner/ReputationMiner.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,9 @@ class ReputationMiner {

try {
const keyElements = ReputationMiner.breakKeyInToElements(key);
const [colonyAddress, ,] = keyElements;
const colonyDecay = await this.colonyNetwork.getColonyReputationDecayRate(colonyAddress, { blockTag: blockNumber });
const [colonyAddress, skillId,] = keyElements;
const chainId = ethers.BigNumber.from(skillId).div(ethers.BigNumber.from(2).pow(128));
const colonyDecay = await this.colonyNetwork.getColonyReputationDecayRate(chainId, colonyAddress, { blockTag: blockNumber });
numerator = colonyDecay.numerator;
denominator = colonyDecay.denominator;
} catch (err) {
Expand Down
10 changes: 5 additions & 5 deletions test-smoke/colony-storage-consistent.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,11 @@ contract("Contract Storage", (accounts) => {
console.log("miningCycleStateHash:", miningCycleStateHash);
console.log("tokenLockingStateHash:", tokenLockingStateHash);

expect(colonyNetworkStateHash).to.equal("0xd7dc9bb9a60f4e3fc44a25ad2e4a8e0f5d1b36f76d4317813b5e6d62328ccea8");
expect(colonyStateHash).to.equal("0xc92b3b975ee3f2f38c9d983d876d168a028837729b402893cbc4c17b2f56d141");
expect(metaColonyStateHash).to.equal("0xbd9e8b3197dc976414edfe8d5e571176c8972e25d0ea5959612304bcdba46599");
expect(miningCycleStateHash).to.equal("0xde4c01a1aa6922deaa03dfcce207e33cd183d36ef13eae1c74e7bb0c956a5de1");
expect(tokenLockingStateHash).to.equal("0x3e8f3dcc972e7f91042be6650f8526b75067f3d0ea0792cbb56496a10aaecd94");
expect(colonyNetworkStateHash).to.equal("0x62096c76fe7c4f8b9a867abcc57cda42c9a67d319f68fcff6c1d11403e12efaa");
expect(colonyStateHash).to.equal("0x832775449d20ba42f583b1908a65a863af7683c775e2cbf161bbd3083d3a9582");
expect(metaColonyStateHash).to.equal("0x33e9165948005dc0c6e9c172be583327c8db3522b40198c4688d3c61aaf71abb");
expect(miningCycleStateHash).to.equal("0x334d426c446ec22228971e6ccd2d542c4ce72a575fe846972dd058a73276bc81");
expect(tokenLockingStateHash).to.equal("0x2361d9616180cb415ea07c5b9b93297b611ab584181bf71fac148d3269f0c658");
});
});
});
Loading

0 comments on commit 22031ec

Please sign in to comment.