Skip to content

Commit d2d7472

Browse files
feature: final V3 of core-mx-life-bonding-sc and V1 of core-mx-liveliness-stake-sc that went to Mainnet
1 parent bc4a99a commit d2d7472

File tree

11 files changed

+174
-134
lines changed

11 files changed

+174
-134
lines changed

core-mx-life-bonding-sc/Cargo.lock

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core-mx-life-bonding-sc/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ publish = false
88
[lib]
99
path = "src/lib.rs"
1010

11-
# [dev-dependencies]
12-
# core-mx-liveliness-stake = {path="../core-mx-liveliness-stake-sc"}
11+
[dev-dependencies]
12+
core-mx-liveliness-stake = {path="../core-mx-liveliness-stake-sc"}
1313

1414
[dependencies.multiversx-sc]
1515
version = "0.51.0"

core-mx-liveliness-stake-sc/Cargo.lock

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core-mx-liveliness-stake-sc/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ path = "src/lib.rs"
1111
[dependencies.multiversx-sc]
1212
version = "0.51.0"
1313

14-
# [dev-dependencies]
15-
# core-mx-life-bonding-sc = {path="../core-mx-life-bonding-sc"}
16-
# num-traits= "0.2.19"
14+
[dev-dependencies]
15+
core-mx-life-bonding-sc = {path="../core-mx-life-bonding-sc"}
16+
num-traits= "0.2.19"
1717

1818
[dev-dependencies.multiversx-sc-scenario]
1919
version = "0.51.0"

