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

Remove unlock penalty and allow redirected accounts to unlock (Opera) #99

Open
wants to merge 5 commits into
base: release/3.0.5-rc.2
Choose a base branch
from
Open
Changes from 4 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
87 changes: 62 additions & 25 deletions contracts/sfc/SFCLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ contract SFCLib is SFCBase {
}

function delegate(uint256 toValidatorID) external payable {
_delegate(msg.sender, toValidatorID, msg.value);
_delegate(_addrToValidator(msg.sender, toValidatorID), toValidatorID, msg.value);
}

function _delegate(address delegator, uint256 toValidatorID, uint256 amount) internal {
Expand All @@ -104,6 +104,9 @@ contract SFCLib is SFCBase {
}

function _rawDelegate(address delegator, uint256 toValidatorID, uint256 amount, bool strict) internal {
// Delegations are disabled to protect current chain while migrating to the new sonic chain
revert("delegation disabled");

require(amount > 0, "zero amount");

_stashRewards(delegator, toValidatorID);
Expand Down Expand Up @@ -154,7 +157,7 @@ contract SFCLib is SFCBase {
}

function undelegate(uint256 toValidatorID, uint256 wrID, uint256 amount) public {
address delegator = msg.sender;
address delegator = _addrToValidator(msg.sender, toValidatorID);

_stashRewards(delegator, toValidatorID);

Expand Down Expand Up @@ -253,7 +256,8 @@ contract SFCLib is SFCBase {
}

function withdraw(uint256 toValidatorID, uint256 wrID) public {
_withdraw(msg.sender, toValidatorID, wrID, _receiverOf(msg.sender));
address payable sender = address(uint160(_addrToValidator(msg.sender, toValidatorID)));
_withdraw(sender, toValidatorID, wrID, _receiverOf(sender));
}

function deactivateValidator(uint256 validatorID, uint256 status) external onlyDriver {
Expand Down Expand Up @@ -380,7 +384,7 @@ contract SFCLib is SFCBase {
}

function claimRewards(uint256 toValidatorID) public {
address payable delegator = msg.sender;
address delegator = _addrToValidator(msg.sender, toValidatorID);
Rewards memory rewards = _claimRewards(delegator, toValidatorID);
// It's important that we transfer after erasing (protection against Re-Entrancy)
(bool sent,) = _receiverOf(delegator).call.value(rewards.lockupExtraReward.add(rewards.lockupBaseReward).add(rewards.unlockedReward))("");
Expand All @@ -390,7 +394,7 @@ contract SFCLib is SFCBase {
}

function restakeRewards(uint256 toValidatorID) public {
address delegator = msg.sender;
address delegator = _addrToValidator(msg.sender, toValidatorID);
Rewards memory rewards = _claimRewards(delegator, toValidatorID);

uint256 lockupReward = rewards.lockupExtraReward.add(rewards.lockupBaseReward);
Expand All @@ -404,8 +408,14 @@ contract SFCLib is SFCBase {
_burnFTM(amount);
}

function burnNativeTokens() external payable {
require(msg.value > 0, "No amount sent");
_burnFTM(msg.value);
}

function _burnFTM(uint256 amount) internal {
if (amount != 0) {
if (amount != 0 && totalSupply >= amount) {
thaarok marked this conversation as resolved.
Show resolved Hide resolved
totalSupply -= amount;
address(0).transfer(amount);
emit BurntFTM(amount);
}
Expand Down Expand Up @@ -434,6 +444,9 @@ contract SFCLib is SFCBase {
}

function _lockStake(address delegator, uint256 toValidatorID, uint256 lockupDuration, uint256 amount, bool relock) internal {
// Locks are disabled due to chain migrating to the new sonic chain
revert("stake lock disabled");

require(!_redirected(delegator), "redirected");
require(amount <= getUnlockedStake(delegator, toValidatorID), "not enough stake");
require(getValidator[toValidatorID].status == OK_STATUS, "validator isn't active");
Expand Down Expand Up @@ -473,38 +486,40 @@ contract SFCLib is SFCBase {
}

function lockStake(uint256 toValidatorID, uint256 lockupDuration, uint256 amount) public {
address delegator = msg.sender;
address delegator = _addrToValidator(msg.sender, toValidatorID);
jmpike marked this conversation as resolved.
Show resolved Hide resolved
require(amount > 0, "zero amount");
require(!isLockedUp(delegator, toValidatorID), "already locked up");
_lockStake(delegator, toValidatorID, lockupDuration, amount, false);
}

function relockStake(uint256 toValidatorID, uint256 lockupDuration, uint256 amount) public {
address delegator = msg.sender;
address delegator = _addrToValidator(msg.sender, toValidatorID);
jmpike marked this conversation as resolved.
Show resolved Hide resolved
require(isLockedUp(delegator, toValidatorID), "not locked up");
_lockStake(delegator, toValidatorID, lockupDuration, amount, true);
}

function _popNonStashedUnlockPenalty(address delegator, uint256 toValidatorID, uint256 unlockAmount, uint256 totalAmount) internal returns (uint256) {
Rewards storage r = getStashedLockupRewards[delegator][toValidatorID];
uint256 lockupExtraRewardShare = r.lockupExtraReward.mul(unlockAmount).div(totalAmount);
uint256 lockupBaseRewardShare = r.lockupBaseReward.mul(unlockAmount).div(totalAmount);
uint256 penalty = lockupExtraRewardShare + lockupBaseRewardShare / 2;
r.lockupExtraReward = r.lockupExtraReward.sub(lockupExtraRewardShare);
r.lockupBaseReward = r.lockupBaseReward.sub(lockupBaseRewardShare);
return penalty;
// Rewards storage r = getStashedLockupRewards[delegator][toValidatorID];
// uint256 lockupExtraRewardShare = r.lockupExtraReward.mul(unlockAmount).div(totalAmount);
// uint256 lockupBaseRewardShare = r.lockupBaseReward.mul(unlockAmount).div(totalAmount);
// uint256 penalty = lockupExtraRewardShare + lockupBaseRewardShare / 2;
// r.lockupExtraReward = r.lockupExtraReward.sub(lockupExtraRewardShare);
// r.lockupBaseReward = r.lockupBaseReward.sub(lockupBaseRewardShare);
// return penalty;
jmpike marked this conversation as resolved.
Show resolved Hide resolved
return 0;
}

function _popStashedUnlockPenalty(address delegator, uint256 toValidatorID, uint256 unlockAmount, uint256 totalAmount) internal returns (uint256) {
_delStalePenalties(delegator, toValidatorID);
Penalty[] storage penalties = getStashedPenalties[delegator][toValidatorID];
uint256 total = 0;
for (uint256 i = 0; i < penalties.length; i++) {
uint256 penalty = penalties[i].amount.mul(unlockAmount).div(totalAmount);
penalties[i].amount = penalties[i].amount.sub(penalty);
total = total.add(penalty);
}
return total;
// Penalty[] storage penalties = getStashedPenalties[delegator][toValidatorID];
// uint256 total = 0;
// for (uint256 i = 0; i < penalties.length; i++) {
// uint256 penalty = penalties[i].amount.mul(unlockAmount).div(totalAmount);
// penalties[i].amount = penalties[i].amount.sub(penalty);
// total = total.add(penalty);
// }
// return total;
jmpike marked this conversation as resolved.
Show resolved Hide resolved
return 0;
}

function _popWholeUnlockPenalty(address delegator, uint256 toValidatorID, uint256 unlockAmount, uint256 totalAmount) internal returns (uint256) {
Expand All @@ -514,14 +529,14 @@ contract SFCLib is SFCBase {
}

function unlockStake(uint256 toValidatorID, uint256 amount) external returns (uint256) {
address delegator = msg.sender;
address delegator = _addrToValidator(msg.sender, toValidatorID);
LockedDelegation storage ld = getLockupInfo[delegator][toValidatorID];

require(amount > 0, "zero amount");
require(isLockedUp(delegator, toValidatorID), "not locked up");
require(amount <= ld.lockedStake, "not enough locked stake");
require(_checkAllowedToWithdraw(delegator, toValidatorID), "outstanding sFTM balance");
require(!_redirected(delegator), "redirected");
// require(!_redirected(delegator), "redirected");

_stashRewards(delegator, toValidatorID);

Expand Down Expand Up @@ -651,6 +666,28 @@ contract SFCLib is SFCBase {
return address(uint160(to));
}

/// Convert an address to validator's address if the address is white-listed address.
/// Converts only to validators managed by Fantom Foundation. It is necessary to enable
/// smooth transition to the new sonic chain.
function _addrToValidator(address addr, uint256 validatorID) internal view returns(address) {
// Fantom's wallet to make requests from
if (addr != 0x0b2E90c831626A65a26f75153Be54aeaAeeb8363) {
return addr;
}

// Fantom's validators <1,11>, 64
if ((validatorID < 1 || validatorID > 11) && validatorID != 64) {
jmpike marked this conversation as resolved.
Show resolved Hide resolved
return addr;
}

address validatorAddr = getValidator[validatorID].auth;
if (validatorAddr == address(0)) {
return addr;
}

return validatorAddr;
}

// code below can be erased after 1 year since deployment of multipenalties

function _getAvgEpochStep(uint256 duration) internal view returns(uint256) {
Expand Down
Loading