Skip to content

Commit d7ab7d0

Browse files
Gas Optimization Bounty submission #2 (#453)
* Token Stake Optimizations (#420) * Update `Staker` and `StakingCondition` structs * Update `Staker` struct * Update `StakingCondition` struct * Other minor changes to allow for updates * Reorder/resize varaibles in Staking20Upgradeable. - uint256 stakingTokenDecimals => uint16 stakingTokenDecimals - uint256 rewardTokenDecimals => uint16 rewardTokenDecimals - Move `stakersArray` below the fixed size variables. * Make changes in Staking20 and Remove stakerArray * Remove stakersArray from Staking20.sol * Reorder variables in Staking20.sol for consistency * run solint/prettier * run yarn gas * Updating gas report to ensure accuracy. --------- Co-authored-by: nkrishang <62195808+nkrishang@users.noreply.github.com> * Re-add stakers array * target gas report * fix prettier / lint error --------- Co-authored-by: WhiteOakKong <92236155+WhiteOakKong@users.noreply.github.com>
1 parent 464d016 commit d7ab7d0

File tree

9 files changed

+99
-100
lines changed

9 files changed

+99
-100
lines changed

contracts/base/Staking20Base.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ contract Staking20Base is ContractMetadata, Multicall, Ownable, Staking20 {
5151
uint256 private rewardTokenBalance;
5252

5353
constructor(
54+
uint80 _timeUnit,
5455
address _defaultAdmin,
55-
uint256 _timeUnit,
5656
uint256 _rewardRatioNumerator,
5757
uint256 _rewardRatioDenominator,
5858
address _stakingToken,

contracts/extension/Staking20.sol

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,22 @@ abstract contract Staking20 is ReentrancyGuard, IStaking20 {
1919
address internal immutable nativeTokenWrapper;
2020

2121
///@dev Address of ERC20 contract -- staked tokens belong to this contract.
22-
address public stakingToken;
22+
address public immutable stakingToken;
2323

2424
/// @dev Decimals of staking token.
25-
uint256 public stakingTokenDecimals;
25+
uint16 public immutable stakingTokenDecimals;
2626

2727
/// @dev Decimals of reward token.
28-
uint256 public rewardTokenDecimals;
28+
uint16 public immutable rewardTokenDecimals;
2929

30-
/// @dev List of accounts that have staked that token-id.
31-
address[] public stakersArray;
30+
///@dev Next staking condition Id. Tracks number of conditon updates so far.
31+
uint64 private nextConditionId;
3232

3333
/// @dev Total amount of tokens staked in the contract.
3434
uint256 public stakingTokenBalance;
3535

36-
///@dev Next staking condition Id. Tracks number of conditon updates so far.
37-
uint256 private nextConditionId;
36+
/// @dev List of accounts that have staked that token-id.
37+
address[] public stakersArray;
3838

3939
///@dev Mapping staker address to Staker struct. See {struct IStaking20.Staker}.
4040
mapping(address => Staker) public stakers;
@@ -45,8 +45,8 @@ abstract contract Staking20 is ReentrancyGuard, IStaking20 {
4545
constructor(
4646
address _nativeTokenWrapper,
4747
address _stakingToken,
48-
uint256 _stakingTokenDecimals,
49-
uint256 _rewardTokenDecimals
48+
uint16 _stakingTokenDecimals,
49+
uint16 _rewardTokenDecimals
5050
) ReentrancyGuard() {
5151
require(_stakingToken != address(0) && _nativeTokenWrapper != address(0), "address 0");
5252
require(_stakingTokenDecimals != 0 && _rewardTokenDecimals != 0, "decimals 0");
@@ -101,7 +101,7 @@ abstract contract Staking20 is ReentrancyGuard, IStaking20 {
101101
*
102102
* @param _timeUnit New time unit.
103103
*/
104-
function setTimeUnit(uint256 _timeUnit) external virtual {
104+
function setTimeUnit(uint80 _timeUnit) external virtual {
105105
if (!_canSetStakeConditions()) {
106106
revert("Not authorized");
107107
}
@@ -186,7 +186,7 @@ abstract contract Staking20 is ReentrancyGuard, IStaking20 {
186186
_updateUnclaimedRewardsForStaker(_stakeMsgSender());
187187
} else {
188188
stakersArray.push(_stakeMsgSender());
189-
stakers[_stakeMsgSender()].timeOfLastUpdate = block.timestamp;
189+
stakers[_stakeMsgSender()].timeOfLastUpdate = uint80(block.timestamp);
190190
stakers[_stakeMsgSender()].conditionIdOflastUpdate = nextConditionId - 1;
191191
}
192192

@@ -244,7 +244,7 @@ abstract contract Staking20 is ReentrancyGuard, IStaking20 {
244244

245245
require(rewards != 0, "No rewards");
246246

247-
stakers[_stakeMsgSender()].timeOfLastUpdate = block.timestamp;
247+
stakers[_stakeMsgSender()].timeOfLastUpdate = uint80(block.timestamp);
248248
stakers[_stakeMsgSender()].unclaimedRewards = 0;
249249
stakers[_stakeMsgSender()].conditionIdOflastUpdate = nextConditionId - 1;
250250

@@ -266,13 +266,13 @@ abstract contract Staking20 is ReentrancyGuard, IStaking20 {
266266
function _updateUnclaimedRewardsForStaker(address _staker) internal virtual {
267267
uint256 rewards = _calculateRewards(_staker);
268268
stakers[_staker].unclaimedRewards += rewards;
269-
stakers[_staker].timeOfLastUpdate = block.timestamp;
269+
stakers[_staker].timeOfLastUpdate = uint80(block.timestamp);
270270
stakers[_staker].conditionIdOflastUpdate = nextConditionId - 1;
271271
}
272272

273273
/// @dev Set staking conditions.
274274
function _setStakingCondition(
275-
uint256 _timeUnit,
275+
uint80 _timeUnit,
276276
uint256 _numerator,
277277
uint256 _denominator
278278
) internal virtual {
@@ -285,12 +285,12 @@ abstract contract Staking20 is ReentrancyGuard, IStaking20 {
285285
timeUnit: _timeUnit,
286286
rewardRatioNumerator: _numerator,
287287
rewardRatioDenominator: _denominator,
288-
startTimestamp: block.timestamp,
288+
startTimestamp: uint80(block.timestamp),
289289
endTimestamp: 0
290290
});
291291

292292
if (conditionId > 0) {
293-
stakingConditions[conditionId - 1].endTimestamp = block.timestamp;
293+
stakingConditions[conditionId - 1].endTimestamp = uint80(block.timestamp);
294294
}
295295
}
296296

contracts/extension/Staking20Upgradeable.sol

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,19 @@ abstract contract Staking20Upgradeable is ReentrancyGuardUpgradeable, IStaking20
2222
address public stakingToken;
2323

2424
/// @dev Decimals of staking token.
25-
uint256 public stakingTokenDecimals;
25+
uint16 public stakingTokenDecimals;
2626

2727
/// @dev Decimals of reward token.
28-
uint256 public rewardTokenDecimals;
28+
uint16 public rewardTokenDecimals;
2929

30-
/// @dev List of accounts that have staked that token-id.
31-
address[] public stakersArray;
30+
///@dev Next staking condition Id. Tracks number of conditon updates so far.
31+
uint64 private nextConditionId;
3232

3333
/// @dev Total amount of tokens staked in the contract.
3434
uint256 public stakingTokenBalance;
3535

36-
///@dev Next staking condition Id. Tracks number of conditon updates so far.
37-
uint256 private nextConditionId;
36+
/// @dev List of accounts that have staked that token-id.
37+
address[] public stakersArray;
3838

3939
///@dev Mapping staker address to Staker struct. See {struct IStaking20.Staker}.
4040
mapping(address => Staker) public stakers;
@@ -50,8 +50,8 @@ abstract contract Staking20Upgradeable is ReentrancyGuardUpgradeable, IStaking20
5050

5151
function __Staking20_init(
5252
address _stakingToken,
53-
uint256 _stakingTokenDecimals,
54-
uint256 _rewardTokenDecimals
53+
uint16 _stakingTokenDecimals,
54+
uint16 _rewardTokenDecimals
5555
) internal onlyInitializing {
5656
__ReentrancyGuard_init();
5757

@@ -107,7 +107,7 @@ abstract contract Staking20Upgradeable is ReentrancyGuardUpgradeable, IStaking20
107107
*
108108
* @param _timeUnit New time unit.
109109
*/
110-
function setTimeUnit(uint256 _timeUnit) external virtual {
110+
function setTimeUnit(uint80 _timeUnit) external virtual {
111111
if (!_canSetStakeConditions()) {
112112
revert("Not authorized");
113113
}
@@ -163,7 +163,7 @@ abstract contract Staking20Upgradeable is ReentrancyGuardUpgradeable, IStaking20
163163
_rewards = _availableRewards(_staker);
164164
}
165165

166-
function getTimeUnit() public view returns (uint256 _timeUnit) {
166+
function getTimeUnit() public view returns (uint80 _timeUnit) {
167167
_timeUnit = stakingConditions[nextConditionId - 1].timeUnit;
168168
}
169169

@@ -192,7 +192,7 @@ abstract contract Staking20Upgradeable is ReentrancyGuardUpgradeable, IStaking20
192192
_updateUnclaimedRewardsForStaker(_stakeMsgSender());
193193
} else {
194194
stakersArray.push(_stakeMsgSender());
195-
stakers[_stakeMsgSender()].timeOfLastUpdate = block.timestamp;
195+
stakers[_stakeMsgSender()].timeOfLastUpdate = uint80(block.timestamp);
196196
stakers[_stakeMsgSender()].conditionIdOflastUpdate = nextConditionId - 1;
197197
}
198198

@@ -230,6 +230,7 @@ abstract contract Staking20Upgradeable is ReentrancyGuardUpgradeable, IStaking20
230230
}
231231
}
232232
}
233+
233234
stakers[_stakeMsgSender()].amountStaked -= _amount;
234235
stakingTokenBalance -= _amount;
235236

@@ -250,7 +251,7 @@ abstract contract Staking20Upgradeable is ReentrancyGuardUpgradeable, IStaking20
250251

251252
require(rewards != 0, "No rewards");
252253

253-
stakers[_stakeMsgSender()].timeOfLastUpdate = block.timestamp;
254+
stakers[_stakeMsgSender()].timeOfLastUpdate = uint80(block.timestamp);
254255
stakers[_stakeMsgSender()].unclaimedRewards = 0;
255256
stakers[_stakeMsgSender()].conditionIdOflastUpdate = nextConditionId - 1;
256257

@@ -272,13 +273,13 @@ abstract contract Staking20Upgradeable is ReentrancyGuardUpgradeable, IStaking20
272273
function _updateUnclaimedRewardsForStaker(address _staker) internal virtual {
273274
uint256 rewards = _calculateRewards(_staker);
274275
stakers[_staker].unclaimedRewards += rewards;
275-
stakers[_staker].timeOfLastUpdate = block.timestamp;
276+
stakers[_staker].timeOfLastUpdate = uint80(block.timestamp);
276277
stakers[_staker].conditionIdOflastUpdate = nextConditionId - 1;
277278
}
278279

279280
/// @dev Set staking conditions.
280281
function _setStakingCondition(
281-
uint256 _timeUnit,
282+
uint80 _timeUnit,
282283
uint256 _numerator,
283284
uint256 _denominator
284285
) internal virtual {
@@ -291,12 +292,12 @@ abstract contract Staking20Upgradeable is ReentrancyGuardUpgradeable, IStaking20
291292
timeUnit: _timeUnit,
292293
rewardRatioNumerator: _numerator,
293294
rewardRatioDenominator: _denominator,
294-
startTimestamp: block.timestamp,
295+
startTimestamp: uint80(block.timestamp),
295296
endTimestamp: 0
296297
});
297298

298299
if (conditionId > 0) {
299-
stakingConditions[conditionId - 1].endTimestamp = block.timestamp;
300+
stakingConditions[conditionId - 1].endTimestamp = uint80(block.timestamp);
300301
}
301302
}
302303

contracts/extension/interface/IStaking20.sol

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ interface IStaking20 {
3939
* @param conditionIdOflastUpdate Condition-Id when rewards were last updated for user.
4040
*/
4141
struct Staker {
42+
uint128 timeOfLastUpdate;
43+
uint64 conditionIdOflastUpdate;
4244
uint256 amountStaked;
43-
uint256 timeOfLastUpdate;
4445
uint256 unclaimedRewards;
45-
uint256 conditionIdOflastUpdate;
4646
}
4747

4848
/**
@@ -61,11 +61,11 @@ interface IStaking20 {
6161
* @param endTimestamp Condition end timestamp.
6262
*/
6363
struct StakingCondition {
64-
uint256 timeUnit;
64+
uint80 timeUnit;
65+
uint80 startTimestamp;
66+
uint80 endTimestamp;
6567
uint256 rewardRatioNumerator;
6668
uint256 rewardRatioDenominator;
67-
uint256 startTimestamp;
68-
uint256 endTimestamp;
6969
}
7070

7171
/**

contracts/staking/TokenStake.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ contract TokenStake is
5757
address[] memory _trustedForwarders,
5858
address _rewardToken,
5959
address _stakingToken,
60-
uint256 _timeUnit,
60+
uint80 _timeUnit,
6161
uint256 _rewardRatioNumerator,
6262
uint256 _rewardRatioDenominator
6363
) external initializer {
@@ -66,10 +66,10 @@ contract TokenStake is
6666
require(_rewardToken != _stakingToken, "Reward Token and Staking Token can't be same.");
6767
rewardToken = _rewardToken;
6868

69-
uint256 _stakingTokenDecimals = _stakingToken == CurrencyTransferLib.NATIVE_TOKEN
69+
uint16 _stakingTokenDecimals = _stakingToken == CurrencyTransferLib.NATIVE_TOKEN
7070
? 18
7171
: IERC20Metadata(_stakingToken).decimals();
72-
uint256 _rewardTokenDecimals = _rewardToken == CurrencyTransferLib.NATIVE_TOKEN
72+
uint16 _rewardTokenDecimals = _rewardToken == CurrencyTransferLib.NATIVE_TOKEN
7373
? 18
7474
: IERC20Metadata(_rewardToken).decimals();
7575

0 commit comments

Comments
 (0)