core-mx-liveliness-stake-sc/README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ Understanding this document is also easier if one knows how [ESDT token transact
1212

1313
## Itheum deployed contract addresses
1414

15-
| Devnet | Mainnet |
16-
| erd1qqqqqqqqqqqqqpgq9j3dj650amzz8lyvek6uq0w0yvgtgggjfsxsf489hq | ------- |
17-
| | |
15+
| Devnet | Mainnet |
16+
| -------------------------------------------------------------- | -------------------------------------------------------------- |
17+
| erd1qqqqqqqqqqqqqpgq9j3dj650amzz8lyvek6uq0w0yvgtgggjfsxsf489hq | erd1qqqqqqqqqqqqqpgq65rn8zmf2tckftpu5lvxg2pzlg0dhfrwc77qcuynw7 |
1818

1919
## Endpoints
2020

@@ -37,9 +37,12 @@ cargo clean
3737
cargo build
3838
```
3939

40+
**Note: REMOVE V1 workaround code from upgrade method in lib.rc**
41+
Check the notes in `upgrade` and remove as needed before any further upgrade.
42+
4043
**Note: REMOVE DEV DEPENDENCIES BEFORE FINAL BUILD**
4144

42-
- As you can see in the main Cargo.toml, we are pointing to in the [dev-dependencies] section to the life-bonding-sc contract. This is only needed for unit tests and local build and test, so in the final build (i.e. before you call the reproducible build), we should comment this out or else the docket build will fail (and also cause we dont need this in the final build we deploy to the blockchain)
45+
- As you can see in the main Cargo.toml, we are pointing to in the [dev-dependencies] section to the life-bonding-sc contract. This is only needed for unit tests and local build and test, so in the final build (i.e. before you call the reproducible build), we should comment this out or else the docket build will fail (and also cause we don't need this in the final build we deploy to the blockchain)
4346

4447
**Note: PROXY FILES**
4548

core-mx-liveliness-stake-sc/interaction/devnet.snippets.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,16 @@ deploy(){
4141
# for upgrade, --outfile deployOutput is not needed
4242
# in below code example we added --metadata-payable to add PAYABLE to the prop of the SC and removed --metadata-not-readable to make it READABLE
4343
upgrade(){
44+
# $1 = address
45+
46+
address="0x$(mxpy wallet bech32 --decode ${1})"
47+
4448
mxpy --verbose contract upgrade ${ADDRESS} \
4549
--bytecode output-docker/core-mx-liveliness-stake/core-mx-liveliness-stake.wasm \
4650
--metadata-not-readable \
4751
--metadata-payable-by-sc \
4852
--pem ${WALLET} \
53+
--arguments $address \
4954
--proxy ${PROXY} \
5055
--chain ${CHAIN_ID} \
5156
--gas-limit 150000000 \

core-mx-liveliness-stake-sc/interaction/mainnet.snippets.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,15 @@ deployMainnet(){
3939
# for upgrade, --outfile deployOutput is not needed
4040
# in below code example we added --metadata-payable to add PAYABLE to the prop of the SC and removed --metadata-not-readable to make it READABLE
4141
upgradeMainnet(){
42+
# $1 = address
43+
44+
# address="0x$(mxpy wallet bech32 --decode ${1})"
45+
4246
mxpy --verbose contract upgrade ${ADDRESS} \
4347
--bytecode output-docker/core-mx-liveliness-stake/core-mx-liveliness-stake.wasm \
4448
--metadata-not-readable \
4549
--metadata-payable-by-sc \
50+
# --arguments $address \
4651
--proxy ${PROXY} \
4752
--chain ${CHAIN_ID} \
4853
--gas-limit 150000000 \

core-mx-liveliness-stake-sc/src/lib.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,19 @@ pub trait CoreMxLivelinessStake:
3131
fn init(&self) {}
3232

3333
#[upgrade]
34-
fn upgrade(&self) {
34+
fn upgrade(&self, address: ManagedAddress) {
3535
self.set_contract_state_inactive();
36+
37+
// @TODO: WAS NEEDED AS WE SOLVED ISSUES WITH MAINNET UPGRADE, THIS SHOULD BE DELETED AFTER UPGRADE
38+
// IN THE NEXT OFFICIAL UPGRADE, LETS REMOVE THIS CODE AND ALSO the 'address: ManagedAddress' ABOVE
39+
// self.address_last_reward_per_share(&address).clear();
40+
// self.address_stack_rewards(&address).clear();
41+
// self.rewards_per_share().clear();
42+
// self.rewards_reserve()
43+
// .update(|value| *value += self.accumulated_rewards().get());
44+
// self.accumulated_rewards().clear();
3645
}
46+
3747
#[endpoint(claimRewards)]
3848
fn claim_rewards(&self) {
3949
require_contract_ready!(self, ERR_CONTRACT_NOT_READY);
Lines changed: 100 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,110 @@
11
use crate::{
2-
config::{self, BLOCKS_IN_YEAR, DIVISION_SAFETY_CONST, MAX_PERCENT},
3-
contexts::base::StorageCache,
4-
events, proxy_contracts, storage,
2+
config::{self, BLOCKS_IN_YEAR, DIVISION_SAFETY_CONST, MAX_PERCENT},
3+
contexts::base::StorageCache,
4+
events, proxy_contracts, storage,
55
};
66

77
multiversx_sc::imports!();
88
multiversx_sc::derive_imports!();
99

1010
#[multiversx_sc::module]
1111
pub trait RewardsModule:
12-
storage::StorageModule + config::ConfigModule + events::EventsModule
12+
storage::StorageModule + config::ConfigModule + events::EventsModule
1313
{
14-
#[endpoint(generateAggregatedRewards)]
15-
fn generate_rewards(&self) {
16-
let mut storage_cache = StorageCache::new(self);
17-
self.generate_aggregated_rewards(&mut storage_cache);
18-
}
19-
fn generate_aggregated_rewards(&self, storage_cache: &mut StorageCache<Self>) {
20-
let last_reward_nonce = self.last_reward_block_nonce().get();
21-
let extra_rewards_unbounded = self.calculate_rewards_since_last_allocation(storage_cache);
22-
let max_apr = self.max_apr().get();
23-
24-
let extra_rewards: BigUint;
25-
if max_apr > BigUint::zero() {
26-
let extra_rewards_apr_bounded_per_block =
27-
self.get_amount_apr_bounded(&storage_cache.rewards_reserve);
28-
29-
let current_block_nonce = self.blockchain().get_block_nonce();
30-
31-
let block_nonce_diff = current_block_nonce - last_reward_nonce;
32-
33-
let extra_rewards_apr_bounded = extra_rewards_apr_bounded_per_block * block_nonce_diff;
34-
35-
extra_rewards = core::cmp::min(extra_rewards_unbounded, extra_rewards_apr_bounded);
36-
} else {
37-
extra_rewards = extra_rewards_unbounded;
38-
}
39-
40-
if extra_rewards > BigUint::zero() && extra_rewards <= storage_cache.rewards_reserve {
41-
let total_staked_amount = self
42-
.tx()
43-
.to(self.bond_contract_address().get())
44-
.typed(proxy_contracts::life_bonding_sc_proxy::LifeBondingContractProxy)
45-
.total_bond_amount()
46-
.returns(ReturnsResult)
47-
.sync_call();
48-
49-
let increment = &extra_rewards * DIVISION_SAFETY_CONST / &total_staked_amount;
50-
51-
storage_cache.rewards_per_share += &increment;
52-
storage_cache.accumulated_rewards += &extra_rewards;
53-
storage_cache.rewards_reserve -= &extra_rewards;
54-
}
55-
}
56-
57-
// not used (useful to enforce a max APR)
58-
fn get_amount_apr_bounded(&self, amount: &BigUint) -> BigUint {
59-
let max_apr = self.max_apr().get();
60-
amount * &max_apr / MAX_PERCENT / BLOCKS_IN_YEAR
61-
}
62-
63-
fn calculate_rewards_since_last_allocation(
64-
&self,
65-
storage_cache: &mut StorageCache<Self>,
66-
) -> BigUint {
67-
let current_block_nonce = self.blockchain().get_block_nonce();
68-
69-
if !self.can_produce_rewards() {
70-
return BigUint::zero();
71-
}
72-
73-
if current_block_nonce <= storage_cache.last_reward_block_nonce {
74-
return BigUint::zero();
75-
}
76-
77-
let block_nonce_diff = current_block_nonce - storage_cache.last_reward_block_nonce;
78-
79-
storage_cache.last_reward_block_nonce = current_block_nonce;
80-
81-
&storage_cache.rewards_per_block * block_nonce_diff
82-
}
83-
84-
fn calculate_caller_share_in_rewards(
85-
self,
86-
caller: &ManagedAddress,
87-
total_staked_amount: BigUint,
88-
user_stake_amount: BigUint,
89-
storage_cache: &mut StorageCache<Self>,
90-
) -> BigUint {
91-
if total_staked_amount > BigUint::zero()
92-
&& storage_cache.accumulated_rewards > BigUint::zero()
93-
{
94-
let user_last_rewards_per_share = self.address_last_reward_per_share(caller).get();
95-
96-
let user_rewards = user_stake_amount
97-
* (&storage_cache.rewards_per_share - &user_last_rewards_per_share)
98-
/ DIVISION_SAFETY_CONST;
99-
100-
self.address_last_reward_per_share(caller)
101-
.set(storage_cache.rewards_per_share.clone());
102-
103-
self.address_stack_rewards(caller)
104-
.update(|value| *value += &user_rewards);
105-
106-
user_rewards
107-
} else {
108-
BigUint::zero()
109-
}
110-
}
14+
#[endpoint(generateAggregatedRewards)]
15+
fn generate_rewards(&self) {
16+
let mut storage_cache = StorageCache::new(self);
17+
self.generate_aggregated_rewards(&mut storage_cache);
18+
}
19+
fn generate_aggregated_rewards(&self, storage_cache: &mut StorageCache<Self>) {
20+
if self.can_produce_rewards() {
21+
let last_reward_nonce = self.last_reward_block_nonce().get();
22+
let extra_rewards_unbounded =
23+
self.calculate_rewards_since_last_allocation(storage_cache);
24+
let max_apr = self.max_apr().get();
25+
26+
let extra_rewards: BigUint;
27+
let total_staked_amount = self
28+
.tx()
29+
.to(self.bond_contract_address().get())
30+
.typed(proxy_contracts::life_bonding_sc_proxy::LifeBondingContractProxy)
31+
.total_bond_amount()
32+
.returns(ReturnsResult)
33+
.sync_call();
34+
if max_apr > BigUint::zero() {
35+
let extra_rewards_apr_bounded_per_block =
36+
self.get_amount_apr_bounded(&total_staked_amount); // max APR based on the total staked amount
37+
38+
let current_block_nonce = self.blockchain().get_block_nonce();
39+
40+
let block_nonce_diff = current_block_nonce - last_reward_nonce;
41+
42+
let extra_rewards_apr_bounded =
43+
extra_rewards_apr_bounded_per_block * block_nonce_diff;
44+
45+
extra_rewards = core::cmp::min(extra_rewards_unbounded, extra_rewards_apr_bounded);
46+
} else {
47+
extra_rewards = extra_rewards_unbounded;
48+
}
49+
50+
if extra_rewards > BigUint::zero() && extra_rewards <= storage_cache.rewards_reserve {
51+
let increment = &extra_rewards * DIVISION_SAFETY_CONST / &total_staked_amount;
52+
53+
storage_cache.rewards_per_share += &increment;
54+
storage_cache.accumulated_rewards += &extra_rewards;
55+
storage_cache.rewards_reserve -= &extra_rewards;
56+
}
57+
}
58+
}
59+
60+
// not used (useful to enforce a max APR)
61+
fn get_amount_apr_bounded(&self, amount: &BigUint) -> BigUint {
62+
let max_apr = self.max_apr().get();
63+
amount * &max_apr / MAX_PERCENT / BLOCKS_IN_YEAR
64+
}
65+
66+
fn calculate_rewards_since_last_allocation(
67+
&self,
68+
storage_cache: &mut StorageCache<Self>,
69+
) -> BigUint {
70+
let current_block_nonce = self.blockchain().get_block_nonce();
71+
72+
if current_block_nonce <= storage_cache.last_reward_block_nonce {
73+
return BigUint::zero();
74+
}
75+
76+
let block_nonce_diff = current_block_nonce - storage_cache.last_reward_block_nonce;
77+
78+
storage_cache.last_reward_block_nonce = current_block_nonce;
79+
80+
&storage_cache.rewards_per_block * block_nonce_diff
81+
}
82+
83+
fn calculate_caller_share_in_rewards(
84+
self,
85+
caller: &ManagedAddress,
86+
total_staked_amount: BigUint,
87+
user_stake_amount: BigUint,
88+
storage_cache: &mut StorageCache<Self>,
89+
) -> BigUint {
90+
if total_staked_amount > BigUint::zero()
91+
&& storage_cache.accumulated_rewards > BigUint::zero()
92+
{
93+
let user_last_rewards_per_share = self.address_last_reward_per_share(caller).get();
94+
95+
let user_rewards = user_stake_amount
96+
* (&storage_cache.rewards_per_share - &user_last_rewards_per_share)
97+
/ DIVISION_SAFETY_CONST;
98+
99+
self.address_last_reward_per_share(caller)
100+
.set(storage_cache.rewards_per_share.clone());
101+
102+
self.address_stack_rewards(caller)
103+
.update(|value| *value += &user_rewards);
104+
105+
user_rewards
106+
} else {
107+
BigUint::zero()
108+
}
109+
}
111110
}

0 commit comments

Comments
 (0)