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

feat: SWIP 21 #275

Merged
merged 43 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
db72550
add height to staking
0xCardinalError Sep 24, 2024
3d0f535
add height to redistribution contract and apply changes to proximity …
0xCardinalError Sep 24, 2024
56edaea
Fix all the staking tests
0xCardinalError Sep 27, 2024
287dd32
fix redis tests
0xCardinalError Sep 27, 2024
f0b0c98
fix stats
0xCardinalError Sep 27, 2024
d8988a0
add 2 new tests that use height 2 to see if commit and reveal still w…
0xCardinalError Oct 1, 2024
9fba1a2
add height to node effective stake calcualation
0xCardinalError Oct 9, 2024
1263581
remove comment
0xCardinalError Oct 9, 2024
0a545d4
change name of var and also make calc format different:
0xCardinalError Oct 9, 2024
4ca46bf
fix per PR
0xCardinalError Oct 10, 2024
b6b2e3d
Merge branch 'master' of https://github.com/ethersphere/storage-incen…
0xCardinalError Oct 10, 2024
144374f
add change of height test and that it is not failing
0xCardinalError Oct 10, 2024
dae9f0e
finalize tests
0xCardinalError Oct 10, 2024
16280a9
deployment of RC 0.9.2
0xCardinalError Oct 10, 2024
1f1f694
Merge branch 'master' of https://github.com/ethersphere/storage-incen…
0xCardinalError Oct 11, 2024
cdf9d19
add proper event value
0xCardinalError Oct 15, 2024
1bf3e2e
add default price for new postagestamp
0xCardinalError Oct 17, 2024
31d23c1
add new potential stake calculations
0xCardinalError Oct 24, 2024
c10479a
add minimum check
0xCardinalError Oct 24, 2024
d649602
add tests for height and amount checks
0xCardinalError Oct 24, 2024
beaa724
deployment with height calc changes
0xCardinalError Oct 24, 2024
9255242
add price adjustment status if it fails
0xCardinalError Oct 25, 2024
4637fbf
add price update checks
0xCardinalError Oct 25, 2024
1a9033f
add check on WD and that its not failing silently
0xCardinalError Oct 25, 2024
788a31f
order state changing func first
0xCardinalError Oct 25, 2024
1c942b9
comment change
0xCardinalError Oct 25, 2024
32a4bc7
normalize commited stake
0xCardinalError Oct 28, 2024
df15b21
adjust tests to new values
0xCardinalError Oct 28, 2024
e2dbfca
add latest deployment code with normalized commited stake
0xCardinalError Oct 28, 2024
3f53ca3
add for proper testnet deployed contracts
0xCardinalError Oct 28, 2024
2354486
add event for height in commit
0xCardinalError Oct 31, 2024
71c7776
add new redis
0xCardinalError Oct 31, 2024
e60d836
remove extra addy text
0xCardinalError Oct 31, 2024
e006ab2
add comment
0xCardinalError Nov 5, 2024
5c56b50
make a test for increased height and withdrawl
0xCardinalError Nov 6, 2024
e3d3976
test for WD when height changes
0xCardinalError Nov 6, 2024
32f9d4a
add testing for height changes
0xCardinalError Nov 7, 2024
025c379
change stake values only when amount is changed
0xCardinalError Nov 8, 2024
50ff8d2
add tests fixes
0xCardinalError Nov 8, 2024
9c96668
add latest deployment
0xCardinalError Nov 8, 2024
1bc80d4
add WD tests and results
0xCardinalError Nov 26, 2024
20bf3c0
write different scenarios for testing height and stake changes
0xCardinalError Nov 26, 2024
1d911a7
typo
0xCardinalError Dec 3, 2024
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
13 changes: 10 additions & 3 deletions src/Redistribution.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ interface IStakeRegistry {

function overlayOfAddress(address _owner) external view returns (bytes32);

function heightOfAddress(address _owner) external view returns (uint8);

function nodeEffectiveStake(address _owner) external view returns (uint256);
}

