In case of multiple interaction of a user to same entry-point with same input parameter. I wish to revert the amount provided by user to the payable contract if their is multiple execution.
type MatchId = u64;
#[receive(
contract = "cryptogammon",
name = "enter_player_one",
parameter = "MatchId",
error = "CryptogammonError",
mutable,
enable_logger,
payable
)]
fn enter_player_one<S: HasStateApi>(
ctx: &impl HasReceiveContext,
host: &mut impl HasHost<State<S>, StateApiType = S>,
_amount: Amount,
logger: &mut impl HasLogger,
) -> ContractResult<()> {
// Parse the parameter.
let params = ctx.parameter_cursor().get()?;
let (state, _builder) = host.state_and_builder();
let y = match ctx.sender() {
Address::Account(a) => a,
_ => return Err(CryptogammonError::Unauthorized),
};
// Check if the player is already in the match.
state.enter_player_one(&y, &_amount, ¶ms)?;
logger.log(&CryptogammonEvent::Player1(Player1Event {
player1: y,
amount: _amount,
match_id: params,
}))?;
return Ok(());
}
Implementation of helper function is
fn enter_player_one(
&mut self,
address: &AccountAddress,
amount: &Amount,
match_id: &u64,
) -> ContractResult<()> {
let _fee = self.fee;
let _amount = amount.micro_ccd();
let _admin_fee = (_amount * (_fee)) / 10000;
self.total_fees += _admin_fee;
let player_amount = _amount - _admin_fee;
let _amount = Amount::from_micro_ccd(player_amount);
let match_instance = Match {
player1: Option::Some(*address),
player2: Option::None,
amount: _amount,
status: Status::Initialized,
winner: Winner::None,
};
self.address_to_match_id
.insert(*address, Option::Some(*match_id));
self.match_id_to_match
.entry(*match_id)
.or_insert(match_instance);
let mut instance = self.match_id_to_match.get_mut(match_id).unwrap();
ensure_eq!(
instance.status,
Status::Initialized,
CryptogammonError::Player1Error
);
if instance.player2 != Option::None {
instance.player1 = Option::Some(*address);
instance.status = Status::Ongoing;
ensure_eq!(instance.amount, _amount, CryptogammonError::Player1Error);
}
Ok(())
}