Skip to content

Commit 5fc7ed9

Browse files
test sanAdapter (#183)
* test sanAdapter * fix test rewards * fix all tests
1 parent ae1ce82 commit 5fc7ed9

9 files changed

Lines changed: 946 additions & 13 deletions

contracts/adapters/SanTokenERC4626Adapter.sol

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,12 @@ abstract contract SanTokenERC4626Adapter is Initializable, ERC20Upgradeable, IER
219219
(, , , , , uint256 sanRate, , SLPData memory slpData, ) = stableMaster().collateralMap(poolManager());
220220
if (block.timestamp != slpData.lastBlockUpdated && slpData.lockedInterests > 0) {
221221
uint256 sanMint = sanToken().totalSupply();
222-
if (slpData.lockedInterests > slpData.maxInterestsDistributed) {
223-
sanRate += (slpData.maxInterestsDistributed * _BASE) / sanMint;
224-
} else {
225-
sanRate += (slpData.lockedInterests * _BASE) / sanMint;
222+
if (sanMint != 0) {
223+
if (slpData.lockedInterests > slpData.maxInterestsDistributed) {
224+
sanRate += (slpData.maxInterestsDistributed * _BASE) / sanMint;
225+
} else {
226+
sanRate += (slpData.lockedInterests * _BASE) / sanMint;
227+
}
226228
}
227229
}
228230
return (sanRate, slpData.slippage);

contracts/adapters/SanTokenERC4626AdapterStakable.sol

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ abstract contract SanTokenERC4626AdapterStakable is SanTokenERC4626Adapter {
1717
/// @notice Angle-related constants
1818
IERC20 private constant _ANGLE = IERC20(0x31429d1856aD1377A8A0079410B297e1a9e214c2);
1919

20+
uint256 public constant BASE_36 = 10**36;
21+
2022
// ================================= REFERENCES ================================
2123

2224
/// @notice Maps each reward token to a track record of cumulated rewards
@@ -43,7 +45,7 @@ abstract contract SanTokenERC4626AdapterStakable is SanTokenERC4626Adapter {
4345
) internal override {
4446
// Not claiming only if it is a deposit
4547
bool _claim = !(_from == address(0));
46-
_claimRewards();
48+
_claimContractRewards();
4749
_checkpointRewardsUser(_from, _claim);
4850
_checkpointRewardsUser(_to, _claim);
4951
// If the user is withdrawing, we need to unstake from the gauge
@@ -58,7 +60,7 @@ abstract contract SanTokenERC4626AdapterStakable is SanTokenERC4626Adapter {
5860
/// @return rewardAmounts Amounts of each reward token claimed by the user
5961
//solhint-disable-next-line
6062
function claim_rewards(address from) external returns (uint256[] memory) {
61-
_claimRewards();
63+
_claimContractRewards();
6264
return _checkpointRewardsUser(from, true);
6365
}
6466

@@ -68,9 +70,9 @@ abstract contract SanTokenERC4626AdapterStakable is SanTokenERC4626Adapter {
6870
function claimableRewards(address from, IERC20 _rewardToken) external view returns (uint256) {
6971
uint256 _totalSupply = totalSupply();
7072
uint256 newIntegral = _totalSupply != 0
71-
? integral[_rewardToken] + (_rewardsToBeClaimed(_rewardToken) * _BASE_PARAMS) / _totalSupply
73+
? integral[_rewardToken] + (_rewardsToBeClaimed(_rewardToken) * BASE_36) / _totalSupply
7274
: integral[_rewardToken];
73-
uint256 newClaimable = (balanceOf(from) * (newIntegral - integralOf[_rewardToken][from])) / _BASE_PARAMS;
75+
uint256 newClaimable = (balanceOf(from) * (newIntegral - integralOf[_rewardToken][from])) / BASE_36;
7476
return pendingRewardsOf[_rewardToken][from] + newClaimable;
7577
}
7678

@@ -88,7 +90,7 @@ abstract contract SanTokenERC4626AdapterStakable is SanTokenERC4626Adapter {
8890
uint256 userBalance = balanceOf(from);
8991
for (uint256 i; i < rewardTokensLength; ++i) {
9092
uint256 totalClaimable = (userBalance * (integral[rewardTokens[i]] - integralOf[rewardTokens[i]][from])) /
91-
_BASE_PARAMS +
93+
BASE_36 +
9294
pendingRewardsOf[rewardTokens[i]][from];
9395
if (totalClaimable != 0) {
9496
if (_claim) {
@@ -104,7 +106,7 @@ abstract contract SanTokenERC4626AdapterStakable is SanTokenERC4626Adapter {
104106
}
105107

106108
/// @notice Claims all available rewards and increases the associated integral
107-
function _claimRewards() internal virtual {
109+
function _claimContractRewards() internal virtual {
108110
uint256 prevBalanceAngle = _ANGLE.balanceOf(address(this));
109111
gauge().claim_rewards(address(this), address(0));
110112
uint256 angleRewards = _ANGLE.balanceOf(address(this)) - prevBalanceAngle;
@@ -117,7 +119,7 @@ abstract contract SanTokenERC4626AdapterStakable is SanTokenERC4626Adapter {
117119
/// @param amount Amount to add to the claimable rewards
118120
function _updateRewards(IERC20 rewardToken, uint256 amount) internal {
119121
uint256 _totalSupply = totalSupply();
120-
if (_totalSupply != 0) integral[rewardToken] += (amount * _BASE_PARAMS) / _totalSupply;
122+
if (_totalSupply != 0) integral[rewardToken] += (amount * BASE_36) / _totalSupply;
121123
}
122124

123125
/// @notice Gets the reward tokens given in the liquidity gauge

contracts/interfaces/coreModule/ILiquidityGauge.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: GPL-3.0
22

3-
pragma solidity 0.8.12;
3+
pragma solidity ^0.8.12;
44

55
interface ILiquidityGauge {
66
function deposit(
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity 0.8.17;
3+
4+
import { ILiquidityGauge } from "../interfaces/coreModule/ILiquidityGauge.sol";
5+
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
6+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
7+
8+
contract MockLiquidityGauge is ILiquidityGauge, ERC20 {
9+
using SafeERC20 for IERC20;
10+
11+
IERC20 internal _ANGLE = IERC20(0x31429d1856aD1377A8A0079410B297e1a9e214c2);
12+
IERC20 internal _token;
13+
mapping(address => uint256) public rewards;
14+
15+
constructor(
16+
string memory name_,
17+
string memory symbol_,
18+
address token_
19+
) ERC20(name_, symbol_) {
20+
_token = IERC20(token_);
21+
}
22+
23+
function deposit(
24+
uint256 _value,
25+
address _addr,
26+
// solhint-disable-next-line
27+
bool
28+
) external {
29+
_token.safeTransferFrom(msg.sender, address(this), _value);
30+
_mint(_addr, _value);
31+
}
32+
33+
function withdraw(
34+
uint256 _value,
35+
// solhint-disable-next-line
36+
bool
37+
) external {
38+
_burn(msg.sender, _value);
39+
_token.safeTransfer(msg.sender, _value);
40+
}
41+
42+
// solhint-disable-next-line
43+
function claim_rewards(address _addr, address _receiver) external {
44+
if (_receiver == address(0)) _receiver = _addr;
45+
_ANGLE.safeTransfer(_receiver, rewards[_addr]);
46+
rewards[_addr] = 0;
47+
}
48+
49+
// solhint-disable-next-line
50+
function claimable_reward(address _addr, address) external view returns (uint256 amount) {
51+
return rewards[_addr];
52+
}
53+
54+
function setReward(address receiver_, uint256 amount) external {
55+
rewards[receiver_] = amount;
56+
}
57+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity 0.8.17;
3+
4+
import "../adapters/SanTokenERC4626Adapter.sol";
5+
import { SanTokenERC4626AdapterStakable } from "../adapters/SanTokenERC4626AdapterStakable.sol";
6+
7+
contract MockSanTokenERC4626Adapter is SanTokenERC4626Adapter {
8+
IStableMaster internal _stableMaster;
9+
address internal _poolManager;
10+
IERC20MetadataUpgradeable internal _sanToken;
11+
address internal _asset;
12+
13+
/// @notice Address of the `StableMaster` in the Core module of the protocol
14+
function stableMaster() public view override returns (IStableMaster) {
15+
return _stableMaster;
16+
}
17+
18+
/// @notice Address of the corresponding poolManager
19+
function poolManager() public view override returns (address) {
20+
return _poolManager;
21+
}
22+
23+
/// @notice Address of the associated sanToken
24+
function sanToken() public view override returns (IERC20MetadataUpgradeable) {
25+
return _sanToken;
26+
}
27+
28+
/// @inheritdoc IERC4626Upgradeable
29+
function asset() public view override returns (address) {
30+
return _asset;
31+
}
32+
33+
// ================================== SETTERS ==================================
34+
35+
/// @notice Address of the `StableMaster` in the Core module of the protocol
36+
function setStableMaster(address stableMaster_) public virtual {
37+
_stableMaster = IStableMaster(stableMaster_);
38+
}
39+
40+
/// @notice Address of the corresponding poolManager
41+
function setPoolManager(address poolManager_) public virtual {
42+
_poolManager = poolManager_;
43+
}
44+
45+
/// @notice Address of the associated sanToken
46+
function setSanToken(address sanToken_) public virtual {
47+
_sanToken = IERC20MetadataUpgradeable(sanToken_);
48+
}
49+
50+
function setAsset(address asset_) public virtual {
51+
_asset = asset_;
52+
}
53+
}
54+
55+
contract MockSanTokenERC4626AdapterStakable is SanTokenERC4626AdapterStakable {
56+
ILiquidityGauge internal _gauge;
57+
IStableMaster internal _stableMaster;
58+
address internal _poolManager;
59+
IERC20MetadataUpgradeable internal _sanToken;
60+
address internal _asset;
61+
62+
/// @notice Address of the `StableMaster` in the Core module of the protocol
63+
function stableMaster() public view override returns (IStableMaster) {
64+
return _stableMaster;
65+
}
66+
67+
/// @notice Address of the corresponding poolManager
68+
function poolManager() public view override returns (address) {
69+
return _poolManager;
70+
}
71+
72+
/// @notice Address of the associated sanToken
73+
function sanToken() public view override returns (IERC20MetadataUpgradeable) {
74+
return _sanToken;
75+
}
76+
77+
/// @inheritdoc IERC4626Upgradeable
78+
function asset() public view override returns (address) {
79+
return _asset;
80+
}
81+
82+
// ================================== SETTERS ==================================
83+
84+
/// @notice Address of the `StableMaster` in the Core module of the protocol
85+
function setStableMaster(address stableMaster_) public virtual {
86+
_stableMaster = IStableMaster(stableMaster_);
87+
}
88+
89+
/// @notice Address of the corresponding poolManager
90+
function setPoolManager(address poolManager_) public virtual {
91+
_poolManager = poolManager_;
92+
}
93+
94+
/// @notice Address of the associated sanToken
95+
function setSanToken(address sanToken_) public virtual {
96+
_sanToken = IERC20MetadataUpgradeable(sanToken_);
97+
}
98+
99+
function setAsset(address asset_) public virtual {
100+
_asset = asset_;
101+
}
102+
103+
/// @notice Address of the corresponding poolManager
104+
function gauge() public view override returns (ILiquidityGauge) {
105+
return _gauge;
106+
}
107+
108+
function setLiquidityGauge(address gauge_) public virtual {
109+
_gauge = ILiquidityGauge(gauge_);
110+
}
111+
}

0 commit comments

Comments
 (0)