Improve UI and delegators logic for banned pools (#2670)

Add ban reason, delegators' ban period, and make corresponding UI changes.
staking
Ed Man 5 years ago committed by Victor Baranov
parent e167996a7e
commit 888e56c13d
  1. 6
      apps/block_scout_web/assets/css/components/_stakes_table.scss
  2. 10
      apps/block_scout_web/assets/css/components/stakes/_modal_validator_info.scss
  3. 1
      apps/block_scout_web/assets/css/components/stakes/_stakes.scss
  4. 2
      apps/block_scout_web/lib/block_scout_web/channels/stakes_channel.ex
  5. 1
      apps/block_scout_web/lib/block_scout_web/controllers/stakes_controller.ex
  6. 15
      apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex
  7. 19
      apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex
  8. 3
      apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex
  9. 10
      apps/explorer/lib/explorer/chain/staking_pool.ex
  10. 3
      apps/explorer/lib/explorer/staking/contract_reader.ex
  11. 12
      apps/explorer/lib/explorer/staking/contract_state.ex
  12. 57
      apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json
  13. 11
      apps/explorer/priv/repo/migrations/20190904170014_add_additional_ban_fields_to_staking_pools.exs
  14. 14
      apps/explorer/test/explorer/staking/contract_state_test.exs

@ -114,6 +114,12 @@ $stakes-table-cell-separation: 25px !default;
background-color: $stakes-banned-background;
color: $stakes-banned-color;
}
.stakes-td-banned-info {
display: block;
float: left;
padding-right: 30px;
}
}
.stakes-td-order {

@ -47,3 +47,13 @@
padding: 0;
}
}
.modal-validator-alert {
padding: 10px 30px;
background-color: #fff3f7;
color: #ff7986;
border-top: 1px solid #fee6ef;
border-bottom: 1px solid #fee6ef;
line-height: 1.5;
font-size: 14px;
}

