Skip to content

Commit

Permalink
Merge branch 'myso-oracle' of github.com:mysofinance/v2 into myso-oracle
Browse files Browse the repository at this point in the history
  • Loading branch information
jpick713 committed Apr 16, 2024
2 parents 79f5d11 + 10ba136 commit 8c3e15e
Show file tree
Hide file tree
Showing 7 changed files with 548 additions and 113 deletions.
41 changes: 41 additions & 0 deletions contracts/test/MockStMysoToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.19;

import {IERC20, ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20Wrapper} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Wrapper.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract MockStMysoToken is Ownable, ERC20Wrapper {
uint8 private _decimals;
mapping(address => uint256) public weight;
address public mysoToken;

constructor(
string memory _name,
string memory _symbol,
IERC20 _mysoToken
) ERC20(_name, _symbol) ERC20Wrapper(_mysoToken) Ownable() {
_decimals = ERC20(address(_mysoToken)).decimals();
}

function depositFor(
address account,
uint256 amount
) public override returns (bool) {
weight[account] = amount;
return super.depositFor(account, amount);
}

function withdrawTo(
address account,
uint256 amount
) public override returns (bool) {
weight[account] -= amount;
return super.withdrawTo(account, amount);
}

function decimals() public view override returns (uint8) {
return _decimals;
}
}
13 changes: 0 additions & 13 deletions contracts/tokenManager/DegenScoreDataTypes.sol

This file was deleted.

84 changes: 70 additions & 14 deletions contracts/tokenManager/MysoTokenManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,24 @@ pragma solidity 0.8.19;

import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {DataTypesPeerToPeer} from "../peer-to-peer/DataTypesPeerToPeer.sol";
import {DataTypesPeerToPool} from "../peer-to-pool/DataTypesPeerToPool.sol";
import {Errors} from "../Errors.sol";
import {Helpers} from "../Helpers.sol";
import {IMysoTokenManager} from "../interfaces/IMysoTokenManager.sol";
import {ILenderVaultImpl} from "../peer-to-peer/interfaces/ILenderVaultImpl.sol";
import {IStMysoToken} from "./interfaces/IStMysoToken.sol";

