Skip to content

Commit ae30e7c

Browse files
committed
make vote-update reward token parameter optional;
use SpecToken for reward tokens in vote-update and update-pool commands;
1 parent 2e745ff commit ae30e7c

File tree

6 files changed

+129
-112
lines changed

6 files changed

+129
-112
lines changed

core/src/box_kind/ballot_box.rs

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ use crate::{
33
BallotContract, BallotContractError, BallotContractInputs, BallotContractParameters,
44
},
55
oracle_types::BlockHeight,
6-
pool_config::CastBallotBoxVoteParameters,
7-
spec_token::{BallotTokenId, SpecToken, TokenIdKind, UpdateTokenId},
6+
spec_token::{BallotTokenId, RewardTokenId, SpecToken, TokenIdKind, UpdateTokenId},
87
};
98
use ergo_lib::{
109
chain::ergo_box::box_builder::{ErgoBoxCandidateBuilder, ErgoBoxCandidateBuilderError},
@@ -13,7 +12,7 @@ use ergo_lib::{
1312
chain::{
1413
address::{Address, AddressEncoderError},
1514
ergo_box::{box_value::BoxValue, ErgoBox, ErgoBoxCandidate, NonMandatoryRegisterId},
16-
token::{Token, TokenId},
15+
token::TokenId,
1716
},
1817
mir::constant::{TryExtractFromError, TryExtractInto},
1918
serialization::SigmaSerializationError,
@@ -28,10 +27,6 @@ pub enum BallotBoxError {
2827
NoBallotToken,
2928
#[error("ballot box: unknown ballot token id in `TOKENS(0)`")]
3029
UnknownBallotTokenId,
31-
#[error("ballot box: no reward token id in R7 register")]
32-
NoRewardTokenIdInR7,
33-
#[error("ballot box: no reward token quantity in R8 register")]
34-
NoRewardTokenQuantityInR8,
3530
#[error("ballot box: no group element in R4 register")]
3631
NoGroupElementInR4,
3732
#[error("ballot box: unexpected group element in R4 register")]
@@ -48,6 +43,8 @@ pub enum BallotBoxError {
4843
TryExtractFrom(#[from] TryExtractFromError),
4944
#[error("ballot box: SigmaSerializationError {0:?}")]
5045
SigmaSerialization(#[from] SigmaSerializationError),
46+
#[error("invalid reward token: {0:?}")]
47+
InvalidRewardToken(String),
5148
}
5249

5350
pub trait BallotBox {
@@ -130,6 +127,13 @@ impl BallotBoxWrapperInputs {
130127
}
131128
}
132129

130+
#[derive(Debug, Clone, PartialEq, Eq)]
131+
pub struct CastBallotBoxVoteParameters {
132+
pub pool_box_address_hash: Digest32,
133+
pub reward_token_opt: Option<SpecToken<RewardTokenId>>,
134+
pub update_box_creation_height: i32,
135+
}
136+
133137
/// A Ballot Box with vote parameters guaranteed to be set
134138
#[derive(Clone, Debug)]
135139
pub struct VoteBallotBoxWrapper {
@@ -169,21 +173,31 @@ impl VoteBallotBoxWrapper {
169173
.ok_or(BallotBoxError::NoPoolBoxAddressInR6)?
170174
.try_extract_into::<Digest32>()?;
171175

172-
let reward_token_id = ergo_box
176+
let reward_token_id_opt = ergo_box
173177
.get_register(NonMandatoryRegisterId::R7.into())
174-
.ok_or(BallotBoxError::NoRewardTokenIdInR7)?
175-
.try_extract_into::<TokenId>()?;
176-
let reward_token_quantity = ergo_box
178+
.map(|c| c.try_extract_into::<TokenId>());
179+
let reward_token_quantity_opt = ergo_box
177180
.get_register(NonMandatoryRegisterId::R8.into())
178-
.ok_or(BallotBoxError::NoRewardTokenQuantityInR8)?
179-
.try_extract_into::<i64>()? as u64;
181+
.map(|c| c.try_extract_into::<i64>());
180182

183+
let reward_token_opt = match (reward_token_id_opt, reward_token_quantity_opt) {
184+
(Some(Ok(reward_token_id)), Some(Ok(reward_token_quantity))) => Some(SpecToken {
185+
token_id: RewardTokenId::from_token_id_unchecked(reward_token_id),
186+
amount: (reward_token_quantity as u64).try_into().unwrap(),
187+
}),
188+
(None, None) => None,
189+
(id, amt) => {
190+
return Err(BallotBoxError::InvalidRewardToken(format!(
191+
"Reward token id {:?} amount {:?}",
192+
id, amt
193+
)))
194+
}
195+
};
181196
let contract =
182197
BallotContract::from_ergo_tree(ergo_box.ergo_tree.clone(), &inputs.contract_inputs)?;
183198
let vote_parameters = CastBallotBoxVoteParameters {
184199
pool_box_address_hash,
185-
reward_token_id,
186-
reward_token_quantity,
200+
reward_token_opt,
187201
update_box_creation_height,
188202
};
189203
Ok(Self {
@@ -269,7 +283,7 @@ pub fn make_local_ballot_box_candidate(
269283
update_box_creation_height: BlockHeight,
270284
ballot_token: SpecToken<BallotTokenId>,
271285
pool_box_address_hash: Digest32,
272-
reward_tokens: Token,
286+
reward_token_opt: Option<SpecToken<RewardTokenId>>,
273287
value: BoxValue,
274288
creation_height: BlockHeight,
275289
) -> Result<ErgoBoxCandidate, ErgoBoxCandidateBuilderError> {
@@ -283,11 +297,16 @@ pub fn make_local_ballot_box_candidate(
283297
(update_box_creation_height.0 as i32).into(),
284298
);
285299
builder.set_register_value(NonMandatoryRegisterId::R6, pool_box_address_hash.into());
286-
builder.set_register_value(NonMandatoryRegisterId::R7, reward_tokens.token_id.into());
287-
builder.set_register_value(
288-
NonMandatoryRegisterId::R8,
289-
(*reward_tokens.amount.as_u64() as i64).into(),
290-
);
300+
if let Some(reward_tokens) = reward_token_opt {
301+
builder.set_register_value(
302+
NonMandatoryRegisterId::R7,
303+
reward_tokens.token_id.token_id().into(),
304+
);
305+
builder.set_register_value(
306+
NonMandatoryRegisterId::R8,
307+
(*reward_tokens.amount.as_u64() as i64).into(),
308+
);
309+
}
291310
builder.add_token(ballot_token.into());
292311
builder.build()
293312
}

core/src/box_kind/pool_box.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use ergo_lib::ergotree_ir::chain::ergo_box::box_value::BoxValue;
44
use ergo_lib::ergotree_ir::chain::ergo_box::ErgoBox;
55
use ergo_lib::ergotree_ir::chain::ergo_box::ErgoBoxCandidate;
66
use ergo_lib::ergotree_ir::chain::ergo_box::NonMandatoryRegisterId;
7-
use ergo_lib::ergotree_ir::chain::token::Token;
87
use ergo_lib::ergotree_ir::mir::constant::TryExtractInto;
98
use thiserror::Error;
109

@@ -229,14 +228,14 @@ pub fn make_pool_box_candidate_unchecked(
229228
datapoint: i64,
230229
epoch_counter: EpochCounter,
231230
pool_nft_token: SpecToken<PoolTokenId>,
232-
reward_token: Token,
231+
reward_token: SpecToken<RewardTokenId>,
233232
value: BoxValue,
234233
creation_height: BlockHeight,
235234
) -> Result<ErgoBoxCandidate, ErgoBoxCandidateBuilderError> {
236235
let mut builder = ErgoBoxCandidateBuilder::new(value, contract.ergo_tree(), creation_height.0);
237236
builder.set_register_value(NonMandatoryRegisterId::R4, datapoint.into());
238237
builder.set_register_value(NonMandatoryRegisterId::R5, (epoch_counter.0 as i32).into());
239238
builder.add_token(pool_nft_token.into());
240-
builder.add_token(reward_token);
239+
builder.add_token(reward_token.into());
241240
builder.build()
242241
}

core/src/cli_commands/update_pool.rs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use ergo_lib::{
99
ergotree_ir::chain::{
1010
address::Address,
1111
ergo_box::{ErgoBox, NonMandatoryRegisterId},
12-
token::Token,
1312
},
1413
ergotree_ir::serialization::SigmaSerializable,
1514
wallet::{
@@ -24,16 +23,17 @@ use std::convert::TryInto;
2423

2524
use crate::{
2625
box_kind::{
27-
make_pool_box_candidate_unchecked, BallotBox, PoolBox, PoolBoxWrapper, VoteBallotBoxWrapper,
26+
make_pool_box_candidate_unchecked, BallotBox, CastBallotBoxVoteParameters, PoolBox,
27+
PoolBoxWrapper, VoteBallotBoxWrapper,
2828
},
2929
cli_commands::ergo_explorer_transaction_link,
3030
contracts::pool::PoolContract,
3131
node_interface::{SignTransaction, SubmitTransaction},
3232
oracle_config::BASE_FEE,
3333
oracle_state::{OraclePool, PoolBoxSource, StageError, UpdateBoxSource, VoteBallotBoxesSource},
3434
oracle_types::BlockHeight,
35-
pool_config::{CastBallotBoxVoteParameters, PoolConfig, POOL_CONFIG},
36-
spec_token::TokenIdKind,
35+
pool_config::{PoolConfig, POOL_CONFIG},
36+
spec_token::{RewardTokenId, SpecToken, TokenIdKind},
3737
wallet::{WalletDataError, WalletDataSource},
3838
};
3939
use derive_more::From;
@@ -77,7 +77,7 @@ pub fn update_pool(
7777
tx_signer: &dyn SignTransaction,
7878
tx_submit: &dyn SubmitTransaction,
7979
new_pool_box_hash_str: Option<String>,
80-
new_reward_tokens: Option<Token>,
80+
new_reward_tokens: Option<SpecToken<RewardTokenId>>,
8181
height: BlockHeight,
8282
) -> Result<(), UpdatePoolError> {
8383
info!("Opening pool_config_updated.yaml");
@@ -137,9 +137,9 @@ fn display_update_diff(
137137
old_pool_config: &PoolConfig,
138138
new_pool_config: &PoolConfig,
139139
old_pool_box: PoolBoxWrapper,
140-
new_reward_tokens: Option<Token>,
140+
new_reward_tokens: Option<SpecToken<RewardTokenId>>,
141141
) {
142-
let new_tokens = new_reward_tokens.unwrap_or_else(|| old_pool_box.reward_token().into());
142+
let new_tokens = new_reward_tokens.unwrap_or_else(|| old_pool_box.reward_token());
143143
let new_pool_contract =
144144
PoolContract::checked_load(&new_pool_config.pool_box_wrapper_inputs.contract_inputs)
145145
.unwrap();
@@ -189,7 +189,7 @@ fn build_update_pool_box_tx(
189189
wallet: &dyn WalletDataSource,
190190
update_box: &dyn UpdateBoxSource,
191191
new_pool_contract: PoolContract,
192-
new_reward_tokens: Option<Token>,
192+
new_reward_tokens: Option<SpecToken<RewardTokenId>>,
193193
height: BlockHeight,
194194
change_address: Address,
195195
) -> Result<TransactionContext<UnsignedTransaction>, UpdatePoolError> {
@@ -202,13 +202,12 @@ fn build_update_pool_box_tx(
202202
.sigma_serialize_bytes()
203203
.unwrap(),
204204
);
205-
let reward_tokens = new_reward_tokens.unwrap_or_else(|| old_pool_box.reward_token().into());
206205
let vote_parameters = CastBallotBoxVoteParameters {
207206
pool_box_address_hash: pool_box_hash,
208-
reward_token_id: reward_tokens.token_id,
209-
reward_token_quantity: *reward_tokens.amount.as_u64(),
207+
reward_token_opt: new_reward_tokens.clone(),
210208
update_box_creation_height: update_box.get_box().creation_height as i32,
211209
};
210+
let reward_tokens = new_reward_tokens.unwrap_or_else(|| old_pool_box.reward_token());
212211
// Find ballot boxes that are voting for the new pool hash
213212
let mut sorted_ballot_boxes = ballot_boxes.get_ballot_boxes()?;
214213
// Sort in descending order of ballot token amounts. If two boxes have the same amount of ballot tokens, also compare box value, in case some boxes were incorrectly created below minStorageRent
@@ -278,11 +277,12 @@ fn build_update_pool_box_tx(
278277
}
279278

280279
let target_balance = *BASE_FEE;
281-
let target_tokens = if reward_tokens.token_id != old_pool_box.reward_token().token_id() {
282-
vec![reward_tokens.clone()]
283-
} else {
284-
vec![]
285-
};
280+
let target_tokens =
281+
if reward_tokens.token_id.token_id() != old_pool_box.reward_token().token_id() {
282+
vec![reward_tokens.clone().into()]
283+
} else {
284+
vec![]
285+
};
286286
let box_selector = SimpleBoxSelector::new();
287287
let selection = box_selector.select(unspent_boxes, target_balance, &target_tokens)?;
288288
let mut input_boxes = vec![old_pool_box.get_box().clone(), update_box.get_box().clone()];
@@ -321,7 +321,7 @@ fn build_update_pool_box_tx(
321321
change_address,
322322
);
323323

324-
if reward_tokens.token_id != old_pool_box.reward_token().token_id() {
324+
if reward_tokens.token_id.token_id() != old_pool_box.reward_token().token_id() {
325325
tx_builder.set_token_burn_permit(vec![old_pool_box.reward_token().into()]);
326326
}
327327

@@ -379,7 +379,7 @@ mod tests {
379379
generate_token_ids, make_wallet_unspent_box, BallotBoxesMock, PoolBoxMock,
380380
UpdateBoxMock, WalletDataMock,
381381
},
382-
spec_token::{RefreshTokenId, SpecToken, TokenIdKind},
382+
spec_token::{RefreshTokenId, RewardTokenId, SpecToken, TokenIdKind},
383383
};
384384

385385
use super::build_update_pool_box_tx;
@@ -405,8 +405,8 @@ mod tests {
405405
token_id: token_ids.reward_token_id.clone(),
406406
amount: 1500.try_into().unwrap(),
407407
};
408-
let new_reward_tokens = Token {
409-
token_id: force_any_tokenid(),
408+
let new_reward_tokens = SpecToken {
409+
token_id: RewardTokenId::from_token_id_unchecked(force_any_tokenid()),
410410
amount: force_any_val(),
411411
};
412412
dbg!(&new_reward_tokens);
@@ -498,7 +498,7 @@ mod tests {
498498
amount: 1.try_into().unwrap(),
499499
},
500500
pool_box_hash,
501-
new_reward_tokens.clone(),
501+
Some(new_reward_tokens.clone()),
502502
ballot_contract.min_storage_rent(),
503503
height,
504504
)
@@ -524,7 +524,7 @@ mod tests {
524524
// create a wallet box with new reward tokens
525525
secret.public_image(),
526526
BASE_FEE.checked_mul_u32(4_000_000_000).unwrap(),
527-
Some(vec![new_reward_tokens.clone()].try_into().unwrap()),
527+
Some(vec![new_reward_tokens.clone().into()].try_into().unwrap()),
528528
);
529529
let change_address = AddressEncoder::unchecked_parse_network_address_from_str(
530530
"9iHyKxXs2ZNLMp9N9gbUT9V8gTbsV7HED1C1VhttMfBUMPDyF7r",

0 commit comments

Comments
 (0)