@ -95,6 +95,7 @@ $stakes-stats-item-border-color: #fff !default;
display: flex;
justify-content: flex-end;
padding-right: 30px;
float: left;
}
.stakes-control {

@ -36,12 +36,14 @@ defmodule BlockScoutWeb.StakesChannel do
def handle_in("render_validator_info", %{"address" => staking_address}, socket) do
pool = Chain.staking_pool(staking_address)
delegator = socket.assigns[:account] && Chain.staking_pool_delegator(staking_address, socket.assigns.account)
average_block_time = AverageBlockTime.average_block_time()
token = ContractState.get(:token)
html =
View.render_to_string(StakesView, "_stakes_modal_validator_info.html",
validator: pool,
delegator: delegator,
average_block_time: average_block_time,
token: token
)

@ -92,6 +92,7 @@ defmodule BlockScoutWeb.StakesController do
"_rows.html",
token: token,
pool: pool,
delegator: delegator,
index: index,
average_block_time: average_block_time,
pools_type: filter,

@ -34,9 +34,20 @@
<td class="stakes-td">
<%= if @pool.is_banned do %>
<span class="stakes-td-banned-info">
Banned until block #<%= @pool.banned_until %> (<%= estimated_unban_day(@pool.banned_until, @average_block_time) %>)
Banned until block #<%= @pool.banned_until %> (<%= estimated_unban_day(@pool.banned_until, @average_block_time) %>).
<%= if @delegator &&
@delegator.delegator_address_hash != @pool.staking_address_hash &&
@pool.are_delegators_banned &&
@pool.banned_until != @pool.banned_delegators_until do %>
You will be able to withdraw after block #<%= @pool.banned_delegators_until %> (<%= estimated_unban_day(@pool.banned_delegators_until, @average_block_time) %>)
<% end %>
</span>
<% else %>
<% end %>
<%= if !@pool.is_banned ||
(!@pool.are_delegators_banned &&
@delegator &&
@delegator.delegator_address_hash != @pool.staking_address_hash
) do %>
<div class="stakes-controls">
<%= if @buttons.move do %>
<%= render BlockScoutWeb.StakesView, "_stakes_control_move.html", address: @pool.staking_address_hash %>

@ -10,6 +10,19 @@
</div>
</div>
</div>
<%= if @validator.is_banned do %>
<div class="modal-validator-alert">
This pool is banned until block <%= "##{@validator.banned_until} (#{estimated_unban_day(@validator.banned_until, @average_block_time)})" %><br />
Reason for Ban: <%= String.capitalize(@validator.ban_reason) %>
<%= if @delegator &&
@delegator.delegator_address_hash != @validator.staking_address_hash &&
@validator.are_delegators_banned &&
@validator.banned_until != @validator.banned_delegators_until do %>
<br />
You will be able to withdraw after block #<%= @validator.banned_delegators_until %> (<%= estimated_unban_day(@validator.banned_delegators_until, @average_block_time) %>)
<% end %>
</div>
<% end %>
<%= render BlockScoutWeb.CommonComponentsView, "_modal_close_button.html" %>
<div class="modal-validator-info-content">
<%=
@ -48,12 +61,6 @@
title: "How Many Times this Address has been Banned",
value: @validator.was_banned_count
%>
<%=
render BlockScoutWeb.StakesView,
"_stakes_validator_info_item.html",
title: "The Block Number and Approximate Date When the Address Will be Unbanned",
value: if(@validator.is_banned, do: "##{@validator.banned_until} (#{estimated_unban_day(@validator.banned_until, @average_block_time)})")
%>
<%=
render BlockScoutWeb.StakesView,
"_stakes_validator_info_item.html",

@ -128,15 +128,18 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do
is_banned: fragment("EXCLUDED.is_banned"),
is_validator: fragment("EXCLUDED.is_validator"),
is_unremovable: fragment("EXCLUDED.is_unremovable"),
are_delegators_banned: fragment("EXCLUDED.are_delegators_banned"),
likelihood: fragment("EXCLUDED.likelihood"),
block_reward_ratio: fragment("EXCLUDED.block_reward_ratio"),
staked_ratio: fragment("EXCLUDED.staked_ratio"),
self_staked_amount: fragment("EXCLUDED.self_staked_amount"),
staked_amount: fragment("EXCLUDED.staked_amount"),
ban_reason: fragment("EXCLUDED.ban_reason"),
was_banned_count: fragment("EXCLUDED.was_banned_count"),
was_validator_count: fragment("EXCLUDED.was_validator_count"),
is_deleted: fragment("EXCLUDED.is_deleted"),
banned_until: fragment("EXCLUDED.banned_until"),
banned_delegators_until: fragment("EXCLUDED.banned_delegators_until"),
inserted_at: fragment("LEAST(?, EXCLUDED.inserted_at)", pool.inserted_at),
updated_at: fragment("GREATEST(?, EXCLUDED.updated_at)", pool.updated_at)
]