Expand Down Expand Up @@ -64,6 +66,7 @@ contract Redistribution is AccessControl, Pausable {
bytes32 overlay;
address owner;
bool revealed;
uint8 height;
uint256 stake;
bytes32 obfuscatedHash;
uint256 revealIndex;
Expand Down Expand Up @@ -281,6 +284,7 @@ contract Redistribution is AccessControl, Pausable {
bytes32 _overlay = Stakes.overlayOfAddress(msg.sender);
uint256 _stake = Stakes.nodeEffectiveStake(msg.sender);
uint256 _lastUpdate = Stakes.lastUpdatedBlockNumberOfAddress(msg.sender);
uint8 _height = Stakes.heightOfAddress(msg.sender);

if (!currentPhaseCommit()) {
revert NotCommitPhase();
Expand Down Expand Up @@ -329,6 +333,7 @@ contract Redistribution is AccessControl, Pausable {
overlay: _overlay,
owner: msg.sender,
revealed: false,
height: _height,
stake: _stake,
obfuscatedHash: _obfuscatedHash,
revealIndex: 0
Expand Down Expand Up @@ -372,9 +377,10 @@ contract Redistribution is AccessControl, Pausable {
bytes32 obfuscatedHash = wrapCommit(_overlay, _depth, _hash, _revealNonce);
uint256 id = findCommit(_overlay, obfuscatedHash);
Commit memory revealedCommit = currentCommits[id];
uint8 depthResponsibility = _depth - revealedCommit.height;
0xCardinalError marked this conversation as resolved.
Show resolved Hide resolved

// Check that commit is in proximity of the current anchor
if (!inProximity(revealedCommit.overlay, currentRevealRoundAnchor, _depth)) {
if (!inProximity(revealedCommit.overlay, currentRevealRoundAnchor, depthResponsibility)) {
revert OutOfDepthReveal(currentRevealRoundAnchor);
}
// Check that the commit has not already been revealed
Expand All @@ -391,7 +397,7 @@ contract Redistribution is AccessControl, Pausable {
owner: revealedCommit.owner,
depth: _depth,
stake: revealedCommit.stake,
stakeDensity: revealedCommit.stake * uint256(2 ** _depth),
stakeDensity: revealedCommit.stake * uint256(2 ** depthResponsibility),
hash: _hash
})
);
Expand Down Expand Up @@ -802,6 +808,7 @@ contract Redistribution is AccessControl, Pausable {
*/
function isParticipatingInUpcomingRound(address _owner, uint8 _depth) public view returns (bool) {
uint256 _lastUpdate = Stakes.lastUpdatedBlockNumberOfAddress(_owner);
uint8 _depthResponsibility = _depth - Stakes.heightOfAddress(_owner);
0xCardinalError marked this conversation as resolved.
Show resolved Hide resolved

if (currentPhaseReveal()) {
revert WrongPhase();
Expand All @@ -815,7 +822,7 @@ contract Redistribution is AccessControl, Pausable {
revert MustStake2Rounds();
}

return inProximity(Stakes.overlayOfAddress(_owner), currentRoundAnchor(), _depth);
return inProximity(Stakes.overlayOfAddress(_owner), currentRoundAnchor(), _depthResponsibility);
}

// ----------------------------- Reveal ------------------------------
Expand Down
46 changes: 36 additions & 10 deletions src/Staking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ contract StakeRegistry is AccessControl, Pausable {
uint256 potentialStake;
// Block height the stake was updated, also used as flag to check if the stake is set
uint256 lastUpdatedBlockNumber;
// Node indicating its increased reserve
uint8 height;
}

// Associate every stake id with node address data.
Expand All @@ -51,14 +53,15 @@ contract StakeRegistry is AccessControl, Pausable {
// ----------------------------- Events ------------------------------

/**
* @dev Emitted when a stake is created or updated by `owner` of the `overlay` by `committedStake`, and `potentialStake` during `lastUpdatedBlock`.
* @dev Emitted when a stake is created or updated by `owner` of the `overlay`.
*/
event StakeUpdated(
address indexed owner,
uint256 committedStake,
uint256 potentialStake,
bytes32 overlay,
uint256 lastUpdatedBlock
uint256 lastUpdatedBlock,
uint8 height
);

/**
Expand Down Expand Up @@ -113,7 +116,7 @@ contract StakeRegistry is AccessControl, Pausable {
* @param _setNonce Nonce that was used for overlay calculation.
* @param _addAmount Deposited amount of ERC20 tokens, equals to added Potential stake value
*/
function manageStake(bytes32 _setNonce, uint256 _addAmount) external whenNotPaused {
function manageStake(bytes32 _setNonce, uint256 _addAmount, uint8 _height) external whenNotPaused {
0xCardinalError marked this conversation as resolved.
Show resolved Hide resolved
bytes32 _previousOverlay = stakes[msg.sender].overlay;
uint256 _stakingSet = stakes[msg.sender].lastUpdatedBlockNumber;
bytes32 _newOverlay = keccak256(abi.encodePacked(msg.sender, reverse(NetworkId), _setNonce));
Expand All @@ -132,13 +135,21 @@ contract StakeRegistry is AccessControl, Pausable {
overlay: _newOverlay,
committedStake: updatedCommittedStake,
potentialStake: updatedPotentialStake,
lastUpdatedBlockNumber: block.number
lastUpdatedBlockNumber: block.number,
height: _height
});

// Transfer tokens and emit event that stake has been updated
if (_addAmount > 0) {
if (!ERC20(bzzToken).transferFrom(msg.sender, address(this), _addAmount)) revert TransferFailed();
emit StakeUpdated(msg.sender, updatedCommittedStake, updatedPotentialStake, _newOverlay, block.number);
emit StakeUpdated(
msg.sender,
updatedCommittedStake,
updatedPotentialStake,
_newOverlay,
block.number,
_height
);
}

// Emit overlay change event
Expand All @@ -153,7 +164,7 @@ contract StakeRegistry is AccessControl, Pausable {
function withdrawFromStake() external {
uint256 _potentialStake = stakes[msg.sender].potentialStake;
uint256 _surplusStake = _potentialStake -
calculateEffectiveStake(stakes[msg.sender].committedStake, _potentialStake);
calculateEffectiveStake(stakes[msg.sender].committedStake, _potentialStake, stakes[msg.sender].height);

if (_surplusStake > 0) {
stakes[msg.sender].potentialStake -= _surplusStake;
Expand Down Expand Up @@ -250,7 +261,11 @@ contract StakeRegistry is AccessControl, Pausable {
function nodeEffectiveStake(address _owner) public view returns (uint256) {
return
addressNotFrozen(_owner)
? calculateEffectiveStake(stakes[_owner].committedStake, stakes[_owner].potentialStake)
? calculateEffectiveStake(
stakes[_owner].committedStake,
stakes[_owner].potentialStake,
stakes[_owner].height
)
: 0;
}

Expand All @@ -259,7 +274,9 @@ contract StakeRegistry is AccessControl, Pausable {
*/
function withdrawableStake() public view returns (uint256) {
uint256 _potentialStake = stakes[msg.sender].potentialStake;
return _potentialStake - calculateEffectiveStake(stakes[msg.sender].committedStake, _potentialStake);
return
_potentialStake -
calculateEffectiveStake(stakes[msg.sender].committedStake, _potentialStake, stakes[msg.sender].height);
}

/**
Expand All @@ -277,12 +294,21 @@ contract StakeRegistry is AccessControl, Pausable {
return stakes[_owner].overlay;
}

/**
* @dev Returns the currently height of the address.
* @param _owner address of node
*/
function heightOfAddress(address _owner) public view returns (uint8) {
return stakes[_owner].height;
}

function calculateEffectiveStake(
uint256 committedStake,
uint256 potentialStakeBalance
uint256 potentialStakeBalance,
uint8 height
) internal view returns (uint256) {
// Calculate the product of committedStake and unitPrice to get price in BZZ
uint256 committedStakeBzz = committedStake * OracleContract.currentPrice();
uint256 committedStakeBzz = (2 ** height) * committedStake * OracleContract.currentPrice();
0xCardinalError marked this conversation as resolved.
Show resolved Hide resolved

// Return the minimum value between committedStakeBzz and potentialStakeBalance
if (committedStakeBzz < potentialStakeBalance) {
Expand Down
72 changes: 61 additions & 11 deletions test/Redistribution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ const depth_0 = '0x06';
const reveal_nonce_0 = '0xb5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33';
const stakeAmount_0 = '100000000000000000';
const effectiveStakeAmount_0 = '99999999999984000';

const obfuscatedHash_0 = '0xb5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33';
const height_0 = 0;
const height_0_n_2 = 2;

//fake
const overlay_f = '0xf4153f4153f4153f4153f4153f4153f4153f4153f4153f4153f4153f4153f415';
Expand All @@ -76,15 +77,19 @@ const nonce_1_n_25 = '0x00000000000000000000000000000000000000000000000000000000
const stakeAmount_1_n_25 = '200000000000000000';
const depth_1 = '0x06';
const reveal_nonce_1 = '0xb5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33';
const height_1 = 0;

let node_2: string;
const overlay_2 = '0xa40db58e368ea6856a24c0264ebd73b049f3dc1c2347b1babc901d3e09842dec';
const stakeAmount_2 = '100000000000000000';
const effectiveStakeAmount_2 = '99999999999984000';
const effectiveStakeAmount_2_n_2 = '100000000000000000';
const nonce_2 = '0xb5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33';
const hash_2 = '0xb5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33';
const depth_2 = '0x06';
const reveal_nonce_2 = '0xb5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33';
const height_2 = 0;
const height_2_n_2 = 2;

let node_3: string;
const overlay_3 = '0xaf217eb0d652baf39ec9464a350c7afc812743fd75ccadf4fcceb6d19a1f190c';
Expand All @@ -93,11 +98,13 @@ const nonce_3 = '0xb5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555
const hash_3 = '0xb5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33';
const depth_3 = '0x06';
const reveal_nonce_3 = '0xb5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33';
const height_3 = 0;
0xCardinalError marked this conversation as resolved.
Show resolved Hide resolved

let node_4: string;
const overlay_4 = '0xaedb2a8007316805b4d64b249ea39c5a1c4a9ce51dc8432724241f41ecb02efb';
const nonce_4 = '0xb5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33';
const depth_4 = '0x06';
const height_4 = 0;
// FDP Play node keys - claim data
// queen node
let node_5: string;
Expand All @@ -107,6 +114,7 @@ const effectiveStakeAmount_5 = '99999999999984000';
const nonce_5 = '0x0000000000000000000000000000000000000000000000000000000000003ba6';
const reveal_nonce_5 = '0xb5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33b5555b33';
const { depth: depth_5, hash: hash_5 } = node5_proof1;
const height_5 = 0;

let node_6: string;
const overlay_6 = '0x141680b0d9c7ab250672fd4603ac13e39e47de6e2c93d71bbdc66459a6c5e39f';
Expand Down Expand Up @@ -236,7 +244,7 @@ describe('Redistribution', function () {
it('should not create a commit with recently staked node', async function () {
const sr_node_0 = await ethers.getContract('StakeRegistry', node_0);
await mintAndApprove(deployer, node_0, sr_node_0.address, stakeAmount_0);
await sr_node_0.manageStake(nonce_0, stakeAmount_0);
await sr_node_0.manageStake(nonce_0, stakeAmount_0, height_0);

expect(await redistribution.currentPhaseCommit()).to.be.true;

Expand All @@ -249,7 +257,20 @@ describe('Redistribution', function () {
it('should create a commit with staked node', async function () {
const sr_node_0 = await ethers.getContract('StakeRegistry', node_0);
await mintAndApprove(deployer, node_0, sr_node_0.address, stakeAmount_0);
await sr_node_0.manageStake(nonce_0, stakeAmount_0);
await sr_node_0.manageStake(nonce_0, stakeAmount_0, height_0);

expect(await redistribution.currentPhaseCommit()).to.be.true;

const r_node_0 = await ethers.getContract('Redistribution', node_0);
await expect(r_node_0['isParticipatingInUpcomingRound(address,uint8)'](node_0, depth_0)).to.be.revertedWith(
errors.commit.stakedRecently
);
});

it('should create a commit with staked node and height 2', async function () {
const sr_node_0 = await ethers.getContract('StakeRegistry', node_0);
await mintAndApprove(deployer, node_0, sr_node_0.address, stakeAmount_0);
await sr_node_0.manageStake(nonce_0, stakeAmount_0, height_0_n_2);

expect(await redistribution.currentPhaseCommit()).to.be.true;

Expand Down Expand Up @@ -308,32 +329,32 @@ describe('Redistribution', function () {

const sr_node_0 = await ethers.getContract('StakeRegistry', node_0);
await mintAndApprove(deployer, node_0, sr_node_0.address, stakeAmount_0);
await sr_node_0.manageStake(nonce_0, stakeAmount_0);
await sr_node_0.manageStake(nonce_0, stakeAmount_0, height_0);

const sr_node_1 = await ethers.getContract('StakeRegistry', node_1);
await mintAndApprove(deployer, node_1, sr_node_1.address, stakeAmount_1);
await sr_node_1.manageStake(nonce_1, stakeAmount_1);
await sr_node_1.manageStake(nonce_1, stakeAmount_1, height_1);

// 16 depth neighbourhood with node_5
const sr_node_1_n_25 = await ethers.getContract('StakeRegistry', node_1);
await mintAndApprove(deployer, node_1, sr_node_1_n_25.address, stakeAmount_1);
await sr_node_1_n_25.manageStake(nonce_1_n_25, stakeAmount_1);
await sr_node_1_n_25.manageStake(nonce_1_n_25, stakeAmount_1, height_1);

const sr_node_2 = await ethers.getContract('StakeRegistry', node_2);
await mintAndApprove(deployer, node_2, sr_node_2.address, stakeAmount_2);
await sr_node_2.manageStake(nonce_2, stakeAmount_2);
await sr_node_2.manageStake(nonce_2, stakeAmount_2, height_2);

const sr_node_3 = await ethers.getContract('StakeRegistry', node_3);
await mintAndApprove(deployer, node_3, sr_node_3.address, stakeAmount_3);
await sr_node_3.manageStake(nonce_3, stakeAmount_3);
await sr_node_3.manageStake(nonce_3, stakeAmount_3, height_4);

const sr_node_4 = await ethers.getContract('StakeRegistry', node_4);
await mintAndApprove(deployer, node_4, sr_node_4.address, stakeAmount_3);
await sr_node_4.manageStake(nonce_4, stakeAmount_3);
await sr_node_4.manageStake(nonce_4, stakeAmount_3, height_4);

const sr_node_5 = await ethers.getContract('StakeRegistry', node_5);
await mintAndApprove(deployer, node_5, sr_node_5.address, stakeAmount_5);
await sr_node_5.manageStake(nonce_5, stakeAmount_5);
await sr_node_5.manageStake(nonce_5, stakeAmount_5, height_5);

// We need to mine 2 rounds to make the staking possible
// as this is the minimum time between staking and committing
Expand Down Expand Up @@ -476,10 +497,39 @@ describe('Redistribution', function () {
});

it('should create a commit with successful reveal if the overlay is within the reported depth', async function () {
const r_node_2 = await ethers.getContract('Redistribution', node_2);

await mineToNode(redistribution, 2);
expect(await redistribution.currentPhaseCommit()).to.be.true;

const obfuscatedHash = encodeAndHash(overlay_2, depth_2, hash_2, reveal_nonce_2);

const currentRound = await r_node_2.currentRound();

await expect(r_node_2.commit(obfuscatedHash, currentRound))
.to.emit(redistribution, 'Committed')
.withArgs(currentRound, overlay_2);

expect((await r_node_2.currentCommits(0)).obfuscatedHash).to.be.eq(obfuscatedHash);

await mineNBlocks(phaseLength);

await r_node_2.reveal(depth_2, hash_2, reveal_nonce_2);

expect((await r_node_2.currentReveals(0)).hash).to.be.eq(hash_2);
expect((await r_node_2.currentReveals(0)).overlay).to.be.eq(overlay_2);
expect((await r_node_2.currentReveals(0)).owner).to.be.eq(node_2);
expect((await r_node_2.currentReveals(0)).stake).to.be.eq(effectiveStakeAmount_2);
expect((await r_node_2.currentReveals(0)).depth).to.be.eq(parseInt(depth_2));
});

it('should create a commit with successful reveal if the overlay is within the reported depth with height 2', async function () {
const r_node_2 = await ethers.getContract('Redistribution', node_2);
const sr_node_2 = await ethers.getContract('StakeRegistry', node_2);
await sr_node_2.manageStake(nonce_2, 0, height_2_n_2);

await mineToNode(redistribution, 2);
expect(await redistribution.currentPhaseCommit()).to.be.true;

const obfuscatedHash = encodeAndHash(overlay_2, depth_2, hash_2, reveal_nonce_2);

Expand All @@ -498,7 +548,7 @@ describe('Redistribution', function () {
expect((await r_node_2.currentReveals(0)).hash).to.be.eq(hash_2);
expect((await r_node_2.currentReveals(0)).overlay).to.be.eq(overlay_2);
expect((await r_node_2.currentReveals(0)).owner).to.be.eq(node_2);
expect((await r_node_2.currentReveals(0)).stake).to.be.eq(effectiveStakeAmount_2);
expect((await r_node_2.currentReveals(0)).stake).to.be.eq(effectiveStakeAmount_2_n_2);
expect((await r_node_2.currentReveals(0)).depth).to.be.eq(parseInt(depth_2));
});

Expand Down
Loading
Loading