UNPKG

@nodeset/contracts

Version:

Protocol for accessing NodeSet's Constellation Ethereum staking network

181 lines (157 loc) 8.17 kB
import { RocketDepositPool, RocketMinipoolPenalty, RocketNodeManager, RocketTokenRETH } from '../_utils/artifacts' import { assertBN } from '../_helpers/bn'; export async function withdrawValidatorBalance(minipool, withdrawalBalance, from) { // Load contracts const [ rocketDepositPool, rocketTokenRETH, rocketNodeManager ] = await Promise.all([ RocketDepositPool.deployed(), RocketTokenRETH.deployed(), RocketNodeManager.deployed(), ]); // Get node parameters let nodeAddress = await minipool.getNodeAddress.call(); let nodeWithdrawalAddress = await rocketNodeManager.getNodeWithdrawalAddress.call(nodeAddress); // Get parameters let [ nodeFee ] = await Promise.all([ minipool.getNodeFee.call(), ]); // Get balances function getBalances() { return Promise.all([ web3.eth.getBalance(rocketTokenRETH.address).then(value => value.BN), rocketDepositPool.getBalance.call(), web3.eth.getBalance(nodeWithdrawalAddress).then(value => value.BN), web3.eth.getBalance(minipool.address).then(value => value.BN), ]).then( ([rethContractEth, depositPoolEth, nodeWithdrawalEth, minipoolEth]) => ({rethContractEth, depositPoolEth, nodeWithdrawalEth, minipoolEth}) ); } // Get minipool balances function getMinipoolBalances() { return Promise.all([ minipool.getNodeDepositBalance.call(), minipool.getNodeRefundBalance.call(), minipool.getUserDepositBalance.call(), ]).then( ([nodeDepositBalance, nodeRefundBalance, userDepositBalance]) => ({nodeDepositBalance, nodeRefundBalance, userDepositBalance}) ); } // Send validator balance to minipool if (withdrawalBalance.gt('0'.BN)) { await web3.eth.sendTransaction({ from: from, to: minipool.address, gas: 12450000, value: withdrawalBalance }); } // Get total withdrawal balance withdrawalBalance = (await web3.eth.getBalance(minipool.address)).BN; // Get initial balances & withdrawal processed status let [balances1, minipoolBalances1] = await Promise.all([ getBalances(), getMinipoolBalances() ]); // Set gas price let gasPrice = '20'.gwei; // Payout the balances now let txReceipt = await minipool.distributeBalance(false, { from: from, gasPrice: gasPrice }); let txFee = gasPrice.mul(web3.utils.toBN(txReceipt.receipt.gasUsed)); // Get updated balances & withdrawal processed status let [balances2, minipoolBalances2] = await Promise.all([ getBalances(), getMinipoolBalances() ]); // Add the fee back into the balance to make assertions easier if (from === nodeWithdrawalAddress) { balances2.nodeWithdrawalEth = balances2.nodeWithdrawalEth.add(txFee); } let nodeBalanceChange = balances2.nodeWithdrawalEth.add(minipoolBalances2.nodeRefundBalance).sub(balances1.nodeWithdrawalEth.add(minipoolBalances1.nodeRefundBalance)); let rethBalanceChange = balances2.rethContractEth.sub(balances1.rethContractEth); let depositPoolChange = balances2.depositPoolEth.sub(balances1.depositPoolEth); // console.log('Node deposit balance:', web3.utils.fromWei(minipoolBalances1.nodeDepositBalance), web3.utils.fromWei(minipoolBalances2.nodeDepositBalance)); // console.log('Node refund balance:', web3.utils.fromWei(minipoolBalances1.nodeRefundBalance), web3.utils.fromWei(minipoolBalances2.nodeRefundBalance)); // console.log('User deposit balance:', web3.utils.fromWei(minipoolBalances1.userDepositBalance), web3.utils.fromWei(minipoolBalances2.userDepositBalance)); // console.log('Node fee:', web3.utils.fromWei(nodeFee)); // console.log('Minipool Amount:', web3.utils.fromWei(balances1.minipoolEth), web3.utils.fromWei(balances2.minipoolEth), web3.utils.fromWei(balances2.minipoolEth.sub(balances1.minipoolEth))); // console.log('Node Withdrawal Address Amount:', web3.utils.fromWei(balances1.nodeWithdrawalEth), web3.utils.fromWei(balances2.nodeWithdrawalEth), web3.utils.fromWei(balances2.nodeWithdrawalEth.sub(balances1.nodeWithdrawalEth))); // console.log('rETH Contract Amount:', web3.utils.fromWei(balances1.rethContractEth), web3.utils.fromWei(balances2.rethContractEth), web3.utils.fromWei(balances2.rethContractEth.sub(balances1.rethContractEth))); // // console.log('Node balance change: ', web3.utils.fromWei(nodeBalanceChange)); // console.log('User balance change: ', web3.utils.fromWei(rethBalanceChange)); // console.log('Deposit pool change: ', web3.utils.fromWei(depositPoolChange)); // // const calculatedNodeShare = await minipool.calculateNodeShare(balances1.minipoolEth); // console.log('Calculated node share: ' + web3.utils.fromWei(calculatedNodeShare)); // Get penalty rate for this minipool const rocketMinipoolPenalty = await RocketMinipoolPenalty.deployed(); const penaltyRate = await rocketMinipoolPenalty.getPenaltyRate(minipool.address); // Calculate rewards let depositBalance = '32'.ether; if (withdrawalBalance.gte(depositBalance)) { let depositType = await minipool.getDepositType(); let userAmount = minipoolBalances1.userDepositBalance; let rewards = withdrawalBalance.sub(depositBalance); if (depositType.toString() === '3'){ // Unbonded let halfRewards = rewards.divn(2); let nodeCommissionFee = halfRewards.mul(nodeFee).div(web3.utils.toBN(web3.utils.toWei('1'))); userAmount = userAmount.add(rewards.sub(nodeCommissionFee)); } else if (depositType.toString() === '2' || depositType.toString() === '1'){ // Half or full let halfRewards = rewards.divn(2); let nodeCommissionFee = halfRewards.mul(nodeFee).div(web3.utils.toBN(web3.utils.toWei('1'))); userAmount = userAmount.add(halfRewards.sub(nodeCommissionFee)); } else if (depositType.toString() === '4') { // Variable const nodeCapital = minipoolBalances1.nodeDepositBalance; let nodeRewards = rewards.mul(nodeCapital).div(userAmount.add(nodeCapital)); nodeRewards = nodeRewards.add(rewards.sub(nodeRewards).mul(nodeFee).div(web3.utils.toBN(web3.utils.toWei('1')))); userAmount = userAmount.add(rewards.sub(nodeRewards)); } let nodeAmount = withdrawalBalance.sub(userAmount); // Adjust amounts according to penalty rate if (penaltyRate.gt(0)) { let penaltyAmount = nodeAmount.mul(penaltyRate).div(web3.utils.toBN(web3.utils.toWei('1'))); if (penaltyRate.gt(nodeAmount)) { penaltyAmount = nodeAmount; } nodeAmount = nodeAmount.sub(penaltyAmount); userAmount = userAmount.add(penaltyAmount); } // console.log('Rewards: ', web3.utils.fromWei(rewards)); // console.log('Node amount: ', web3.utils.fromWei(nodeAmount)); // console.log('User amount: ', web3.utils.fromWei(userAmount)); // Check balances assertBN.equal(rethBalanceChange.add(depositPoolChange), userAmount, "rETH balance was not correct"); assertBN.equal(nodeBalanceChange, nodeAmount, "Node balance was not correct"); // If not sent from node operator then refund balance should be correct if (!(from === nodeWithdrawalAddress || from === nodeAddress)) { let refundBalance = await minipool.getNodeRefundBalance.call(); // console.log('Node refund balance after withdrawal:', web3.utils.fromWei(refundBalance)); assertBN.equal(refundBalance, minipoolBalances1.nodeRefundBalance.add(nodeAmount), "Node balance was not correct"); } } return { nodeBalanceChange, rethBalanceChange } } export async function beginUserDistribute(minipool, txOptions) { await minipool.beginUserDistribute(txOptions); }