contract MysoTokenManager is Ownable2Step, IMysoTokenManager {
using SafeERC20 for IERC20;
using ECDSA for bytes32;

struct RewardInfo {
uint128 collThreshold;
// Multiplier in units of BASE
uint128 mysoTokenMultiplier;
}

Expand All @@ -25,9 +31,9 @@ contract MysoTokenManager is Ownable2Step, IMysoTokenManager {
address public mysoIOOVault;
address public mysoToken;
address public stMysoToken;
address public degenscoreBeaconReader;
address public accessSigner;
mapping(address => RewardInfo) public rewardInfos;

mapping(bytes32 => bool) public alreadyClaimed;
event RewardInfoSet(
address indexed collToken,
uint128 collThreshold,
Expand All @@ -37,50 +43,59 @@ contract MysoTokenManager is Ownable2Step, IMysoTokenManager {
event StMysoTokenSet(address stMysoToken);
event MinMysoWeightSet(uint256 minMysoWeight);
event IOOVaultSet(address mysoIOOVault);
event SignerSet(address signer);
event TotalMysoLoanAmountSet(uint256 totalMysoLoanAmount);

error NotAllowed();

constructor(
address _mysoIOOVault,
address _mysoToken,
address _stMysoToken,
uint256 _minMysoWeight
uint256 _minMysoWeight,
address _signer
) {
mysoIOOVault = _mysoIOOVault;
mysoToken = _mysoToken;
stMysoToken = _stMysoToken;
minMysoWeight = _minMysoWeight;
accessSigner = _signer;
_transferOwnership(msg.sender);
}

function processP2PBorrow(
uint128[2] memory currProtocolFeeParams,
DataTypesPeerToPeer.BorrowTransferInstructions
calldata /*borrowInstructions*/,
calldata borrowInstructions,
DataTypesPeerToPeer.Loan calldata loan,
address lenderVault
) external returns (uint128[2] memory applicableProtocolFeeParams) {
applicableProtocolFeeParams = currProtocolFeeParams;
address _mysoToken = mysoToken;
if (_mysoToken != address(0)) {
if (loan.loanToken == _mysoToken && lenderVault == mysoIOOVault) {
totalMysoLoanAmount += loan.initLoanAmount;
}
if (!_isAllowed(loan)) {
bool isMysoIoo = loan.loanToken == _mysoToken &&
lenderVault == mysoIOOVault;
if (!_isAllowed(isMysoIoo, borrowInstructions, loan)) {
revert NotAllowed();
}
if (isMysoIoo) {
totalMysoLoanAmount += loan.initLoanAmount;
}
address _stMysoToken = stMysoToken;
if (
_stMysoToken != address(0) &&
IStMysoToken(_stMysoToken).weight(loan.borrower) > minMysoWeight
IStMysoToken(_stMysoToken).weight(loan.borrower) >=
minMysoWeight
) {
RewardInfo memory rewardInfo = rewardInfos[loan.collToken];
uint256 rewardAmount = loan.initCollAmount *
rewardInfo.mysoTokenMultiplier;
// @dev: multiplier in BASE cancels out with MYT decimals
uint256 rewardAmount = (loan.initCollAmount *
rewardInfo.mysoTokenMultiplier) /
(10 ** IERC20Metadata(loan.collToken).decimals());
uint256 bal = IERC20(_mysoToken).balanceOf(address(this));
rewardAmount = rewardAmount > bal ? bal : rewardAmount;
if (
loan.initCollAmount > rewardInfo.collThreshold &&
loan.initCollAmount >= rewardInfo.collThreshold &&
rewardAmount > 0
) {
SafeERC20.safeTransfer(
Expand Down Expand Up @@ -196,6 +211,18 @@ contract MysoTokenManager is Ownable2Step, IMysoTokenManager {
emit IOOVaultSet(_mysoIOOVault);
}

function setSigner(address _signer) external {
_checkOwner();
accessSigner = _signer;
emit SignerSet(_signer);
}

function setTotalMysoLoanAmount(uint256 _totalMysoLoanAmount) external {
_checkOwner();
totalMysoLoanAmount = _totalMysoLoanAmount;
emit TotalMysoLoanAmountSet(_totalMysoLoanAmount);
}

function transferOwnership(address _newOwnerProposal) public override {
_checkOwner();
if (
Expand All @@ -210,8 +237,37 @@ contract MysoTokenManager is Ownable2Step, IMysoTokenManager {
}

function _isAllowed(
DataTypesPeerToPeer.Loan calldata /*loan*/
bool isMysoIoo,
DataTypesPeerToPeer.BorrowTransferInstructions
calldata borrowInstructions,
DataTypesPeerToPeer.Loan calldata loan
) internal virtual returns (bool) {
return true;
if (isMysoIoo) {
address _signer = accessSigner;
if (_signer == address(0)) {
return true;
} else {
(bytes memory compactSig, uint256 nonce) = abi.decode(
borrowInstructions.mysoTokenManagerData,
(bytes, uint256)
);
bytes32 payloadHash = keccak256(
abi.encode(loan.borrower, nonce)
);
if (alreadyClaimed[payloadHash]) {
return false;
}
(bytes32 r, bytes32 vs) = Helpers.splitSignature(compactSig);
bytes32 messageHash = ECDSA.toEthSignedMessageHash(payloadHash);
address recoveredSigner = messageHash.recover(r, vs);
if (recoveredSigner == _signer) {
alreadyClaimed[payloadHash] = true;
return true;
}
return false;
}
} else {
return true;
}
}
}
60 changes: 40 additions & 20 deletions contracts/tokenManager/MysoTokenManagerArbitrum.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,34 @@ contract MysoTokenManagerArbitrum is MysoTokenManager {
0xd3443ee1e91aF28e5FB858Fbd0D72A63bA8046E0;
address internal constant GETH = 0x5977A9682D7AF81D347CFc338c61692163a2784C;
mapping(address => uint256) public gVolume;
uint256 public gVolumeCap;
mapping(address => uint256) public gVolumeCaps;

event GVolumeSet(address gToken, uint256 gVolume);
event GVolumeCapSet(uint256 gVolumeCap);
event GVolumeCapSet(address gToken, uint256 gVolumeCap);

error NoGToken();

constructor(
address _mysoIOOVault,
address _mysoToken,
address _stMysoToken,
uint256 _minMysoWeight,
uint256 _gVolumeCap
address _signer,
uint256 _gDaiCap,
uint256 _gUsdcCap,
uint256 _gEthCap
)
MysoTokenManager(
_mysoIOOVault,
_mysoToken,
_stMysoToken,
_minMysoWeight
_minMysoWeight,
_signer
)
{
gVolumeCap = _gVolumeCap;
gVolumeCaps[GDAI] = _gDaiCap;
gVolumeCaps[GUSDC] = _gUsdcCap;
gVolumeCaps[GETH] = _gEthCap;
}

function setGVolume(address _gToken, uint256 _gVolume) external {
Expand All @@ -39,27 +47,39 @@ contract MysoTokenManagerArbitrum is MysoTokenManager {
emit GVolumeSet(_gToken, _gVolume);
}

function setGVolumeCap(uint256 _gVolumeCap) external {
function setGVolumeCap(address gToken, uint256 _gVolumeCap) external {
_checkOwner();
gVolumeCap = _gVolumeCap;
emit GVolumeCapSet(_gVolumeCap);
if (gToken != GDAI && gToken != GDAI && gToken != GDAI) {
revert NoGToken();
}
gVolumeCaps[gToken] = _gVolumeCap;
emit GVolumeCapSet(gToken, _gVolumeCap);
}

function _isAllowed(
bool isMysoIoo,
DataTypesPeerToPeer.BorrowTransferInstructions
calldata borrowInstructions,
DataTypesPeerToPeer.Loan calldata loan
) internal override returns (bool isAllowed) {
if (
loan.collToken == GDAI ||
loan.collToken == GUSDC ||
loan.collToken == GETH
) {
uint256 _gVolume = gVolume[loan.collToken];
_gVolume +=
(loan.collToken == GETH ? 3500 : 1) *
loan.initCollAmount;
isAllowed = _gVolume <= gVolumeCap;
if (isAllowed) {
gVolume[loan.collToken] = _gVolume;
isAllowed = super._isAllowed(isMysoIoo, borrowInstructions, loan);
if (!isAllowed) {
return isAllowed;
}
if (isMysoIoo) {
if (
loan.collToken == GDAI ||
loan.collToken == GUSDC ||
loan.collToken == GETH
) {
uint256 _newGVolume = gVolume[loan.collToken] +
loan.initCollAmount;
isAllowed = _newGVolume <= gVolumeCaps[loan.collToken];
if (isAllowed) {
gVolume[loan.collToken] = _newGVolume;
}
} else {
isAllowed = true;
}
} else {
isAllowed = true;
Expand Down
50 changes: 0 additions & 50 deletions contracts/tokenManager/MysoTokenManagerMainnet.sol

This file was deleted.

16 changes: 0 additions & 16 deletions contracts/tokenManager/interfaces/IDegenScoreBeaconReader.sol

This file was deleted.

Loading

0 comments on commit 8c3e15e

Please sign in to comment.