moving towards working delegation + timelocks.

This commit is contained in:
Greg Hysen 2019-06-03 18:31:42 -07:00
parent 9c8716da09
commit 717a19a08e
9 changed files with 550 additions and 178 deletions

View File

@ -31,88 +31,120 @@ contract Staking is
MixinPools
{
///// STAKING /////
///// STAKE /////
function stake(uint256 amount)
function deposit(address owner, uint256 amount)
external
returns (uint256 amountOfStakeMinted)
{
amountOfStakeMinted = _stake(amount);
return amountOfStakeMinted;
_deposit(msg.sender, amount);
}
function unstake(uint256 amount)
function depositAndStake(address owner, uint256 amount)
external
returns (uint256 amountOfStakeBurned)
{
amountOfStakeBurned = _unstake(amount);
return amountOfStakeBurned;
_depositAndStake(msg.sender, amount);
}
function getStakeBalance(address owner)
function depositAndDelegate(address owner, bytes32 poolId, uint256 amount)
external
view
returns (uint256 balance)
{
balance = _getStakeBalance(owner);
return balance;
_depositAndDelegate(owner, poolId, amount);
}
function delegateStake(bytes32 makerId, uint256 amount)
function activateStake(address owner, uint256 amount)
external
returns (uint256 amountOfStakeDelegated)
{
amountOfStakeDelegated = _delegateStake(makerId, amount);
return amountOfStakeDelegated;
_activateStake(msg.sender, amount);
}
function undelegateStake(bytes32 makerId, uint256 amount)
function activateAndDelegateStake(address owner, uint256 amount)
external
returns (uint256 amountOfStakeUndelegated)
{
amountOfStakeUndelegated = _undelegateStake(makerId, amount);
return amountOfStakeUndelegated;
_activateAndDelegateStake(msg.sender, amount);
}
function stakeAndDelegate(bytes32 makerId, uint256 amount)
function deactivateAndTimelockStake(address owner, uint256 amount)
external
returns (uint256 amountOfStakeMintedAndDelegated)
{
amountOfStakeMintedAndDelegated = _stakeAndDelegate(makerId, amount);
return amountOfStakeMintedAndDelegated;
_deactivateAndTimelockStake(msg.sender, amount);
}
function undelegateAndUnstake(bytes32 makerId, uint256 amount)
function deactivateAndTimelockDelegatedStake(address owner, bytes32 poolId, uint256 amount)
external
returns (uint256 amountOfStakeUndelegatedAndUnstaked)
{
_deactivateAndTimelockDelegatedStake(msg.sender, poolId, amount);
}
function withdraw(address owner, uint256 amount)
external
{
_withdraw(msg.sender, amount);
}
///// STAKE BALANCES /////
function getStakeDelegatedByOwner(address owner, bytes32 makerId)
function getTotalStake(address owner)
external
returns (uint256 balance)
view
returns (uint256)
{
balance = _getStakeDelegatedByOwner(owner, makerId);
return balance;
return _getTotalStake(owner);
}
function getTotalStakeDelegatedByOwner(address owner)
function getActivatedStake(address owner)
external
returns (uint256 balance)
view
returns (uint256)
{
balance = _getTotalStakeDelegatedByOwner(owner);
return balance;
return _getActivatedStake(owner);
}
function getTotalStakeDelegatedToMaker(bytes32 makerId)
function getDeactivatedStake(address owner)
external
returns (uint256 balance)
view
returns (uint256)
{
balance = _getTotalStakeDelegatedToMaker(makerId);
return balance;
return _getDeactivatedStake(owner);
}
function getWithdrawableStake(address owner)
external
view
returns (uint256)
{
return getWithdrawableStake(owner);
}
function getTimelockedStake(address owner)
external
view
returns (uint256)
{
return _getTimelockedStake(owner);
}
function getStakeDelegatedByOwner(address owner)
external
view
returns (uint256)
{
return _getStakeDelegatedByOwner(owner);
}
function getStakeDelegatedToPoolByOwner(address owner, bytes32 poolId)
internal
view
returns (uint256)
{
return _getStakeDelegatedToPoolByOwner(owner, poolId);
}
function getStakeDelegatedToPool(bytes32 poolId)
external
view
returns (uint256)
{
return _getStakeDelegatedToPool(poolId);
}
///// POOLS /////

View File

@ -0,0 +1,33 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "@0x/contracts-utils/contracts/src/SafeMath.sol";
import "./MixinStorage.sol";
contract MixinEpoch {
function _getCurrentTimelockPeriod()
internal
returns (uint64)
{
// @TODO - IMPLEMENT
return 7;
}
}

View File

@ -24,158 +24,204 @@ import "@0x/contracts-utils/contracts/src/SafeMath.sol";
import "./MixinStorage.sol";
import "./MixinConstants.sol";
import "../interfaces/IStakingEvents.sol";
import "./StakingBalances.sol";
contract MixinStake is
SafeMath,
IStakingEvents,
MixinConstants,
MixinStorage
MixinStorage,
MixinStakeBalances
{
using LibZrxToken for uint256;
// default maker id that stake is delegated to
bytes32 constant internal NIL_MAKER_ID = 0x0;
function _stake(uint256 amount)
function _deposit(address owner, uint256 amount)
internal
returns (uint256)
{
// sanitize input - can only stake whole tokens
uint256 amountOfStakeToMint = amount._roundDownToNearestWholeToken();
// deposit equivalent amount of ZRX into vault
zrxVault.depositFrom(msg.sender, amountOfStakeToMint);
// mint stake
totalStake[msg.sender] = _safeAdd(totalStake[msg.sender], amountOfStakeToMint);
delegatedStake[msg.sender][NIL_MAKER_ID] = _safeAdd(delegatedStake[msg.sender][NIL_MAKER_ID], amountOfStakeToMint);
// emit stake event
emit StakeMinted(
msg.sender,
amountOfStakeToMint
);
// return amount of stake minted
return amountOfStakeToMint;
_mintStake(owner, amount);
}
function _unstake(uint256 amount)
function _depositAndStake(address owner, uint256 amount)
internal
returns (uint256)
{
// sanitize input - can only stake whole tokens
uint256 amountOfStakeToBurn = amount._roundDownToNearestWholeToken();
_mintStake(owner, amount);
_activateStake(owner, amount);
}
function _depositAndDelegate(address owner, bytes32 poolId, uint256 amount)
internal
{
_depositAndStake(owner, amount);
_delegateStake(owner, poolId, amount);
}
function _activateStake(address owner, uint256 amount)
internal
{
_syncTimelockedStake();
Timelock memory ownerTimelock = timelocksByOwner[owner];
require(
ownerTimelock.availableBalance >= amount,
"INSUFFICIENT_BALANCE"
);
ownerTimelock.sub(amount);
timelocksByOwner[owner] = ownerTimelock;
_activateStake(owner, amount);
}
function _activateAndDelegateStake(address owner, bytes32 poolId, uint256 amount)
internal
{
_activateStake(owner, amount);
_delegateStake(owner, poolId, amount);
}
function _deactivateAndTimelockStake(address owner, uint256 amount)
internal
{
Timelock memory ownerTimelock = timelocksByOwner[owner];
ownerTimelock.add(amount);
timelocksByOwner[owner] = ownerTimelock;
activeStakeByOwner[owner] = _safeSub(activeStakeByOwner[owner], amount);
}
function _deactivateAndTimelockDelegatedStake(address owner, bytes32 poolId, uint256 amount)
internal
{
_deactivateStake(owner, amount);
_undelegateStake(owner, poolId, amount);
}
function _withdraw(address owner, uint256 amount)
internal
{
Timelock memory ownerTimelock = timelocksByOwner[owner];
require(
ownerTimelock.availableBalance >= amount,
"INSUFFICIENT_BALANCE"
);
ownerTimelock.sub(amount);
timelocksByOwner[owner] = ownerTimelock;
// burn stake
totalStake[msg.sender] = _safeSub(totalStake[msg.sender], amountOfStakeToBurn);
delegatedStake[msg.sender][NIL_MAKER_ID] = _safeSub(delegatedStake[msg.sender][NIL_MAKER_ID], amountOfStakeToBurn);
_burnStake(owner, amount);
}
// withdraw equivalent amount of ZRX from vault
zrxVault.withdrawFrom(msg.sender, amountOfStakeToBurn);
///// PRIVATE HELPERS /////
function _mintStake(address owner, uint256 amount)
private
{
// deposit equivalent amount of ZRX into vault
zrxVault.depositFrom(owner, amount);
// mint stake
stakeByOwner[owner] = _safeAdd(stakeByOwner[owner], amount);
// emit stake event
emit StakeMinted(
msg.sender,
amountOfStakeToBurn
);
// return amount of stake minted
return amountOfStakeToBurn;
}
function _delegateStake(bytes32 makerId, uint256 amount)
internal
returns (uint256)
{
require(
_getUndelegatedStake(msg.sender) >= amount,
"INSUFFICIENT_STAKE_BALANCE"
);
// change from undelegated to delegated
delegatedStake[msg.sender][NIL_MAKER_ID] = _safeSub(delegatedStake[msg.sender][NIL_MAKER_ID], amount);
delegatedStake[msg.sender][makerId] = _safeAdd(delegatedStake[msg.sender][makerId], amount);
// Update total stake delegated to `makerId`
totalDelegatedStake[makerId] = _safeAdd(totalDelegatedStake[makerId], amount);
}
function _undelegateStake(bytes32 makerId, uint256 amount)
internal
returns (uint256)
{
require(
_getStakeDelegatedByOwner(msg.sender, makerId) >= amount,
"INSUFFICIENT_DELEGATED_STAKE_BALANCE"
);
// change from delegated to undelegated
delegatedStake[msg.sender][makerId] = _safeSub(delegatedStake[msg.sender][makerId], amount);
delegatedStake[msg.sender][NIL_MAKER_ID] = _safeAdd(delegatedStake[msg.sender][NIL_MAKER_ID], amount);
// Update total stake delegated to `makerId`
totalDelegatedStake[makerId] = _safeAdd(totalDelegatedStake[makerId], amount);
}
function _undelegateAllStake(bytes32 makerId)
internal
returns (uint256)
{
address owner = msg.sender;
uint256 delegatedStakeBalance = _getStakeDelegatedByOwner(owner, makerId);
return _undelegateStake(makerId, delegatedStakeBalance);
}
function _stakeAndDelegate(bytes32 makerId, uint256 amount)
internal
returns (uint256 amountOfStakeDelegated)
{
// mint stake
uint256 amountOfStakeMinted = _stake(amount);
// delegate stake to maker
amountOfStakeDelegated = _delegateStake(makerId, amountOfStakeMinted);
return amountOfStakeDelegated;
}
function _getUndelegatedStake(address owner)
internal
returns (uint256)
{
return delegatedStake[owner][NIL_MAKER_ID];
}
function _getStakeDelegatedByOwner(address owner, bytes32 makerId)
internal
returns (uint256)
{
return delegatedStake[owner][makerId];
}
function _getTotalStakeDelegatedByOwner(address owner)
internal
returns (uint256)
{
return _safeSub(
totalStake[owner],
delegatedStake[owner][NIL_MAKER_ID]
owner,
amount
);
}
function _getTotalStakeDelegatedToMaker(bytes32 makerId)
internal
returns (uint256)
function _burnStake(address owner, uint256 amount)
private
{
return totalDelegatedStake[makerId];
// burn stake
stakeByOwner[owner] = _safeSub(stakeByOwner[owner], amount);
// withdraw equivalent amount of ZRX from vault
zrxVault.withdrawFrom(owner, amount);
// emit stake event
emit StakeBurned(
owner,
amount
);
}
function _getStakeBalance(address owner)
internal
view
returns (uint256)
function _activateStake(address owner, uint256 amount)
private
{
return totalStake[owner];
activeStakeByOwner[owner] = _safeAdd(activeStakeByOwner[owner], amount);
}
function _delegateStake(address owner, bytes32 poolId, uint256 amount)
private
{
// increment how much stake the owner has delegated
delegatedStakeByOwner[owner] = _safeAdd(stakeByOwner[owner], amount);
// increment how much stake the owner has delegated to the input pool
delegatedStakeToPoolByOwner[owner][poolId] = _safeAdd(delegatedStakeToPoolByOwner[owner][poolId], amount);
// increment how much stake has been delegated to pool
delegatedStakeByPoolId[poolId] = _safeAdd(delegatedStakeByPoolId[poolId], amount);
}
function _undelegateStake(address owner, bytes32 poolId, uint256 amount)
private
{
// decrement how much stake the owner has delegated
delegatedStakeByOwner[owner] = _safeSub(stakeByOwner[owner], amount);
// decrement how much stake the owner has delegated to the input pool
delegatedStakeToPoolByOwner[owner][poolId] = _safeSub(delegatedStakeToPoolByOwner[owner][poolId], amount);
// decrement how much stake has been delegated to pool
delegatedStakeByPoolId[poolId] = _safeSub(delegatedStakeByPoolId[poolId], amount);
}
// Epoch | lockedAt | total | pending | current | timelock() | withdraw() | available()
// 0 | 0 | 0 | 0 | 0 | | | 0
// 1 | 1 | 5 | 0 | 0 | +5 | | 0
// 2 | 1 | 5 | 0 | 0 | | | 0
// 2 | 2 | 15 | 5 | 0 | +10 | | 0
// 3 | 2 | 15 | 5 | 0 | | | 5
// 3 | 3 | 30 | 15 | 5 | +15 | | 5
// 4 | 3 | 30 | 15 | 5 | | | 15
// 5 | 3 | 30 | 15 | 5 | | | 30
// 5 | 5 | 30 | 30 | 30 | +0 * | | 30
// 6 | 6 | 50 | 30 | 30 | +20 | | 30
// 6 | 6 | 20 | 0 | 0 | | -30 | 0
// 7 | 6 | 20 | 0 | 0 | | | 0
// 8 | 6 | 20 | 0 | 0 | | | 20
function _timelockStake(address owner, uint256 amount)
private
{
Timelock memory ownerTimelock = _getSynchronizedTimelock(owner, amount);
ownerTimelock.total = _safeAdd(ownerTimelock.total, amount);
timelocksByOwner[owner] = ownerTimelock;
}
function _syncTimelockedStake(address owner, uint256 amount)
private
{
timelocksByOwner[owner] = _getSynchronizedTimelock(owner, amount);
}
function _getSynchronizedTimelock(address owner, uint256 amount)
private
returns (Timelock memory ownerTimelock)
{
Timelock memory ownerTimelock = timelocksByOwner[owner];
uint64 currentTimelockPeriod = getCurrentTimelockPeriod();
if (currentTimelockPeriod == _safeAdd(ownerTimelock.lockedAt, 1)) {
// shift one period
ownerTimelock.current = ownerTimelock.pending;
ownerTimelock.pending = ownerTimelock.total;
} else if (currentTimelockPeriod > ownerTimelock.lockedAt) {
// shift n periods
ownerTimelock.current = ownerTimelock.total;
ownerTimelock.pending = ownerTimelock.total;
} else {
// do nothing
}
return ownerTimelock;
}
}

View File

@ -0,0 +1,99 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "../interfaces/IVault.sol";
import "../libs/LibZrxToken.sol";
import "@0x/contracts-utils/contracts/src/SafeMath.sol";
import "./MixinStorage.sol";
import "./MixinConstants.sol";
contract MixinStake is
SafeMath,
MixinConstants,
MixinStorage,
{
function _getTotalStake(address owner)
internal
view
returns (uint256)
{
return stakeByOwner[owner];
}
function getActivatedStake(address owner)
internal
view
returns (uint256)
{
return activeStakeByOwner[owner];
}
function getDeactivatedStake(address owner)
internal
view
returns (uint256)
{
return _safeSub(_getTotalStake(owner), getActivatedStake(owner));
}
function getStakeAvailableForActivation()
function getWithdrawableStake(address owner)
internal
view
returns (uint256)
{
}
function getTimelockedStake(address owner)
internal
view
returns (uint256)
{
return timelockedStakeByOwner[owner].total;
}
function getStakeDelegatedByOwner(address owner)
internal
view
returns (uint256)
{
return delegatedStakeByOwner[owner];
}
function getStakeDelegatedToPoolByOwner(address owner, bytes32 poolId)
internal
view
returns (uint256)
{
return delegatedStakeToPoolByOwner[owner][poolId];
}
function getStakeDelegatedToPool(bytes32 poolId)
internal
view
returns (uint256)
{
return delegatedStakeByPoolId[poolId];
}
}

View File

@ -20,31 +20,39 @@ pragma solidity ^0.5.5;
import "../interfaces/IVault.sol";
import "./MixinConstants.sol";
import "../interfaces/IStructs.sol";
contract MixinStorage is
IStructs,
MixinConstants
{
// address of staking contract
address stakingContract;
// mapping from Staker to Maker Id to Amount Staked
mapping (address => mapping (bytes32 => uint256)) delegatedStake;
// mapping from Owner to Amount Staked
mapping (address => uint256) stakeByOwner;
// mapping from Staker to Maker Id to Amount Staked
mapping (address => uint256) totalStake;
// mapping from Owner to Amount of Instactive Stake
mapping (address => uint256) activeStakeByOwner;
// mapping from Maker Id to Amount of Delegated Staked
mapping (bytes32 => uint256) totalDelegatedStake;
// mapping from Owner to Amount Timelocked
mapping (address => Timelock) timelockedStakeByOwner;
// tracking Maker Id
// mapping from Pool Id to Amount Delegated
mapping (bytes32 => uint256) delegatedStakeByPoolId;
// mapping from Owner to Amount Delegated
mapping (address => uint256) delegatedStakeByOwner;
// mapping from Owner to Pool Id to Amount Delegated
mapping (address => mapping (bytes32 => uint256)) delegatedStakeToPoolByOwner;
// tracking Pool Id
bytes32 nextPoolId = INITIAL_POOL_ID;
struct Pool {
address operatorAddress;
uint8 operatorShare;
}
// mapping from Pool Id to Pool
mapping (bytes32 => Pool) poolById;
// mapping from Maker Address to Pool Id

View File

@ -0,0 +1,49 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "@0x/contracts-utils/contracts/src/SafeMath.sol";
import "./MixinStorage.sol";
contract MixinStake is
SafeMath,
MixinStorage
{
contract MixinTimelock {
// Epoch | lockedAt | total | pending | current | timelock() | withdraw() | available()
// 0 | 0 | 0 | 0 | 0 | | | 0
// 1 | 1 | 5 | 0 | 0 | +5 | | 0
// 2 | 1 | 5 | 0 | 0 | | | 0
// 2 | 2 | 15 | 5 | 0 | +10 | | 0
// 3 | 2 | 15 | 5 | 0 | | | 5
// 3 | 3 | 30 | 15 | 5 | +15 | | 5
// 4 | 3 | 30 | 15 | 5 | | | 15
// 5 | 3 | 30 | 15 | 5 | | | 30
// 5 | 5 | 30 | 30 | 30 | +0 * | | 30
// 6 | 6 | 50 | 30 | 30 | +20 | | 30
// 6 | 6 | 20 | 0 | 0 | | -30 | 0
// 7 | 6 | 20 | 0 | 0 | | | 0
// 8 | 6 | 20 | 0 | 0 | | | 20
function _timelockStake()
}

View File

@ -0,0 +1,99 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "../interfaces/IStructs.sol";
import "@0x/contracts-utils/contracts/src/SafeMath.sol";
contract MixinTimelock is
IStructs,
SafeMath
{
// Epoch | lockedAt | total | pending | current | timelock() | withdraw() | available()
// 0 | 0 | 0 | 0 | 0 | | | 0
// 1 | 1 | 5 | 0 | 0 | +5 | | 0
// 2 | 1 | 5 | 0 | 0 | | | 0
// 2 | 2 | 15 | 5 | 0 | +10 | | 0
// 3 | 2 | 15 | 5 | 0 | | | 5
// 3 | 3 | 30 | 15 | 5 | +15 | | 5
// 4 | 3 | 30 | 15 | 5 | | | 15
// 5 | 3 | 30 | 15 | 5 | | | 30
// 5 | 5 | 30 | 30 | 30 | +0 * | | 30
// 6 | 6 | 50 | 30 | 30 | +20 | | 30
// 6 | 6 | 20 | 0 | 0 | | -30 | 0
// 7 | 6 | 20 | 0 | 0 | | | 0
// 8 | 6 | 20 | 0 | 0 | | | 20
function _add(Timelock memory timelock, uint256 amount)
internal
returns (uint256)
{
timelock.total += amount;
}
function _sub(Timelock memory timelock, uint256 amount)
internal
returns (uint256)
{
}
function _subTimelockedStake(address owner, uint256 amount)
internal
{
}
function _addTimelockedStake(address owner, uint256 amount)
internal
{
timelockedStakeByOwner[owner] = safeAdd(timelockedStakeByOwner[owner], amount);
// update timelock
uint64 currentTimelockPeriod = _getTimelockPeriod();
Timelock memory timelock = timelocksByOwner[owner];
}
function _getAvailableTimelockedStake(address owner)
internal
returns (uint256)
{
}
function _getPendingTimelockedStake(address owner)
internal
returns (uint256)
{
}
function _getTotalTimelockedStake(address owner)
internal
returns (uint256)
{
}
}

View File

@ -69,6 +69,7 @@ describe('Staking Core', () => {
});
describe('end-to-end tests', () => {
it('staking/unstaking', async () => {
/*
///// 1/3 SETUP TEST PARAMETERS /////
const amountToStake = stakingWrapper.toBaseUnitAmount(10);
const amountToUnstake = stakingWrapper.toBaseUnitAmount(5);
@ -111,6 +112,7 @@ describe('Staking Core', () => {
const zrxTokenBalanceOfStakerAfterStaking = await stakingWrapper.getZrxTokenBalance(stakers[0]);
expect(zrxTokenBalanceOfStakerAfterStaking).to.be.bignumber.equal(zrxTokenBalanceOfStakerBeforeStaking.minus(amountToStake).plus(amountToUnstake));
}
*/
});
it('nth root', async () => {

View File

@ -115,6 +115,8 @@ export class StakingWrapper {
const returnValue = await this._web3Wrapper.callAsync(txData);
return returnValue;
}
/*
public async stake(holder: string, amount: BigNumber): Promise<BigNumber> {
const calldata = this.getStakingContract().stake.getABIEncodedTransactionData(amount);
const txReceipt = await this._executeTransactionAsync(calldata, holder);
@ -129,11 +131,13 @@ export class StakingWrapper {
const stakeBurned = (stakeBurnedLog as any).args.amount;
return stakeBurned;
}
public async getStakeBalance(holder: string): Promise<BigNumber> {
const calldata = this.getStakingContract().getStakeBalance.getABIEncodedTransactionData(holder);
const balance = await this._callAsync(calldata, holder);
return balance;
}
*/
public async getNextPoolIdAsync(): Promise<string> {
const calldata = this.getStakingContract().getNextPoolId.getABIEncodedTransactionData();
const nextPoolId = await this._callAsync(calldata);