From 2924a4d9c5622929e3748390f6dbaf1d25b15a25 Mon Sep 17 00:00:00 2001 From: DrZoltanFazekas Date: Tue, 4 Mar 2025 07:00:00 +0100 Subject: [PATCH] Extend e2e tests, minimize rounding errors per delegator --- README.md | 3 +- e2e_liquid.sh | 179 +++++++++++-------- e2e_non-liquid.sh | 302 ++++++++++++++++++++------------- src/NonLiquidDelegation.sol | 41 ++++- test/NonLiquidDelegation.t.sol | 1 + 5 files changed, 327 insertions(+), 199 deletions(-) diff --git a/README.md b/README.md index 8060d0f..2f2d167 100644 --- a/README.md +++ b/README.md @@ -352,8 +352,7 @@ To enable the tests to interact with the Zilliqa 2.0 deposit contract, the contr @zilliqa/zq2/=/home/user/zq2/zilliqa/src/contracts/ ``` -To execute end-to-end tests on a local network, set `consensus.staker_withdrawal_period` to 5 and -`consensus.blocks_per_epoch` to 3 in `config_docker.toml` and run +To execute end-to-end tests on a local network, set the funds of the first item in `consensus.genesis_accounts` to `5000000000000000000000000`, `consensus.staker_withdrawal_period` to 5 and `consensus.blocks_per_epoch` to 3 in `config_docker.toml` and run ```bash chmod +x e2e_liquid.sh && ./e2e_liquid.sh chmod +x e2e_non-liquid.sh && ./e2e_non-liquid.sh diff --git a/e2e_liquid.sh b/e2e_liquid.sh index 1c3a7d2..b84ee77 100755 --- a/e2e_liquid.sh +++ b/e2e_liquid.sh @@ -20,6 +20,17 @@ CONTROL_KEY_4=0xdb670cbff28f4b15297d03fafdab8f5303d68b7591bd59e31eaef215dd0f246a +staker() { + # $1 = 2-digit index + # $2 = STAKER_KEY or STAKER_ADDRESS + STAKER_KEY=${STAKER_KEY:0:64}$1 + STAKER_ADDRESS=$(cast wallet address $STAKER_KEY) + local var=$2 + echo ${!var} +} + + + unbond() { # sleep two times as many seconds as many blocks the deposit withdrawal period # consists of to wait long enough even if there is a 2 second average block time @@ -204,25 +215,92 @@ join_all() { -stake_all() { - echo "############################### EARNING ##############################" - sleep 10s +stake_one() { + # $1 = 2-digit staker index + # $2 = amount echo "############################### STAKING ##############################" - cast send --legacy --value 300ether --private-key 0x0000000000000000000000000000000000000000000000000000000000000002 $STAKER_ADDRESS 1>/dev/null - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 lst price: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getPrice()(uint256)" | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether + temp=$(forge script script/Stake.s.sol --broadcast --legacy --sig "run(address payable, uint256)" $CONTRACT_ADDRESS $2 --private-key $(staker $1 STAKER_KEY) 2>&1 1>/dev/null) + errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) + if [ $errors -eq 0 ]; then + echo "🟢 Stake $1" + else + echo "🔴 Stake $1 $temp" + fi + echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether + echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 lst price: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getPrice()(uint256)" | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + sleep 2s +} + + + +unstake_one() { + # $1 = 2-digit staker index + # $2 = amount + echo "############################### UNSTAKING ##############################" + echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether + echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 lst price: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getPrice()(uint256)" | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + temp=$(forge script script/Unstake.s.sol --broadcast --legacy --sig "run(address payable, uint256)" $CONTRACT_ADDRESS $2 --private-key $(staker $1 STAKER_KEY) 2>&1 1>/dev/null) + errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) + if [ $errors -eq 0 ]; then + echo "🟢 Unstake $1" + else + echo "🔴 Unstake $1 $temp" + fi + echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether + echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 lst price: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getPrice()(uint256)" | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + sleep 2s +} + + +claim_one() { + # $1 = 2-digit staker index + echo "############################### CLAIMING ##############################" + echo -n "🟢 claimable: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getClaimable()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - temp=$(forge script script/Stake.s.sol --broadcast --legacy --sig "run(address payable, uint256)" $CONTRACT_ADDRESS 200000000000000000000 --private-key $STAKER_KEY 2>&1 1>/dev/null) + echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 lst price: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getPrice()(uint256)" | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + temp=$(forge script script/Claim.s.sol --broadcast --legacy --sig "run(address payable)" $CONTRACT_ADDRESS --private-key $(staker $1 STAKER_KEY) 2>&1 1>/dev/null) errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) if [ $errors -eq 0 ]; then - echo "🟢 Stake" + echo "🟢 Claim $1" else - echo "🔴 Stake $temp" + echo "🔴 Claim $1 $temp" fi + echo -n "🟢 claimable: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getClaimable()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether echo -n "🟢 lst price: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getPrice()(uint256)" | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 controller balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + sleep 2s +} + + + +stake_all() { + echo "############################### EARNING ##############################" + sleep 10s + + cast send --legacy --value 300ether --private-key 0x0000000000000000000000000000000000000000000000000000000000000002 $(staker 01 STAKER_ADDRESS) 1>/dev/null + stake_one 01 200000000000000000000 + + cast send --legacy --value 2100ether --private-key 0x0000000000000000000000000000000000000000000000000000000000000002 $(staker 02 STAKER_ADDRESS) 1>/dev/null + stake_one 02 2000000000000000000000 + + cast send --legacy --value 20100ether --private-key 0x0000000000000000000000000000000000000000000000000000000000000002 $(staker 03 STAKER_ADDRESS) 1>/dev/null + stake_one 03 20000000000000000000000 + validators=$(cast call $CONTRACT_ADDRESS "validators()(bool[])" | grep -o "true" | wc -l) if [ $validators -gt 0 ]; then priv_key=$CONTROL_KEY_3 @@ -245,27 +323,19 @@ stake_all() { echo "############################### EARNING ##############################" sleep 10s - echo "############################### UNSTAKING ##############################" - temp=$(forge script script/Unstake.s.sol --broadcast --legacy --sig "run(address payable, uint256)" $CONTRACT_ADDRESS 100000000000000000000 --private-key $STAKER_KEY 2>&1 1>/dev/null) - errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) - if [ $errors -eq 0 ]; then - echo "🟢 Unstake" - else - echo "🔴 Unstake $temp" - fi - echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 lst price: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getPrice()(uint256)" | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether + unstake_one 01 100000000000000000000 + + unstake_one 02 1000000000000000000000 + + unstake_one 03 10000000000000000000000 echo "############################### UNBONDING ##############################" unbond echo "############################### STAKING REWARDS ##############################" echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $(staker 01 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether echo -n "🟢 lst price: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getPrice()(uint256)" | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether temp=$(forge script script/StakeRewards.s.sol --broadcast --legacy --sig "run(address payable)" $CONTRACT_ADDRESS --private-key $OWNER_KEY 2>&1 1>/dev/null) errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) if [ $errors -eq 0 ]; then @@ -274,25 +344,14 @@ stake_all() { echo "🔴 StakeRewards $temp" fi echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $(staker 01 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether echo -n "🟢 lst price: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getPrice()(uint256)" | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether - echo "############################### CLAIMING ##############################" - echo -n "🟢 claimable: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getClaimable()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - temp=$(forge script script/Claim.s.sol --broadcast --legacy --sig "run(address payable)" $CONTRACT_ADDRESS --private-key $STAKER_KEY 2>&1 1>/dev/null) - errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) - if [ $errors -eq 0 ]; then - echo "🟢 Claim" - else - echo "🔴 Claim $temp" - fi - echo -n "🟢 claimable: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getClaimable()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether + claim_one 01 - echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 lst price: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getPrice()(uint256)" | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether + claim_one 02 + + claim_one 03 echo "############################### EARNING ##############################" sleep 10s @@ -366,20 +425,11 @@ unstake_all() { echo -n "🟢 total rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getRewards()(uint256)" | sed 's/\[[^]]*\]//g') ether echo -n "🟢 lst price: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getPrice()(uint256)" | sed 's/\[[^]]*\]//g') ether - echo "############################### UNSTAKING ##############################" - echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether - temp=$(forge script script/Unstake.s.sol --broadcast --legacy --sig "run(address payable, uint256)" $CONTRACT_ADDRESS $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $STAKER_ADDRESS) --private-key $STAKER_KEY 2>&1 1>/dev/null) - errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) - if [ $errors -eq 0 ]; then - echo "🟢 Unstake" - else - echo "🔴 Unstake $temp" - fi - echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether + unstake_one 01 $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $(staker 01 STAKER_ADDRESS)) + + unstake_one 02 $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $(staker 02 STAKER_ADDRESS)) + + unstake_one 03 $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $(staker 03 STAKER_ADDRESS)) echo "############################### UNBONDING ##############################" unbond @@ -387,22 +437,11 @@ unstake_all() { echo -n "🟢 total rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getRewards()(uint256)" | sed 's/\[[^]]*\]//g') ether echo -n "🟢 lst price: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getPrice()(uint256)" | sed 's/\[[^]]*\]//g') ether - echo "############################### CLAIMING ##############################" - echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether - echo -n "🟢 claimable: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getClaimable()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - temp=$(forge script script/Claim.s.sol --broadcast --legacy --sig "run(address payable)" $CONTRACT_ADDRESS --private-key $STAKER_KEY 2>&1 1>/dev/null) - errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) - if [ $errors -eq 0 ]; then - echo "🟢 Claim" - else - echo "🔴 Claim $temp" - fi - echo -n "🟢 claimable: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getClaimable()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether - echo -n "🟢 lst balance: " && cast to-unit $(cast call $(cast call $CONTRACT_ADDRESS "getLST()(address)") "balanceOf(address)(uint256)" $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether + claim_one 01 + + claim_one 02 + + claim_one 03 } diff --git a/e2e_non-liquid.sh b/e2e_non-liquid.sh index ff18116..48468ac 100755 --- a/e2e_non-liquid.sh +++ b/e2e_non-liquid.sh @@ -20,6 +20,17 @@ CONTROL_KEY_4=0xdb670cbff28f4b15297d03fafdab8f5303d68b7591bd59e31eaef215dd0f246a +staker() { + # $1 = 2-digit index + # $2 = STAKER_KEY or STAKER_ADDRESS + STAKER_KEY=${STAKER_KEY:0:64}$1 + STAKER_ADDRESS=$(cast wallet address $STAKER_KEY) + local var=$2 + echo ${!var} +} + + + unbond() { # sleep two times as many seconds as many blocks the deposit withdrawal period # consists of to wait long enough even if there is a 2 second average block time @@ -149,7 +160,9 @@ leave_one() { rewards() { bc -l <<< "scale=18; \ - $(cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether)+\ + $(cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(staker 01 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether)+\ + $(cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(staker 02 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether)+\ + $(cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(staker 03 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether)+\ $(cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(cast wallet address $CONTROL_KEY_1) | sed 's/\[[^]]*\]//g') ether)+\ $(cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(cast wallet address $CONTROL_KEY_2) | sed 's/\[[^]]*\]//g') ether)+\ $(cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(cast wallet address $CONTROL_KEY_3) | sed 's/\[[^]]*\]//g') ether)+\ @@ -239,126 +252,192 @@ join_all() { -stake_all() { - echo "############################### EARNING ##############################" - sleep 10s +stake_one() { + # $1 = 2-digit staker index + # $2 = amount echo "############################### STAKING ##############################" - cast send --legacy --value 300ether --private-key 0x0000000000000000000000000000000000000000000000000000000000000002 $STAKER_ADDRESS 1>/dev/null - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether - + echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - temp=$(forge script script/Stake.s.sol --broadcast --legacy --sig "run(address payable, uint256)" $CONTRACT_ADDRESS 200000000000000000000 --private-key $STAKER_KEY 2>&1 1>/dev/null) + temp=$(forge script script/Stake.s.sol --broadcast --legacy --sig "run(address payable, uint256)" $CONTRACT_ADDRESS $2 --private-key $(staker $1 STAKER_KEY) 2>&1 1>/dev/null) errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) if [ $errors -eq 0 ]; then - echo "🟢 Stake" + echo "🟢 Stake $1" else - echo "🔴 Stake $temp" + echo "🔴 Stake $1 $temp" fi echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether - validators=$(cast call $CONTRACT_ADDRESS "validators()(bool[])" | grep -o "true" | wc -l) - if [ $validators -gt 0 ]; then - priv_key=$CONTROL_KEY_3 - cast send --legacy --value 1000ether --private-key 0x0000000000000000000000000000000000000000000000000000000000000002 $(cast wallet address $priv_key) 1>/dev/null - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(cast wallet address $priv_key)) ether + echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + sleep 2s +} + - echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - temp=$(forge script script/Stake.s.sol --broadcast --legacy --sig "run(address payable, uint256)" $CONTRACT_ADDRESS 1000000000000000000000 --private-key $priv_key 2>&1 1>/dev/null) - errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) - if [ $errors -eq 0 ]; then - echo "🟢 Stake" - else - echo "🔴 Stake $temp" - fi - echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 controller rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(cast wallet address $priv_key) | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 controller delegated: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(cast wallet address $priv_key) | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 controller balance: " && cast to-unit $(cast balance $(cast wallet address $priv_key)) ether - fi - echo "############################### EARNING ##############################" - sleep 10s +withdraw_rewards_one() { + # $1 = 2-digit staker index echo "############################### WITHDRAWING REWARDS ##############################" echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether - temp=$(forge script script/WithdrawRewards.s.sol --broadcast --legacy --sig "run(address payable, string, string)" $CONTRACT_ADDRESS all all --private-key $STAKER_KEY 2>&1 1>/dev/null) + echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + temp=$(forge script script/WithdrawRewards.s.sol --broadcast --legacy --sig "run(address payable, string, string)" $CONTRACT_ADDRESS all all --private-key $(staker $1 STAKER_KEY) 2>&1 1>/dev/null) errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) if [ $errors -eq 0 ]; then - echo "🟢 WithdrawRewards" + echo "🟢 WithdrawRewards $1" else - echo "🔴 WithdrawRewards $temp" + echo "🔴 WithdrawRewards $1 $temp" fi echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether + echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + sleep 2s +} + + +unstake_one() { + # $1 = 2-digit staker index + # $2 = amount echo "############################### UNSTAKING ##############################" - temp=$(forge script script/Unstake.s.sol --broadcast --legacy --sig "run(address payable, uint256)" $CONTRACT_ADDRESS 100000000000000000000 --private-key $STAKER_KEY 2>&1 1>/dev/null) + echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether + echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + temp=$(forge script script/Unstake.s.sol --broadcast --legacy --sig "run(address payable, uint256)" $CONTRACT_ADDRESS $2 --private-key $(staker $1 STAKER_KEY) 2>&1 1>/dev/null) errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) if [ $errors -eq 0 ]; then - echo "🟢 Unstake" + echo "🟢 Unstake $1" else - echo "🔴 Unstake $temp" + echo "🔴 Unstake $1 $temp" fi echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether + echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + sleep 2s +} + - echo "############################### UNBONDING ##############################" - unbond +stake_rewards_one() { + # $1 = 2-digit staker index echo "############################### STAKING REWARDS ##############################" echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether - temp=$(forge script script/StakeRewards.s.sol --broadcast --legacy --sig "run(address payable)" $CONTRACT_ADDRESS --private-key $STAKER_KEY 2>&1 1>/dev/null) + echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + temp=$(forge script script/StakeRewards.s.sol --broadcast --legacy --sig "run(address payable)" $CONTRACT_ADDRESS --private-key $(staker $1 STAKER_KEY) 2>&1 1>/dev/null) errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) if [ $errors -eq 0 ]; then - echo "🟢 StakeRewards" + echo "🟢 StakeRewards $1" else - echo "🔴 StakeRewards $temp" + echo "🔴 StakeRewards $1 $temp" fi echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether + echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + sleep 2s +} - echo "############################### CLAIMING ##############################" - echo -n "🟢 claimable: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getClaimable()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - temp=$(forge script script/Claim.s.sol --broadcast --legacy --sig "run(address payable)" $CONTRACT_ADDRESS --private-key $STAKER_KEY 2>&1 1>/dev/null) - errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) - if [ $errors -eq 0 ]; then - echo "🟢 Claim" - else - echo "🔴 Claim $temp" - fi - echo -n "🟢 claimable: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getClaimable()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo "############################### WITHDRAWING REWARDS ##############################" + +claim_one() { + # $1 = 2-digit staker index + echo "############################### CLAIMING ##############################" + echo -n "🟢 claimable: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getClaimable()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether - echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - temp=$(forge script script/WithdrawRewards.s.sol --broadcast --legacy --sig "run(address payable, string, string)" $CONTRACT_ADDRESS all all --private-key $STAKER_KEY 2>&1 1>/dev/null) + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + temp=$(forge script script/Claim.s.sol --broadcast --legacy --sig "run(address payable)" $CONTRACT_ADDRESS --private-key $(staker $1 STAKER_KEY) 2>&1 1>/dev/null) errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) if [ $errors -eq 0 ]; then - echo "🟢 WithdrawRewards" + echo "🟢 Claim $1" else - echo "🔴 WithdrawRewards $temp" + echo "🔴 Claim $1 $temp" fi + echo -n "🟢 claimable: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getClaimable()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(staker $1 STAKER_ADDRESS)) ether + echo -n "🟢 delegated amount: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(staker $1 STAKER_ADDRESS) | sed 's/\[[^]]*\]//g') ether + sleep 2s +} + + + +stake_all() { + echo "############################### EARNING ##############################" + sleep 10s + + cast send --legacy --value 300ether --private-key 0x0000000000000000000000000000000000000000000000000000000000000002 $(staker 01 STAKER_ADDRESS) 1>/dev/null + stake_one 01 200000000000000000000 + + cast send --legacy --value 3000ether --private-key 0x0000000000000000000000000000000000000000000000000000000000000002 $(staker 02 STAKER_ADDRESS) 1>/dev/null + stake_one 02 2000000000000000000000 + + cast send --legacy --value 30000ether --private-key 0x0000000000000000000000000000000000000000000000000000000000000002 $(staker 03 STAKER_ADDRESS) 1>/dev/null + stake_one 03 20000000000000000000000 + + validators=$(cast call $CONTRACT_ADDRESS "validators()(bool[])" | grep -o "true" | wc -l) + if [ $validators -gt 0 ]; then + priv_key=$CONTROL_KEY_3 + cast send --legacy --value 1000ether --private-key 0x0000000000000000000000000000000000000000000000000000000000000002 $(cast wallet address $priv_key) 1>/dev/null + echo -n "🟢 staker balance: " && cast to-unit $(cast balance $(cast wallet address $priv_key)) ether + + echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether + temp=$(forge script script/Stake.s.sol --broadcast --legacy --sig "run(address payable, uint256)" $CONTRACT_ADDRESS 1000000000000000000000 --private-key $priv_key 2>&1 1>/dev/null) + errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) + if [ $errors -eq 0 ]; then + echo "🟢 Stake" + else + echo "🔴 Stake $temp" + fi + echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether + echo -n "🟢 controller rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $(cast wallet address $priv_key) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 controller delegated: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(cast wallet address $priv_key) | sed 's/\[[^]]*\]//g') ether + echo -n "🟢 controller balance: " && cast to-unit $(cast balance $(cast wallet address $priv_key)) ether + fi + echo "############################### EARNING ##############################" + sleep 10s + + withdraw_rewards_one 01 + + withdraw_rewards_one 02 + + withdraw_rewards_one 03 + + unstake_one 01 100000000000000000000 + + unstake_one 02 1000000000000000000000 + + unstake_one 03 10000000000000000000000 + + echo "############################### UNBONDING ##############################" + unbond + + stake_rewards_one 01 + + stake_rewards_one 02 + + stake_rewards_one 03 + + claim_one 01 + + claim_one 02 + + claim_one 03 + + withdraw_rewards_one 01 + + withdraw_rewards_one 02 + + withdraw_rewards_one 03 echo "############################### EARNING ##############################" sleep 10s @@ -426,60 +505,38 @@ unstake_all() { echo -n "🟢 immutable rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getImmutableRewards()(uint256)" | sed 's/\[[^]]*\]//g') ether echo -n "🟢 total rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getRewards()(uint256)" | sed 's/\[[^]]*\]//g') ether - echo "############################### UNSTAKING ##############################" - echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether - temp=$(forge script script/Unstake.s.sol --broadcast --legacy --sig "run(address payable, uint256)" $CONTRACT_ADDRESS $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $STAKER_ADDRESS) --private-key $STAKER_KEY 2>&1 1>/dev/null) - errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) - if [ $errors -eq 0 ]; then - echo "🟢 Unstake" - else - echo "🔴 Unstake $temp" - fi - echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether + unstake_one 01 $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(staker 01 STAKER_ADDRESS)) + + unstake_one 02 $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(staker 02 STAKER_ADDRESS)) + + unstake_one 03 $(cast call $CONTRACT_ADDRESS "getDelegatedAmount()(uint256)" --from $(staker 03 STAKER_ADDRESS)) echo "############################### UNBONDING ##############################" unbond echo -n "🟢 immutable rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getImmutableRewards()(uint256)" | sed 's/\[[^]]*\]//g') ether echo -n "🟢 total rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getRewards()(uint256)" | sed 's/\[[^]]*\]//g') ether - echo "############################### CLAIMING ##############################" - echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether - echo -n "🟢 claimable: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getClaimable()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - temp=$(forge script script/Claim.s.sol --broadcast --legacy --sig "run(address payable)" $CONTRACT_ADDRESS --private-key $STAKER_KEY 2>&1 1>/dev/null) - errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) - if [ $errors -eq 0 ]; then - echo "🟢 Claim" - else - echo "🔴 Claim $temp" - fi - echo -n "🟢 claimable: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getClaimable()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether + claim_one 01 + + claim_one 02 + + claim_one 03 + echo -n "🟢 immutable rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getImmutableRewards()(uint256)" | sed 's/\[[^]]*\]//g') ether echo -n "🟢 total rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getRewards()(uint256)" | sed 's/\[[^]]*\]//g') ether - echo "############################### WITHDRAWING REWARDS ##############################" echo -n "🟢 exposure: " && bc -l <<< "scale=18; $(cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedTotal()(uint256)" | sed 's/\[[^]]*\]//g') ether)+$(echo $(rewards))" echo -n "🟢 funds: " && bc -l <<< "scale=18; $(cast to-unit $(cast call $CONTRACT_ADDRESS "getStake()(uint256)" | sed 's/\[[^]]*\]//g') ether)+0.9*$(cast to-unit $(cast call $CONTRACT_ADDRESS "getRewards()(uint256)" | sed 's/\[[^]]*\]//g') ether)" - echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether - temp=$(forge script script/WithdrawRewards.s.sol --broadcast --legacy --sig "run(address payable, string, string)" $CONTRACT_ADDRESS all all --private-key $STAKER_KEY 2>&1 1>/dev/null) - errors=$(echo $temp | grep -o -i -e "error" -e "fail" -e "revert" | wc -l) - if [ $errors -eq 0 ]; then - echo "🟢 WithdrawRewards" - else - echo "🔴 WithdrawRewards $temp" - fi + + withdraw_rewards_one 01 + + withdraw_rewards_one 02 + + withdraw_rewards_one 03 + echo -n "🟢 exposure: " && bc -l <<< "scale=18; $(cast to-unit $(cast call $CONTRACT_ADDRESS "getDelegatedTotal()(uint256)" | sed 's/\[[^]]*\]//g') ether)+$(echo $(rewards))" echo -n "🟢 funds: " && bc -l <<< "scale=18; $(cast to-unit $(cast call $CONTRACT_ADDRESS "getStake()(uint256)" | sed 's/\[[^]]*\]//g') ether)+0.9*$(cast to-unit $(cast call $CONTRACT_ADDRESS "getRewards()(uint256)" | sed 's/\[[^]]*\]//g') ether)" - echo -n "🟢 commission: " && cast to-unit $(cast balance $COMMISSION_ADDRESS) ether - echo -n "🟢 staker balance: " && cast to-unit $(cast balance $STAKER_ADDRESS) ether - echo -n "🟢 staker rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "rewards()(uint256)" --from $STAKER_ADDRESS | sed 's/\[[^]]*\]//g') ether + echo "############################### WITHDRAWING VALIDATOR REWARDS ##############################" withdraw_rewards $CONTROL_KEY_1 withdraw_rewards $CONTROL_KEY_2 @@ -496,6 +553,7 @@ report() { echo -n "🟢 total deposited: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getStake()(uint256)" | sed 's/\[[^]]*\]//g') ether echo -n "🟡 immutable rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getImmutableRewards()(uint256)" | sed 's/\[[^]]*\]//g') ether echo -n "🟡 total rewards: " && cast to-unit $(cast call $CONTRACT_ADDRESS "getRewards()(uint256)" | sed 's/\[[^]]*\]//g') ether + echo -n "🟠 total rounding errors: " && cast call $CONTRACT_ADDRESS "totalRoundingErrors()(uint256)" } diff --git a/src/NonLiquidDelegation.sol b/src/NonLiquidDelegation.sol index b66cfc6..867cf2e 100644 --- a/src/NonLiquidDelegation.sol +++ b/src/NonLiquidDelegation.sol @@ -80,6 +80,8 @@ contract NonLiquidDelegation is IDelegation, BaseDelegation, INonLiquidDelegatio mapping(address => uint256) taxedSinceLastStaking; int256 immutableRewards; mapping(address => address) newAddress; + mapping(address => uint256) roundingErrors; + uint256 totalRoundingErrors; } // keccak256(abi.encode(uint256(keccak256("zilliqa.storage.NonLiquidDelegation")) - 1)) & ~bytes32(uint256(0xff)) @@ -319,6 +321,13 @@ contract NonLiquidDelegation is IDelegation, BaseDelegation, INonLiquidDelegatio return resultInTotal - resultInTotal * getCommissionNumerator() / DENOMINATOR + $.availableTaxedRewards[_msgSender()]; } + /* this breaks the invariant that getRewards() is not decreasing over time and causes underflows + function getRewards() public view override returns(uint256 total) { + total = super.getRewards(); + NonLiquidDelegationStorage storage $ = _getNonLiquidDelegationStorage(); + total -= $.totalRoundingErrors / 1 ether; + }*/ + /** * @dev Return the total amount of taxed rewards the caller is eligible to withdraw. */ @@ -393,6 +402,15 @@ contract NonLiquidDelegation is IDelegation, BaseDelegation, INonLiquidDelegatio emit Staked(_msgSender(), amount, ""); } + /** + * @dev Returns the total amount of rewards in `wei * 10**18` that was not paid out due to + * rounding errors. + */ + function totalRoundingErrors() public view returns(uint256) { + NonLiquidDelegationStorage storage $ = _getNonLiquidDelegationStorage(); + return $.totalRoundingErrors; + } + /** * @dev Make the requested `amount` of taxed rewards available to the caller for staking or * withdrawing by traversing the {Staking} history in `1 + additionalSteps`. @@ -402,14 +420,19 @@ contract NonLiquidDelegation is IDelegation, BaseDelegation, INonLiquidDelegatio */ function _useRewards(uint256 amount, uint64 additionalSteps) internal whenNotPaused returns(uint256, uint256) { NonLiquidDelegationStorage storage $ = _getNonLiquidDelegationStorage(); + uint256 oldRoundingError = $.roundingErrors[_msgSender()]; ( uint256 resultInTotal, uint256 resultAfterLastStaking, uint64 posInStakingIndices, uint64 nextStakingIndex, + uint256 roundingError ) = additionalSteps == type(uint64).max ? _rewards() : _rewards(additionalSteps); + $.roundingErrors[_msgSender()] = roundingError; + $.totalRoundingErrors -= oldRoundingError; + $.totalRoundingErrors += roundingError; // the caller has not delegated any stake yet if (nextStakingIndex == 0) return (0, 0); @@ -463,6 +486,7 @@ contract NonLiquidDelegation is IDelegation, BaseDelegation, INonLiquidDelegatio uint64 firstStakingIndex; uint256 amount; uint256 total; + roundingError = $.roundingErrors[_msgSender()]; for ( posInStakingIndices = $.firstStakingIndex[_msgSender()]; posInStakingIndices < $.stakingIndices[_msgSender()].length; @@ -489,14 +513,19 @@ contract NonLiquidDelegation is IDelegation, BaseDelegation, INonLiquidDelegatio } total = $.stakings[nextStakingIndex].total; nextStakingIndex++; - if (nextStakingIndex - firstStakingIndex > additionalSteps) + if (nextStakingIndex - firstStakingIndex > additionalSteps) { + if (getRewards() >= resultInTotal + roundingError / 1 ether) { + resultInTotal += roundingError / 1 ether; + roundingError -= 1 ether * (roundingError / 1 ether); + } return ( - resultInTotal + roundingError / 1 ether, + resultInTotal, resultAfterLastStaking, posInStakingIndices, nextStakingIndex, - roundingError - 1 ether * (roundingError / 1 ether) + roundingError ); + } } } @@ -517,8 +546,10 @@ contract NonLiquidDelegation is IDelegation, BaseDelegation, INonLiquidDelegatio // existed during the current call of the function so that we can continue from there if (posInStakingIndices > 0) posInStakingIndices--; - resultInTotal += roundingError / 1 ether; - roundingError -= 1 ether * (roundingError / 1 ether); + if (getRewards() >= resultInTotal + roundingError / 1 ether) { + resultInTotal += roundingError / 1 ether; + roundingError -= 1 ether * (roundingError / 1 ether); + } } /** diff --git a/test/NonLiquidDelegation.t.sol b/test/NonLiquidDelegation.t.sol index b1d50d2..11622e1 100644 --- a/test/NonLiquidDelegation.t.sol +++ b/test/NonLiquidDelegation.t.sol @@ -2049,6 +2049,7 @@ contract NonLiquidDelegationTest is BaseDelegationTest { Console.log("round %s of %s", i, numOfRounds); assertEq(delegation.getStake(), delegation.getDelegatedTotal(), "getStake does not match getDelegatedTotal"); assertEq(totalWithdrawnZil + delegation.totalPendingWithdrawals(), totalUnstakedZil, "owned does not match owed"); + assertLt(delegation.totalRoundingErrors(), numOfUsers * 1 ether, "rounding errors out of bounds"); } uint256 outstandingRewards; for (uint256 i = 0; i < users.length; i++) {