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

ECDSAKeep Rewards #269

Closed
wants to merge 77 commits into from
Closed

ECDSAKeep Rewards #269

wants to merge 77 commits into from

Conversation

NicholasDotSol
Copy link
Contributor

@NicholasDotSol NicholasDotSol commented Mar 2, 2020

Refs: #446
ECDSAKeep Rewards to distribute KEEP tokens to keep owners based on a predetermined curve separated by intervals.

Draft until:

  • fully tested
  • documented
  • cleaned up
  • optimized

NicholasDotSol added 7 commits March 2, 2020 15:45
Used by ECDSAKeepRewards to get the
owner of the keep, and the time it was opened.
Track all created keeps and timestamps.
These are used for rewards and will
be utilized furhter in the future.
Expose functions to get basic info on keeps and timestamps from the
internal data structures.
stubOpenKeep is an easy way to open a keep with no extra requirements.
It's beneficial when mny keeps are needed
and the initializatoin logic is not important.
Draft of ECDSAKeepRewards. findInterval not implemented.
Test the binary search custom functinality.
@NicholasDotSol NicholasDotSol requested a review from eth-r March 2, 2020 22:11
pdyraga added 4 commits March 14, 2020 15:48
Importing via `@openzeppelin` makes Go bindings code generation fails as
the path for `@openzeppelin` is not configured in the Makefile.

