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: saner accounting logic #2

Merged
merged 11 commits into from
Apr 9, 2024
Merged

feat: saner accounting logic #2

merged 11 commits into from
Apr 9, 2024

Conversation

gomesalexandre
Copy link
Contributor

@gomesalexandre gomesalexandre commented Apr 8, 2024

See #1 (comment)

This PR:

  • Ensures saner accounting, by making it so that calling requestWithdraw actually doesn't do any complex logic of "withdraw request resets the previous one under x condition, or replaces it under y condition" but instead does some simple accounting i.e decreases the staking balance and increases the unstaking balance.
  • Introduces a new StakingInfo struct containing the staking balance, unstaking balance, and cooldown expiry timestamp, and a stakingInfo() view fn for it
  • Removes cooldownInfo() since this data is now exposed by stakingInfo()
  • balanceOf now behaves as a regular balanceOf i.e "for a given address, give me the amount of tokens I have in the smart contract, regardless of the ramifications of them being still staked and earning rewards, or in the process of being unstaked, with no rewards being earned"

Copy link
Contributor

@0xean 0xean left a comment

Choose a reason for hiding this comment

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

General comments from our team call

@@ -2,7 +2,7 @@
pragma solidity ^0.8.25;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IFoxStaking} from "./IFoxStaking.sol";
import {IFoxStaking, StakingInfo} from "./IFoxStaking.sol";
import {console} from "forge-std/Script.sol";

contract FoxStaking is IFoxStaking {
Copy link
Contributor

Choose a reason for hiding this comment

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

  • for the mappings, no need to have them private, use public so solidity will allow helper functions / getters
  • consider consolidating into a struct, so we only have to index once to get the data for a user
  • COOLDOWN_PERIOD should not be constant, add priviledged setter so governance can modify
    • OZ owner which will be set to the DAO msig after deployment

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

https://github.com/shapeshift/rFOX/pull/2/files#diff-e687f106fe1b3606e04f72cd2e69cc2b1836e3bb0d8f411a12a1501947b9ce6bR18 - Unstake refactored to request withdraw or however we want to make that more clear.

Copy link
Contributor

Choose a reason for hiding this comment

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

IE consistent across function call, event, and mapping / struct values

Copy link
Contributor Author

@gomesalexandre gomesalexandre Apr 9, 2024

Choose a reason for hiding this comment

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

Public mappings: 0fa07ae
Indexed rune addy in event: ae0a1bb
Struct consolidation: 321f1bc
Consistant unstake vernacular: d4e8c2d

foundry/src/FoxStaking.sol Outdated Show resolved Hide resolved
@@ -38,26 +38,18 @@ contract FoxStaking is IFoxStaking {

Copy link
Contributor

Choose a reason for hiding this comment

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

function stake(uint 256) and function stake(uint256, string rune addy)

Copy link
Contributor

Choose a reason for hiding this comment

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

stake(uint256 amt) {
  require(runePairingAddresses[msg.sender] != "")
  stake(amt, runePairingAddresses[msg.sender])
}

Copy link
Contributor

Choose a reason for hiding this comment

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

https://github.com/shapeshift/rFOX/pull/2/files#diff-e687f106fe1b3606e04f72cd2e69cc2b1836e3bb0d8f411a12a1501947b9ce6bR30 - should confirm that whatever token we are using reverts vs returns false here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note, while we can do overload, we cannot call an overloaded function from another arity variant - went back to the previous implementation of stake (not overloaded) taking a runeAddress: 46718e8

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe I oversimplified this in my above comment, it might actually look more like

private _stake(amt) {
do the staking logic
}

external stake(amt) {
// check we have a rune address assigned and then call _stake(amt)
}

external stake(amt, runeAddy) {
// assign new rune addy and then call _stake(amt)
}

also fine with your implementation

foundry/src/FoxStaking.sol Show resolved Hide resolved
foundry/src/FoxStaking.sol Outdated Show resolved Hide resolved
Copy link
Contributor

@0xean 0xean left a comment

Choose a reason for hiding this comment

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

Happy to merge and keep moving forward, but left some other comments around the run e address data type and verification

event Unstake(address indexed account, uint256 amount);
event Withdraw(address indexed account, uint256 amount);
event SetRuneAddress(address indexed account, string newRuneAddress);
event SetRuneAddress(address indexed account, string indexed newRuneAddress);
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure on this one, but do we want to also emit the oldRuneAddress if we are changing it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That would definitely make sense for completeness, nice one


constructor(address foxTokenAddress) {
foxToken = IERC20(foxTokenAddress);
}

function stake(uint256 amount) external {
function stake(uint256 amount, string memory runeAddress) external {
require(bytes(runeAddress).length > 0, "Rune address cannot be empty");
Copy link
Contributor

Choose a reason for hiding this comment

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

can we do better than this? I would imagine rune addresses are specific length / number of bytes so we might be able to

  1. use something like bytes32 depending on thorchain address structure
  2. verify the input is alteast the correct number of bytes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As long as we don't handle THORnames as valid addresses, we can absolutely do this. Will just need to ensure tests use the right format and we're good

@@ -38,26 +38,18 @@ contract FoxStaking is IFoxStaking {

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe I oversimplified this in my above comment, it might actually look more like

private _stake(amt) {
do the staking logic
}

external stake(amt) {
// check we have a rune address assigned and then call _stake(amt)
}

external stake(amt, runeAddy) {
// assign new rune addy and then call _stake(amt)
}

also fine with your implementation

@gomesalexandre
Copy link
Contributor Author

Happy to merge and keep moving forward, but left some other comments around the run e address data type and verification

Ty @0xean ! Will merge, restack and tackle as part of the upmost PR in the stack i.e #13

@gomesalexandre gomesalexandre merged commit 8a7b97e into main Apr 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants