Skip to content

Commit

Permalink
Code organization for XyoChain code
Browse files Browse the repository at this point in the history
  • Loading branch information
arietrouw committed Dec 13, 2024
1 parent 51a7975 commit 211b306
Show file tree
Hide file tree
Showing 18 changed files with 536 additions and 290 deletions.
2 changes: 1 addition & 1 deletion packages/solidity/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@
"publishConfig": {
"access": "public"
}
}
}
38 changes: 38 additions & 0 deletions packages/solidity/src/xyo-chain/AddressStaking/AddressStaking.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;

import "./interface/IAddressStaking.sol";
import "../TransferStake/TransferStake.sol";
import "./AddressStakingProperties.sol";
import "./Library.sol";
import "./Internal.sol";

contract AddressStaking is
IAddressStaking,
TransferStake,
AddressStakingProperties
{
// ========== CONSTRUCTOR ==========

constructor(
uint256 _minWithdrawalBlocks, // The minimum number of blocks that must pass before a pending stake can be withdrawn
address _stakingToken // The token that is used for staking
)
TransferStake(_stakingToken)
AddressStakingProperties(_minWithdrawalBlocks)
{}

// ========== PUBLIC ==========

function addStake(address staked, uint256 amount) public returns (bool) {
return _addStake(staked, amount);
}

function removeStake(uint256 slot) public returns (bool) {
return _removeStake(slot);
}

function withdrawStake(uint256 slot) public returns (bool) {
return _withdrawStake(slot, this.minWithdrawalBlocks());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;

import "./interface/IAddressStakingProperties.sol";
import "./Internal.sol";

abstract contract AddressStakingProperties is
IAddressStakingProperties,
AddressStakingInternal
{
uint256 private __minWithdrawalBlocks;

constructor(
uint256 _minWithdrawalBlocks // The minimum number of blocks that must pass before a pending stake can be withdrawn
) {
__minWithdrawalBlocks = _minWithdrawalBlocks;
}

function minWithdrawalBlocks() external view returns (uint256) {
return __minWithdrawalBlocks;
}

function activeByAddressStaked(
address staked
) external view returns (uint256) {
return _stakeAmountByAddressStaked[staked];
}

function activeByStaker(address staker) external view returns (uint256) {
return AddressStakingLibrary._calcActiveStake(_accountStakes[staker]);
}

function pendingByStaker(address staker) external view returns (uint256) {
return AddressStakingLibrary._calcPendingStake(_accountStakes[staker]);
}

function withdrawnByStalker(
address staker
) external view returns (uint256) {
return
AddressStakingLibrary._calcWithdrawnStake(_accountStakes[staker]);
}

function active() external view returns (uint256) {
return _totalActiveStake;
}

function pending() external view returns (uint256) {
return _totalPendingStake;
}

function withdrawn() external view returns (uint256) {
return _totalWithdrawnStake;
}
}
97 changes: 97 additions & 0 deletions packages/solidity/src/xyo-chain/AddressStaking/Internal.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;

import "./Library.sol";
import "./interface/IAddressStakingEvents.sol";
import "../TransferStake/Abstract.sol";
import "./interface/IAddressStakingProperties.sol";

abstract contract AddressStakingInternal is
IAddressStakingEvents,
AbstractTransferStake
{
uint256 internal _totalActiveStake;

uint256 internal _totalPendingStake;

uint256 internal _totalWithdrawnStake;

//total amount that is staked for a given address
mapping(address => uint256) internal _stakeAmountByAddressStaked;

//total amount that is staked by a given staker
mapping(address => uint256) internal _stakeAmountByStaker;

mapping(address => AddressStakingLibrary.Stake[]) internal _accountStakes;

function _addStake(address staked, uint256 amount) internal returns (bool) {
require(amount > 0, "Staking: amount must be greater than 0");
_transferStakeFromSender(amount);
_accountStakes[msg.sender].push(
AddressStakingLibrary.Stake({
staked: staked,
amount: amount,
addBlock: block.number,
removeBlock: 0,
withdrawBlock: 0
})
);
_totalActiveStake += amount;
_stakeAmountByAddressStaked[staked] += amount;
_stakeAmountByStaker[msg.sender] += amount;
emit StakeAdded(
staked,
msg.sender,
_accountStakes[msg.sender].length - 1,
amount
);
return true;
}

function _removeStake(uint256 slot) internal returns (bool) {
require(
AddressStakingLibrary._isStakeRemovable(
_accountStakes[msg.sender][slot]
),
"Staking: not removable"
);

uint256 amount = _accountStakes[msg.sender][slot].amount;
address staked = _accountStakes[msg.sender][slot].staked;

_accountStakes[msg.sender][slot].removeBlock = block.number;
_totalActiveStake -= amount;
_totalPendingStake += amount;
_stakeAmountByAddressStaked[staked] -= amount;
_stakeAmountByStaker[msg.sender] -= amount;

emit StakeRemoved(staked, msg.sender, slot, amount);
return true;
}

function _withdrawStake(
uint256 slot,
uint256 minWithdrawalBlocks
) internal returns (bool) {
require(
AddressStakingLibrary._isStakeWithdrawable(
_accountStakes[msg.sender][slot],
minWithdrawalBlocks
),
"Staking: not withdrawable"
);

uint256 amount = _accountStakes[msg.sender][slot].amount;
address staked = _accountStakes[msg.sender][slot].staked;

_accountStakes[msg.sender][slot].withdrawBlock = block.number;
_totalPendingStake -= amount;
_totalWithdrawnStake += amount;

_transferStakeToSender(amount);

emit StakeWithdrawn(staked, msg.sender, slot, amount);

return true;
}
}
105 changes: 105 additions & 0 deletions packages/solidity/src/xyo-chain/AddressStaking/Library.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;

library AddressStakingLibrary {
struct Stake {
// the thing that is being staked
address staked;
uint256 amount;
uint256 addBlock;
uint256 removeBlock;
uint256 withdrawBlock;
}

function _activeStakeAmount(
Stake memory stake
) internal pure returns (uint256) {
if (
stake.addBlock > 0 &&
stake.removeBlock == 0 &&
stake.withdrawBlock == 0
) {
return stake.amount;
} else {
return 0;
}
}

function _pendingStakeAmount(
Stake memory stake
) internal pure returns (uint256) {
if (
stake.addBlock > 0 &&
stake.removeBlock > 0 &&
stake.withdrawBlock == 0
) {
return stake.amount;
} else {
return 0;
}
}

function _withdrawnStakeAmount(
Stake memory stake
) internal pure returns (uint256) {
if (
stake.addBlock > 0 &&
stake.removeBlock > 0 &&
stake.withdrawBlock > 0
) {
return stake.amount;
} else {
return 0;
}
}

function _calcActiveStake(
AddressStakingLibrary.Stake[] memory stakes
) internal pure returns (uint256) {
uint total = 0;
for (uint i = 0; i < stakes.length; i++) {
total += _activeStakeAmount(stakes[i]);
}
return total;
}

function _calcPendingStake(
AddressStakingLibrary.Stake[] memory stakes
) internal pure returns (uint256) {
uint total = 0;
for (uint i = 0; i < stakes.length; i++) {
total += _pendingStakeAmount(stakes[i]);
}
return total;
}

function _calcWithdrawnStake(
AddressStakingLibrary.Stake[] memory stakes
) internal pure returns (uint256) {
uint total = 0;
for (uint i = 0; i < stakes.length; i++) {
total += _withdrawnStakeAmount(stakes[i]);
}
return total;
}

function _isStakeRemovable(
AddressStakingLibrary.Stake memory stake
) internal pure returns (bool) {
return
stake.addBlock > 0 &&
stake.removeBlock == 0 &&
stake.withdrawBlock == 0;
}

function _isStakeWithdrawable(
AddressStakingLibrary.Stake memory stake,
uint256 minWithdrawalBlocks
) internal view returns (bool) {
return
stake.addBlock > 0 &&
stake.removeBlock > 0 &&
stake.withdrawBlock == 0 &&
block.number > (stake.removeBlock + minWithdrawalBlocks);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;

import "./IAddressStakingProperties.sol";
import "./IAddressStakingFunctions.sol";
import "./IAddressStakingEvents.sol";

interface IAddressStaking is
IAddressStakingProperties,
IAddressStakingFunctions,
IAddressStakingEvents
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;

interface IAddressStakingEvents {
// This is when a stake is added to the staking contract
event StakeAdded(
address indexed staked,
address indexed by,
uint256 indexed slot,
uint256 amount
);

// This is when a specific stake is requested for removal. It removes it from the staked amount but does not actually remove the XYO from the staking contract
event StakeRemoved(
address indexed staked,
address indexed by,
uint256 indexed slot,
uint256 amount
);

// This is when actual XYO is removed from the staking contract
event StakeWithdrawn(
address indexed staked,
address indexed by,
uint256 indexed slot,
uint256 amount
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;

interface IAddressStakingFunctions {
function addStake(address staked, uint256 amount) external returns (bool);

function removeStake(uint256 slot) external returns (bool);

function withdrawStake(uint256 slot) external returns (bool);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;

interface IAddressStakingProperties {
// ============ Static ============
function minWithdrawalBlocks() external view returns (uint256);

// ============ Volatile [Overall] ============
function active() external view returns (uint256);

function pending() external view returns (uint256);

function withdrawn() external view returns (uint256);

// ============ Volatile [By Staker] ============
function activeByStaker(address staker) external view returns (uint256);

function pendingByStaker(address staker) external view returns (uint256);

function withdrawnByStalker(address staker) external view returns (uint256);

// ============ Volatile [By Address Staked] ============
function activeByAddressStaked(
address staked
) external view returns (uint256);
}
Loading

0 comments on commit 211b306

Please sign in to comment.