@ -15,17 +15,20 @@ defmodule Explorer.Chain.StakingPool do
@type t :: %__MODULE__{
staking_address_hash: Hash.Address.t(),
mining_address_hash: Hash.Address.t(),
banned_until: boolean,
banned_until: integer,
banned_delegators_until: integer,
delegators_count: integer,
is_active: boolean,
is_banned: boolean,
is_validator: boolean,
is_unremovable: boolean,
are_delegators_banned: boolean,
likelihood: Decimal.t(),
block_reward_ratio: Decimal.t(),
staked_ratio: Decimal.t(),
self_staked_amount: Decimal.t(),
staked_amount: Decimal.t(),
ban_reason: String.t(),
was_banned_count: integer,
was_validator_count: integer,
is_deleted: boolean
@ -33,7 +36,7 @@ defmodule Explorer.Chain.StakingPool do
@attrs ~w(
is_active delegators_count staked_amount self_staked_amount is_validator
was_validator_count is_banned was_banned_count banned_until likelihood
was_validator_count is_banned are_delegators_banned ban_reason was_banned_count banned_until banned_delegators_until likelihood
staked_ratio staking_address_hash mining_address_hash block_reward_ratio
is_unremovable
)a
@ -45,16 +48,19 @@ defmodule Explorer.Chain.StakingPool do
schema "staking_pools" do
field(:banned_until, :integer)
field(:banned_delegators_until, :integer)
field(:delegators_count, :integer)
field(:is_active, :boolean, default: false)
field(:is_banned, :boolean, default: false)
field(:is_validator, :boolean, default: false)
field(:is_unremovable, :boolean, default: false)
field(:are_delegators_banned, :boolean, default: false)
field(:likelihood, :decimal)
field(:block_reward_ratio, :decimal)
field(:staked_ratio, :decimal)
field(:self_staked_amount, :decimal)
field(:staked_amount, :decimal)
field(:ban_reason, :string)
field(:was_banned_count, :integer)
field(:was_validator_count, :integer)
field(:is_deleted, :boolean, default: false)

@ -41,7 +41,10 @@ defmodule Explorer.Staking.ContractReader do
[
was_validator_count: {:validator_set, "validatorCounter", [mining_address]},
is_banned: {:validator_set, "isValidatorBanned", [mining_address]},
are_delegators_banned: {:validator_set, "areDelegatorsBanned", [mining_address]},
ban_reason: {:validator_set, "banReason", [mining_address]},
banned_until: {:validator_set, "bannedUntil", [mining_address]},
banned_delegators_until: {:validator_set, "bannedDelegatorsUntil", [mining_address]},
was_banned_count: {:validator_set, "banCounter", [mining_address]}
]
end

@ -186,7 +186,8 @@ defmodule Explorer.Staking.ContractState do
block_reward_ratio: staking_response.block_reward / 10_000,
is_deleted: false,
is_validator: is_validator[staking_response.mining_address_hash] || false,
is_unremovable: hash_to_string(staking_address) == unremovable_validator
is_unremovable: hash_to_string(staking_address) == unremovable_validator,
ban_reason: binary_to_string(mining_response.ban_reason)
}
|> Map.merge(
Map.take(staking_response, [
@ -200,7 +201,9 @@ defmodule Explorer.Staking.ContractState do
Map.take(mining_response, [
:was_validator_count,
:is_banned,
:are_delegators_banned,
:banned_until,
:banned_delegators_until,
:was_banned_count
])
)
@ -318,4 +321,11 @@ defmodule Explorer.Staking.ContractState do
|> File.read!()
|> Jason.decode!()
end
defp binary_to_string(binary) do
binary
|> :binary.bin_to_list()
|> Enum.filter(fn x -> x != 0 end)
|> List.to_string()
end
end

@ -126,6 +126,25 @@
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "banReason",
"outputs": [
{
"name": "",
"type": "bytes32"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
@ -145,6 +164,25 @@
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "bannedDelegatorsUntil",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
@ -630,6 +668,25 @@
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_miningAddress",
"type": "address"
}
],
"name": "areDelegatorsBanned",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [

@ -0,0 +1,11 @@
defmodule Explorer.Repo.Migrations.AddAdditionalBanFieldsToStakingPools do
use Ecto.Migration
def change do
alter table(:staking_pools) do
add(:are_delegators_banned, :boolean, default: false)
add(:ban_reason, :string)
add(:banned_delegators_until, :bigint)
end
end
end

@ -149,7 +149,7 @@ defmodule Explorer.Staking.ContractStateTest do
EthereumJSONRPC.Mox,
:json_rpc,
fn requests, _opts ->
assert length(requests) == 16
assert length(requests) == 28
{:ok,
format_responses([
@ -157,17 +157,29 @@ defmodule Explorer.Staking.ContractStateTest do
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000002",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x000000000000000000000000000000000000000000000000000000000000004a",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x000000000000000000000000000000000000000000000000000000000000004a",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000"
])}
end

Loading…
Cancel
Save