-
Notifications
You must be signed in to change notification settings - Fork 21
Add CL4RRedeemer #791
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
Add CL4RRedeemer #791
Changes from 8 commits
405b315
de03b8a
92aaaa3
1d609d1
5ef28e7
c82038a
a513ad3
9685d71
aedef91
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
pragma solidity ^0.6.12; | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
import "./ContinuousLocking4Reputation.sol"; | ||
|
||
/** | ||
* @title A scheme for redeeming a ContinuousLocking4Reputation contract used in a different DAO. | ||
* This is used to migrate from an older DAO to a new one while the older DAO has an active ContinuousLocking4Reputation | ||
* Using it should be done by initiaalizing this contract s a scheme in the new DAO, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
* with the old ContinuousLocking4Reputation as an init parameter. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as an init parameter (_ct4r) |
||
* Then the old ContinuousLocking4Reputation should be unregistered as a scheme from the older DAO so | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note : the old ContinuousLocking4Reputation should be unregistered as a scheme from the older .... |
||
* that redeeming is done only through this scheme into the new DAO. | ||
*/ | ||
contract CL4RRedeemer is ArcScheme { | ||
using SafeMath for uint256; | ||
using SafeERC20 for IERC20; | ||
using RealMath for uint216; | ||
using RealMath for uint256; | ||
using Math for uint256; | ||
|
||
event Redeem(uint256 indexed _lockingId, address indexed _beneficiary, uint256 _amount, uint256 _batchIndex); | ||
|
||
struct Batch { | ||
uint256 totalScore; | ||
// A mapping from lockingId to its score | ||
mapping(uint256=>uint) scores; | ||
mapping(uint256=>uint) redeemedScores; | ||
} | ||
|
||
struct Lock { | ||
uint256 amount; | ||
uint256 lockingTime; | ||
uint256 period; | ||
} | ||
|
||
// A mapping from batch index to batch | ||
mapping(uint256 => Batch) public batches; | ||
|
||
uint256 public reputationRewardLeft; // the amount of reputation that is still left to distribute | ||
uint256 public startTime; // the time (in secs since epoch) that locking can start (is enable) | ||
orenyodfat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
uint256 public redeemEnableTime; | ||
uint256 public batchTime; // the length of a batch, in seconds | ||
ContinuousLocking4Reputation public cl4r; | ||
|
||
uint256 constant private REAL_FBITS = 40; | ||
// What's the first non-fractional bit | ||
uint256 constant private REAL_ONE = uint256(1) << REAL_FBITS; | ||
|
||
/** | ||
* @dev initialize | ||
* @param _avatar the avatar to mint reputation from | ||
* @param _cl4r the ContinuousLocking4Reputation address | ||
*/ | ||
function initialize(Avatar _avatar, ContinuousLocking4Reputation _cl4r) external { | ||
super._initialize(_avatar); | ||
require(address(_cl4r) != address(0), "ContinuousLocking4Reputation reference contract must be specified"); | ||
cl4r = _cl4r; | ||
startTime = _cl4r.startTime(); | ||
reputationRewardLeft = _cl4r.reputationRewardLeft(); | ||
redeemEnableTime = _cl4r.redeemEnableTime(); | ||
batchTime = _cl4r.batchTime(); | ||
} | ||
|
||
/** | ||
* @dev redeem reputation function | ||
* @param _beneficiary the beneficiary to redeem. | ||
* @param _lockingId the lockingId to redeem from. | ||
* @return reputation reputation rewarded | ||
*/ | ||
function redeem(address _beneficiary, uint256 _lockingId) public returns(uint256 reputation) { | ||
|
||
// solhint-disable-next-line not-rely-on-time | ||
require(now > redeemEnableTime, "now > redeemEnableTime"); | ||
Lock memory locker = Lock(0, 0, 0); | ||
(locker.amount, locker.lockingTime, locker.period) = cl4r.lockers(_beneficiary, _lockingId); | ||
|
||
require(locker.lockingTime != 0, "_lockingId does not exist"); | ||
uint256 batchIndexToRedeemFrom = (locker.lockingTime - startTime) / batchTime; | ||
// solhint-disable-next-line not-rely-on-time | ||
uint256 currentBatch = (now - startTime) / batchTime; | ||
uint256 lastBatchIndexToRedeem = currentBatch.min(batchIndexToRedeemFrom.add(locker.period)); | ||
for (batchIndexToRedeemFrom; batchIndexToRedeemFrom < lastBatchIndexToRedeem; batchIndexToRedeemFrom++) { | ||
if (batches[batchIndexToRedeemFrom].scores[_lockingId] == 0) { | ||
batches[batchIndexToRedeemFrom].totalScore = cl4r.batches(batchIndexToRedeemFrom); | ||
batches[batchIndexToRedeemFrom].scores[_lockingId] = cl4r.getLockingIdScore( | ||
batchIndexToRedeemFrom, _lockingId | ||
) - batches[batchIndexToRedeemFrom].redeemedScores[_lockingId]; | ||
batches[ | ||
batchIndexToRedeemFrom | ||
].redeemedScores[_lockingId] += batches[batchIndexToRedeemFrom].scores[_lockingId]; | ||
} | ||
Batch storage locking = batches[batchIndexToRedeemFrom]; | ||
uint256 score = locking.scores[_lockingId]; | ||
if (score > 0) { | ||
locking.scores[_lockingId] = 0; | ||
uint256 batchReputationReward = cl4r.getRepRewardPerBatch(batchIndexToRedeemFrom); | ||
uint256 repRelation = mul(toReal(uint216(score)), batchReputationReward); | ||
uint256 redeemForBatch = div(repRelation, toReal(uint216(locking.totalScore))); | ||
reputation = reputation.add(redeemForBatch); | ||
emit Redeem(_lockingId, _beneficiary, uint256(fromReal(redeemForBatch)), batchIndexToRedeemFrom); | ||
} | ||
} | ||
reputation = uint256(fromReal(reputation)); | ||
require(reputation > 0, "reputation to redeem is 0"); | ||
// check that the reputation is sum zero | ||
reputationRewardLeft = reputationRewardLeft.sub(reputation); | ||
require( | ||
Controller(avatar.owner()) | ||
.mintReputation(reputation, _beneficiary), "mint reputation should succeed"); | ||
} | ||
|
||
/** | ||
* Multiply one real by another. Truncates overflows. | ||
*/ | ||
function mul(uint256 realA, uint256 realB) private pure returns (uint256) { | ||
// When multiplying fixed point in x.y and z.w formats we get (x+z).(y+w) format. | ||
// So we just have to clip off the extra REAL_FBITS fractional bits. | ||
uint256 res = realA * realB; | ||
require(res/realA == realB, "RealMath mul overflow"); | ||
return (res >> REAL_FBITS); | ||
} | ||
|
||
/** | ||
* Convert an integer to a real. Preserves sign. | ||
*/ | ||
function toReal(uint216 ipart) private pure returns (uint256) { | ||
return uint256(ipart) * REAL_ONE; | ||
} | ||
|
||
/** | ||
* Convert a real to an integer. Preserves sign. | ||
*/ | ||
function fromReal(uint256 _realValue) private pure returns (uint216) { | ||
return uint216(_realValue / REAL_ONE); | ||
} | ||
|
||
/** | ||
* Divide one real by another real. Truncates overflows. | ||
*/ | ||
function div(uint256 realNumerator, uint256 realDenominator) private pure returns (uint256) { | ||
// We use the reverse of the multiplication trick: convert numerator from | ||
// x.y to (x+z).(y+w) fixed point, then divide by denom in z.w fixed point. | ||
return uint256((uint256(realNumerator) * REAL_ONE) / uint256(realDenominator)); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is used
- >This contract can be use