I could add `@openzeppelin` path to the Makefile but since all other
contracts use `openzeppelin-solidity` import, I altered the single
`@openzeppelin` import to `openzeppeling-solidity for consistency.
KeepTerminated event is handled the same way as KeepClosed event exept
that it logs warning on the console.
@pdyraga
Copy link
Member

pdyraga commented Mar 14, 2020

Tested off-chain client against the changes, everything works as expected.

Test log
$ truffle exec integration/smoke_test.js --network local
Using network 'local'.

selecting a keep factory...
validate registered member candidates...
operator [0x65EA55c1f10491038425725dC00dFFEAb2A1e28A] is registered for application [0x146748a2b46B99ee1470b587bc9812Ea59b79597]
operator [0x524f2E0176350d950fA630D9A5a59A0a190DAf48] is registered for application [0x146748a2b46B99ee1470b587bc9812Ea59b79597]
operator [0x3365D0Ed0e526D3B1d8b417fc0fdE5b1cEF2f416] is registered for application [0x146748a2b46B99ee1470b587bc9812Ea59b79597]
opening a new keep for owner [0x7020A5556Ba1ce5f92c81063a13d33512cf1305c]...
open new keep fee: [11516250000000000]
new keep opened with address: [0x5E9033CE4f88cFDaa734ec7F0905e9845771D884] and members: [0x65EA55c1f10491038425725dC00dFFEAb2A1e28A,0x524f2E0176350d950fA630D9A5a59A0a190DAf48,0x3365D0Ed0e526D3B1d8b417fc0fdE5b1cEF2f416]
get public key...
public key generated for keep: [0x35f5c98c67a84590ff5fb6d726c3a88323ae31145571ab1322c523b72495ed9ccac925819b8941e925a2aed35f4ae2a1f0f13d6bad396c5c7919258ffca9eadc]
request signature...
received valid signature:
r: [0x8afe3457efca609b203092667caf77eab48725260862c88b2c230382e6044cb9]
s: [0x059711b2c8ba20265b8c53155050fefbc67d085b1e39330246ada1f9d4576bfd]
recoveryID: [1]

wait for new relay entry generation...
get current group selection seed...
group selection seed was successfully updated by the random beacon
$ cat close_keep.js 
const BondedECDSAKeep = artifacts.require('BondedECDSAKeep.sol');

module.exports = async function() {

    const keepAddress = "0x5E9033CE4f88cFDaa734ec7F0905e9845771D884"
    const keepOwner = "0x7020A5556Ba1ce5f92c81063a13d33512cf1305c"

    try {
        keep = await BondedECDSAKeep.at(keepAddress)
        await keep.closeKeep({from: keepOwner})

        console.log('keep closed')
    } catch(error) {
        console.log(error)
    }
};

$ truffle exec close_keep.js --network local
Using network 'local'.

keep closed

On the client:

17:22:25.344  INFO keep-tecds: keep [0x5E9033CE4f88cFDaa734ec7F0905e9845771D884] closed client.go:310
17:22:25.344  INFO keep-tecds: unsubscribing from events on keep closed client.go:329
$ truffle exec integration/smoke_test.js --network local
Using network 'local'.

Browserslist: caniuse-lite is outdated. Please run next command `npm update`
selecting a keep factory...
validate registered member candidates...
operator [0x65EA55c1f10491038425725dC00dFFEAb2A1e28A] is registered for application [0x146748a2b46B99ee1470b587bc9812Ea59b79597]
operator [0x524f2E0176350d950fA630D9A5a59A0a190DAf48] is registered for application [0x146748a2b46B99ee1470b587bc9812Ea59b79597]
operator [0x3365D0Ed0e526D3B1d8b417fc0fdE5b1cEF2f416] is registered for application [0x146748a2b46B99ee1470b587bc9812Ea59b79597]
opening a new keep for owner [0x7020A5556Ba1ce5f92c81063a13d33512cf1305c]...
open new keep fee: [11516250000000000]
new keep opened with address: [0x9E8E3487dCCd6a50045792fAfe8Ac71600B649a9] and members: [0x3365D0Ed0e526D3B1d8b417fc0fdE5b1cEF2f416,0x65EA55c1f10491038425725dC00dFFEAb2A1e28A,0x524f2E0176350d950fA630D9A5a59A0a190DAf48]
get public key...
public key generated for keep: [0x9d8e332d3ad0eca30cfd1f9304d34d5a40821688e4bcaab333fcd582cbca9de919b30c725541d71d4913f021ed7db3524a25496f4e0ea9af767f0596a51e6999]
request signature...
received valid signature:
r: [0x0a7dfb771d112d99d4ce458b130795e52440aa35bcdecaa4049f39691be35b4a]
s: [0x7b60414653f1251c4ab2dac275fd2bec2a74f421504dcb3f13c61019976a9492]
recoveryID: [1]

wait for new relay entry generation...
get current group selection seed...
group selection seed was successfully updated by the random beacon
$ cat seize_bonds.js 
const BondedECDSAKeep = artifacts.require('BondedECDSAKeep.sol');

module.exports = async function() {

    const keepAddress = "0x9E8E3487dCCd6a50045792fAfe8Ac71600B649a9"
    const keepOwner = "0x7020A5556Ba1ce5f92c81063a13d33512cf1305c"

    try {
        keep = await BondedECDSAKeep.at(keepAddress)
        await keep.seizeSignerBonds({from: keepOwner})

        console.log('bonds seized')
    } catch(error) {
        console.log(error)
    }
};

$ truffle exec seize_bonds.js --network local 
Using network 'local'.

bonds seized

On the client:

17:25:44.352 WARNI keep-tecds: keep [0x9E8E3487dCCd6a50045792fAfe8Ac71600B649a9] terminated client.go:346
17:25:44.353  INFO keep-tecds: unsubscribing from events on keep terminated client.go:365

I still need to go through the Rewards contract.

Copy link
Member

@pdyraga pdyraga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to add more docs and explain in the PR description how this mechanism works.

import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";

contract ECDSAKeepRewards {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth adding some documentation to this contract.

_processKeep(true, keepAddress);
}

function reportTermination(address keepAddress)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add documentation to this function.

Do we expect it's called by parties interested in eventually claiming something from unallocated rewards?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes; the rewards allocated for that keep will be returned to the pool of unallocated rewards.

// Rewards that haven't been allocated to finished intervals
uint256 unallocatedRewards;

// Length of one interval.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... in seconds ?

// Total number of intervals. (Implicit in intervalWeights)
// uint256 termCount = intervalWeights.length;

// mapping of keeps to booleans. True if the keep has been used to calim a reward.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/calim/claim

let keepAddress = await keepFactory.getKeepAtIndex(0)
let eligible = await rewards.eligibleForReward(keepAddress)
expect(eligible).to.equal(false)
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should cover the following cases as well:

  • keep not recognized by the factory,
  • reward already claimed.

}
}

function _getIntervalWeight(uint256 interval) internal view returns (uint256) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is interval weight and why is it 100% for the interval above their count?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interval weight is the percentage of remaining unallocated rewards that are to be allocated for that interval. Once the defined schedule is over, any leftover rewards (e.g. from terminated keeps or division remainders) are allocated to the earliest available interval.

50, // 40:40
25, // 10:30
50, // 15:15
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do understand allocated : remaining relation but I have no idea how does it relate to interval weights. Shouldn't weights add up to 100%?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No; weights are how much of the remaining unallocated rewards are allocated for that interval. After the initially allocated schedule is over, the allocation jumps to 100% meaning that all remaining unallocated rewards are allocated for each closing interval.

let bondedSortitionPoolFactory
let keepBonding
let randomBeacon
let signerPool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not used

const aliceBeneficiary = accounts[2]
const bobBeneficiary = accounts[3]

let factory
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not used


/// @notice Sends the reward for a keep to the keep members.
/// @param keepAddress ECDSA keep factory address.
function receiveReward(address keepAddress)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Who will call this function? From what I understand, it does not make sense to call this function before all previous keeps are closed or terminated. If there is a lot of active keeps, we never know if some of them will be terminated and rewards potentially increased.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of how rewards are allocated for the intervals, the outcome for keeps in a closed interval won't change even if the unallocated amount increases. That means that keeps can call receiveReward as soon as the keep is closed and the interval is over, without needing to wait for other keeps.

@eth-r eth-r requested a review from pdyraga March 17, 2020 15:51
@pdyraga
Copy link
Member

pdyraga commented Mar 28, 2020

I extracted parts about the client, keep and factory contracts to a separate PR: #333. Reviewing this one should be easier once #333 gets merged.

@Shadowfiend Shadowfiend changed the base branch from master to ci-fetch-external May 28, 2020 19:40
@Shadowfiend Shadowfiend changed the base branch from ci-fetch-external to master May 28, 2020 19:40
@pdyraga
Copy link
Member

pdyraga commented Oct 1, 2020

Closing in favor of #513

@pdyraga pdyraga closed this Oct 1, 2020
@pdyraga pdyraga deleted the rewards branch October 1, 2020 08:09
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants