Source Code
Overview
XDAI Balance
XDAI Value
$0.00View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Loading...
Loading
Contract Name:
LendingStorageManager
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.9;
import {ISynthereumFinder} from '../core/interfaces/IFinder.sol';
import {ISynthereumFactoryVersioning} from '../core/interfaces/IFactoryVersioning.sol';
import {ILendingStorageManager} from './interfaces/ILendingStorageManager.sol';
import {ILendingModule} from './interfaces/ILendingModule.sol';
import {SynthereumInterfaces, FactoryInterfaces} from '../core/Constants.sol';
import {PreciseUnitMath} from '../base/utils/PreciseUnitMath.sol';
import {SynthereumFactoryAccess} from '../common/libs/FactoryAccess.sol';
import {EnumerableSet} from '../../@openzeppelin/contracts/utils/structs/EnumerableSet.sol';
import {ReentrancyGuard} from '../../@openzeppelin/contracts/security/ReentrancyGuard.sol';
contract LendingStorageManager is ILendingStorageManager, ReentrancyGuard {
using EnumerableSet for EnumerableSet.AddressSet;
mapping(bytes32 => LendingInfo) internal idToLendingInfo;
EnumerableSet.AddressSet internal swapModules;
mapping(address => address) internal collateralToSwapModule; // ie USDC -> JRTSwapUniswap address
mapping(address => PoolStorage) internal poolStorage; // ie jEUR/USDC pooldata
ISynthereumFinder immutable synthereumFinder;
modifier onlyLendingManager() {
require(
msg.sender ==
synthereumFinder.getImplementationAddress(
SynthereumInterfaces.LendingManager
),
'Not allowed'
);
_;
}
modifier onlyPoolFactory() {
SynthereumFactoryAccess._onlyPoolFactory(synthereumFinder);
_;
}
constructor(ISynthereumFinder _finder) {
synthereumFinder = _finder;
}
function setLendingModule(
string calldata _id,
LendingInfo calldata _lendingInfo
) external override nonReentrant onlyLendingManager {
bytes32 lendingId = keccak256(abi.encode(_id));
require(lendingId != 0x00, 'Wrong module identifier');
idToLendingInfo[lendingId] = _lendingInfo;
}
function addSwapProtocol(address _swapModule)
external
override
nonReentrant
onlyLendingManager
{
require(_swapModule != address(0), 'Swap module can not be 0x');
require(swapModules.add(_swapModule), 'Swap module already supported');
}
function removeSwapProtocol(address _swapModule)
external
override
nonReentrant
onlyLendingManager
{
require(_swapModule != address(0), 'Swap module can not be 0x');
require(swapModules.remove(_swapModule), 'Swap module not supported');
}
function setSwapModule(address _collateral, address _swapModule)
external
override
nonReentrant
onlyLendingManager
{
require(
swapModules.contains(_swapModule) || _swapModule == address(0),
'Swap module not supported'
);
collateralToSwapModule[_collateral] = _swapModule;
}
function setShares(
address _pool,
uint64 _daoInterestShare,
uint64 _jrtBuybackShare
) external override nonReentrant onlyLendingManager {
PoolStorage storage poolData = poolStorage[_pool];
require(poolData.lendingModuleId != 0x00, 'Bad pool');
require(
_jrtBuybackShare <= PreciseUnitMath.PRECISE_UNIT &&
_daoInterestShare <= PreciseUnitMath.PRECISE_UNIT,
'Invalid share'
);
poolData.jrtBuybackShare = _jrtBuybackShare;
poolData.daoInterestShare = _daoInterestShare;
}
function setPoolStorage(
string calldata _lendingID,
address _pool,
address _collateral,
address _interestBearingToken,
uint64 _daoInterestShare,
uint64 _jrtBuybackShare
) external override nonReentrant onlyPoolFactory {
bytes32 id = keccak256(abi.encode(_lendingID));
LendingInfo memory lendingInfo = idToLendingInfo[id];
address lendingModule = lendingInfo.lendingModule;
require(lendingModule != address(0), 'Module not supported');
require(
_jrtBuybackShare <= PreciseUnitMath.PRECISE_UNIT &&
_daoInterestShare <= PreciseUnitMath.PRECISE_UNIT,
'Invalid share'
);
// set pool storage
PoolStorage storage poolData = poolStorage[_pool];
require(poolData.lendingModuleId == 0x00, 'Pool already exists');
poolData.lendingModuleId = id;
poolData.collateral = _collateral;
poolData.jrtBuybackShare = _jrtBuybackShare;
poolData.daoInterestShare = _daoInterestShare;
// set interest bearing token
_setBearingToken(
poolData,
_collateral,
lendingModule,
lendingInfo,
_interestBearingToken
);
}
function migratePoolStorage(
address _oldPool,
address _newPool,
uint256 _newCollateralDeposited
) external override nonReentrant onlyLendingManager {
PoolStorage memory oldPoolData = poolStorage[_oldPool];
bytes32 oldLendingId = oldPoolData.lendingModuleId;
require(oldLendingId != 0x00, 'Bad migration pool');
PoolStorage storage newPoolData = poolStorage[_newPool];
require(newPoolData.lendingModuleId == 0x00, 'Bad new pool');
// copy storage to new pool
newPoolData.lendingModuleId = oldLendingId;
newPoolData.collateral = oldPoolData.collateral;
newPoolData.interestBearingToken = oldPoolData.interestBearingToken;
newPoolData.jrtBuybackShare = oldPoolData.jrtBuybackShare;
newPoolData.daoInterestShare = oldPoolData.daoInterestShare;
newPoolData.collateralDeposited = _newCollateralDeposited;
newPoolData.unclaimedDaoJRT = oldPoolData.unclaimedDaoJRT;
newPoolData.unclaimedDaoCommission = oldPoolData.unclaimedDaoCommission;
// delete old pool slot
delete poolStorage[_oldPool];
}
function migrateLendingModule(
string calldata _newLendingID,
address _pool,
address _newInterestBearingToken
)
external
override
nonReentrant
onlyLendingManager
returns (PoolStorage memory, LendingInfo memory)
{
bytes32 id = keccak256(abi.encode(_newLendingID));
LendingInfo memory newLendingInfo = idToLendingInfo[id];
address newLendingModule = newLendingInfo.lendingModule;
require(newLendingModule != address(0), 'Id not existent');
// set lending module
PoolStorage storage poolData = poolStorage[_pool];
poolData.lendingModuleId = id;
// set interest bearing token
_setBearingToken(
poolData,
poolData.collateral,
newLendingModule,
newLendingInfo,
_newInterestBearingToken
);
return (poolData, newLendingInfo);
}
function updateValues(
address _pool,
uint256 _collateralDeposited,
uint256 _daoJRT,
uint256 _daoInterest
) external override nonReentrant onlyLendingManager {
PoolStorage storage poolData = poolStorage[_pool];
require(poolData.lendingModuleId != 0x00, 'Bad pool');
// update collateral deposit amount of the pool
poolData.collateralDeposited = _collateralDeposited;
// update dao unclaimed interest of the pool
poolData.unclaimedDaoJRT = _daoJRT;
poolData.unclaimedDaoCommission = _daoInterest;
}
function getLendingModule(string calldata _id)
external
view
override
returns (LendingInfo memory lendingInfo)
{
bytes32 lendingId = keccak256(abi.encode(_id));
require(lendingId != 0x00, 'Wrong module identifier');
lendingInfo = idToLendingInfo[lendingId];
require(
lendingInfo.lendingModule != address(0),
'Lending module not supported'
);
}
function getPoolData(address _pool)
external
view
override
returns (PoolStorage memory poolData, LendingInfo memory lendingInfo)
{
poolData = poolStorage[_pool];
require(poolData.lendingModuleId != 0x00, 'Not existing pool');
lendingInfo = idToLendingInfo[poolData.lendingModuleId];
}
function getPoolStorage(address _pool)
external
view
override
returns (PoolStorage memory poolData)
{
poolData = poolStorage[_pool];
require(poolData.lendingModuleId != 0x00, 'Not existing pool');
}
function getLendingData(address _pool)
external
view
override
returns (
PoolLendingStorage memory lendingStorage,
LendingInfo memory lendingInfo
)
{
PoolStorage storage poolData = poolStorage[_pool];
require(poolData.lendingModuleId != 0x00, 'Not existing pool');
lendingStorage.collateralToken = poolData.collateral;
lendingStorage.interestToken = poolData.interestBearingToken;
lendingInfo = idToLendingInfo[poolData.lendingModuleId];
}
function getSwapModules() external view override returns (address[] memory) {
uint256 numberOfModules = swapModules.length();
address[] memory modulesList = new address[](numberOfModules);
for (uint256 j = 0; j < numberOfModules; j++) {
modulesList[j] = swapModules.at(j);
}
return modulesList;
}
function getCollateralSwapModule(address _collateral)
external
view
override
returns (address swapModule)
{
swapModule = collateralToSwapModule[_collateral];
require(
swapModule != address(0),
'Swap module not added for this collateral'
);
require(swapModules.contains(swapModule), 'Swap module not supported');
}
function getInterestBearingToken(address _pool)
external
view
override
returns (address interestTokenAddr)
{
require(poolStorage[_pool].lendingModuleId != 0x00, 'Not existing pool');
interestTokenAddr = poolStorage[_pool].interestBearingToken;
}
function getShares(address _pool)
external
view
override
returns (uint256 jrtBuybackShare, uint256 daoInterestShare)
{
require(poolStorage[_pool].lendingModuleId != 0x00, 'Not existing pool');
jrtBuybackShare = poolStorage[_pool].jrtBuybackShare;
daoInterestShare = poolStorage[_pool].daoInterestShare;
}
function getCollateralDeposited(address _pool)
external
view
override
returns (uint256 collateralAmount)
{
require(poolStorage[_pool].lendingModuleId != 0x00, 'Not existing pool');
collateralAmount = poolStorage[_pool].collateralDeposited;
}
function _setBearingToken(
PoolStorage storage _actualPoolData,
address _collateral,
address _lendingModule,
LendingInfo memory _lendingInfo,
address _interestToken
) internal {
try
ILendingModule(_lendingModule).getInterestBearingToken(
_collateral,
_lendingInfo.args
)
returns (address interestTokenAddr) {
_actualPoolData.interestBearingToken = interestTokenAddr;
} catch {
require(_interestToken != address(0), 'No bearing token passed');
_actualPoolData.interestBearingToken = _interestToken;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role, _msgSender());
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _grantRole(bytes32 role, address account) private {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) private {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IAccessControlEnumerable.sol";
import "./AccessControl.sol";
import "../utils/structs/EnumerableSet.sol";
/**
* @dev Extension of {AccessControl} that allows enumerating the members of each role.
*/
abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {
using EnumerableSet for EnumerableSet.AddressSet;
mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/
function getRoleMember(bytes32 role, uint256 index) public view override returns (address) {
return _roleMembers[role].at(index);
}
/**
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/
function getRoleMemberCount(bytes32 role) public view override returns (uint256) {
return _roleMembers[role].length();
}
/**
* @dev Overload {grantRole} to track enumerable memberships
*/
function grantRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {
super.grantRole(role, account);
_roleMembers[role].add(account);
}
/**
* @dev Overload {revokeRole} to track enumerable memberships
*/
function revokeRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {
super.revokeRole(role, account);
_roleMembers[role].remove(account);
}
/**
* @dev Overload {renounceRole} to track enumerable memberships
*/
function renounceRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {
super.renounceRole(role, account);
_roleMembers[role].remove(account);
}
/**
* @dev Overload {_setupRole} to track enumerable memberships
*/
function _setupRole(bytes32 role, address account) internal virtual override {
super._setupRole(role, account);
_roleMembers[role].add(account);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
/**
* @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
*/
interface IAccessControlEnumerable is IAccessControl {
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
/**
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/
function getRoleMemberCount(bytes32 role) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
return _values(set._inner);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.9;
import {ILendingManager} from './interfaces/ILendingManager.sol';
import {ILendingModule} from './interfaces/ILendingModule.sol';
import {ILendingStorageManager} from './interfaces/ILendingStorageManager.sol';
import {ISynthereumFinder} from '../core/interfaces/IFinder.sol';
import {SynthereumInterfaces} from '../core/Constants.sol';
import {ISynthereumLendingTransfer} from '../synthereum-pool/common/interfaces/ILendingTransfer.sol';
import {ISynthereumLendingRewards} from '../synthereum-pool/common/interfaces/ILendingRewards.sol';
import {PreciseUnitMath} from '../base/utils/PreciseUnitMath.sol';
import {Address} from '../../@openzeppelin/contracts/utils/Address.sol';
import {IERC20} from '../../@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from '../../@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import {SynthereumFactoryAccess} from '../common/libs/FactoryAccess.sol';
import {AccessControlEnumerable} from '../../@openzeppelin/contracts/access/AccessControlEnumerable.sol';
import {ReentrancyGuard} from '../../@openzeppelin/contracts/security/ReentrancyGuard.sol';
contract LendingManager is
ILendingManager,
ReentrancyGuard,
AccessControlEnumerable
{
using Address for address;
using SafeERC20 for IERC20;
using PreciseUnitMath for uint256;
ISynthereumFinder immutable synthereumFinder;
bytes32 public constant MAINTAINER_ROLE = keccak256('Maintainer');
string private constant DEPOSIT_SIG =
'deposit((bytes32,uint256,uint256,uint256,address,uint64,address,uint64),bytes,uint256)';
string private constant WITHDRAW_SIG =
'withdraw((bytes32,uint256,uint256,uint256,address,uint64,address,uint64),address,bytes,uint256,address)';
string private JRTSWAP_SIG =
'swapToJRT(address,address,address,uint256,bytes)';
string private TOTAL_TRANSFER_SIG =
'totalTransfer(address,address,address,address,bytes)';
modifier onlyMaintainer() {
require(
hasRole(MAINTAINER_ROLE, msg.sender),
'Sender must be the maintainer'
);
_;
}
modifier onlyPoolFactory() {
SynthereumFactoryAccess._onlyPoolFactory(synthereumFinder);
_;
}
constructor(ISynthereumFinder _finder, Roles memory _roles) nonReentrant {
synthereumFinder = _finder;
_setRoleAdmin(DEFAULT_ADMIN_ROLE, DEFAULT_ADMIN_ROLE);
_setRoleAdmin(MAINTAINER_ROLE, DEFAULT_ADMIN_ROLE);
_setupRole(DEFAULT_ADMIN_ROLE, _roles.admin);
_setupRole(MAINTAINER_ROLE, _roles.maintainer);
}
function deposit(uint256 _amount)
external
override
nonReentrant
returns (ReturnValues memory returnValues)
{
(
ILendingStorageManager.PoolStorage memory poolData,
ILendingStorageManager.LendingInfo memory lendingInfo,
ILendingStorageManager poolStorageManager
) = _getPoolInfo();
// delegate call implementation
bytes memory result = address(lendingInfo.lendingModule)
.functionDelegateCall(
abi.encodeWithSignature(DEPOSIT_SIG, poolData, lendingInfo.args, _amount)
);
ILendingModule.ReturnValues memory res = abi.decode(
result,
(ILendingModule.ReturnValues)
);
// split interest
InterestSplit memory interestSplit = splitGeneratedInterest(
res.totalInterest,
poolData.daoInterestShare,
poolData.jrtBuybackShare
);
// update pool storage values
poolStorageManager.updateValues(
msg.sender,
poolData.collateralDeposited + res.tokensOut + interestSplit.poolInterest,
poolData.unclaimedDaoJRT + interestSplit.jrtInterest,
poolData.unclaimedDaoCommission + interestSplit.commissionInterest
);
// set return values
returnValues.tokensOut = res.tokensOut;
returnValues.tokensTransferred = res.tokensTransferred;
returnValues.poolInterest = interestSplit.poolInterest;
returnValues.daoInterest =
interestSplit.commissionInterest +
interestSplit.jrtInterest;
returnValues.prevTotalCollateral = poolData.collateralDeposited;
}
function withdraw(uint256 _interestTokenAmount, address _recipient)
external
override
nonReentrant
returns (ReturnValues memory returnValues)
{
(
ILendingStorageManager.PoolStorage memory poolData,
ILendingStorageManager.LendingInfo memory lendingInfo,
ILendingStorageManager poolStorageManager
) = _getPoolInfo();
// delegate call implementation
bytes memory result = address(lendingInfo.lendingModule)
.functionDelegateCall(
abi.encodeWithSignature(
WITHDRAW_SIG,
poolData,
msg.sender,
lendingInfo.args,
_interestTokenAmount,
_recipient
)
);
ILendingModule.ReturnValues memory res = abi.decode(
result,
(ILendingModule.ReturnValues)
);
// split interest
InterestSplit memory interestSplit = splitGeneratedInterest(
res.totalInterest,
poolData.daoInterestShare,
poolData.jrtBuybackShare
);
// update storage value
poolStorageManager.updateValues(
msg.sender,
poolData.collateralDeposited + interestSplit.poolInterest - res.tokensOut,
poolData.unclaimedDaoJRT + interestSplit.jrtInterest,
poolData.unclaimedDaoCommission + interestSplit.commissionInterest
);
// set return values
returnValues.tokensOut = res.tokensOut;
returnValues.tokensTransferred = res.tokensTransferred;
returnValues.poolInterest = interestSplit.poolInterest;
returnValues.daoInterest =
interestSplit.commissionInterest +
interestSplit.jrtInterest;
returnValues.prevTotalCollateral = poolData.collateralDeposited;
}
function updateAccumulatedInterest()
external
override
nonReentrant
returns (ReturnValues memory returnValues)
{
(
ILendingStorageManager.PoolStorage memory poolData,
ILendingStorageManager.LendingInfo memory lendingInfo,
ILendingStorageManager poolStorageManager
) = _getPoolInfo();
// retrieve accumulated interest
uint256 totalInterest = ILendingModule(lendingInfo.lendingModule)
.getUpdatedInterest(msg.sender, poolData, lendingInfo.args);
// split according to shares
InterestSplit memory interestSplit = splitGeneratedInterest(
totalInterest,
poolData.daoInterestShare,
poolData.jrtBuybackShare
);
//update pool storage
poolStorageManager.updateValues(
msg.sender,
poolData.collateralDeposited + interestSplit.poolInterest,
poolData.unclaimedDaoJRT + interestSplit.jrtInterest,
poolData.unclaimedDaoCommission + interestSplit.commissionInterest
);
// return values
returnValues.poolInterest = interestSplit.poolInterest;
returnValues.daoInterest =
interestSplit.jrtInterest +
interestSplit.commissionInterest;
returnValues.prevTotalCollateral = poolData.collateralDeposited;
}
function batchClaimCommission(
address[] calldata _pools,
uint256[] calldata _amounts
) external override onlyMaintainer nonReentrant {
require(_pools.length == _amounts.length, 'Invalid call');
address recipient = synthereumFinder.getImplementationAddress(
SynthereumInterfaces.CommissionReceiver
);
uint256 totalAmount;
for (uint8 i = 0; i < _pools.length; i++) {
if (_amounts[i] > 0) {
claimCommission(_pools[i], _amounts[i], recipient);
totalAmount += _amounts[i];
}
}
emit BatchCommissionClaim(totalAmount, recipient);
}
function batchBuyback(
address[] calldata _pools,
uint256[] calldata _amounts,
address _collateralAddress,
bytes calldata _swapParams
) external override onlyMaintainer nonReentrant {
require(_pools.length == _amounts.length, 'Invalid call');
ILendingStorageManager poolStorageManager = getStorageManager();
// withdraw collateral and update all pools
uint256 aggregatedCollateral;
address recipient = synthereumFinder.getImplementationAddress(
SynthereumInterfaces.BuybackProgramReceiver
);
for (uint8 i = 0; i < _pools.length; i++) {
address pool = _pools[i];
uint256 _collateralAmount = _amounts[i];
(
ILendingStorageManager.PoolStorage memory poolData,
ILendingStorageManager.LendingInfo memory lendingInfo
) = poolStorageManager.getPoolData(pool);
// all pools need to have the same collateral
require(poolData.collateral == _collateralAddress, 'Collateral mismatch');
(uint256 interestTokenAmount, ) = collateralToInterestToken(
pool,
_collateralAmount
);
// trigger transfer of interest token from the pool
interestTokenAmount = ISynthereumLendingTransfer(pool)
.transferToLendingManager(interestTokenAmount);
bytes memory withdrawRes = address(lendingInfo.lendingModule)
.functionDelegateCall(
abi.encodeWithSignature(
WITHDRAW_SIG,
poolData,
pool,
lendingInfo.args,
interestTokenAmount,
address(this)
)
);
ILendingModule.ReturnValues memory res = abi.decode(
withdrawRes,
(ILendingModule.ReturnValues)
);
// update aggregated collateral to use for buyback
aggregatedCollateral += res.tokensTransferred;
// split interest
InterestSplit memory interestSplit = splitGeneratedInterest(
res.totalInterest,
poolData.daoInterestShare,
poolData.jrtBuybackShare
);
//update pool storage
poolStorageManager.updateValues(
pool,
poolData.collateralDeposited + interestSplit.poolInterest,
poolData.unclaimedDaoJRT + interestSplit.jrtInterest - res.tokensOut,
poolData.unclaimedDaoCommission + interestSplit.commissionInterest
);
}
// execute the buyback call with all the withdrawn collateral
address JARVIS = synthereumFinder.getImplementationAddress(
SynthereumInterfaces.JarvisToken
);
bytes memory result = address(
poolStorageManager.getCollateralSwapModule(_collateralAddress)
).functionDelegateCall(
abi.encodeWithSignature(
JRTSWAP_SIG,
recipient,
_collateralAddress,
JARVIS,
aggregatedCollateral,
_swapParams
)
);
emit BatchBuyback(
aggregatedCollateral,
abi.decode(result, (uint256)),
recipient
);
}
function setLendingModule(
string calldata _id,
ILendingStorageManager.LendingInfo calldata _lendingInfo
) external override onlyMaintainer nonReentrant {
ILendingStorageManager poolStorageManager = getStorageManager();
poolStorageManager.setLendingModule(_id, _lendingInfo);
}
function addSwapProtocol(address _swapModule)
external
override
onlyMaintainer
nonReentrant
{
ILendingStorageManager poolStorageManager = getStorageManager();
poolStorageManager.addSwapProtocol(_swapModule);
}
function removeSwapProtocol(address _swapModule)
external
override
onlyMaintainer
nonReentrant
{
ILendingStorageManager poolStorageManager = getStorageManager();
poolStorageManager.removeSwapProtocol(_swapModule);
}
function setSwapModule(address _collateral, address _swapModule)
external
override
onlyMaintainer
nonReentrant
{
ILendingStorageManager poolStorageManager = getStorageManager();
poolStorageManager.setSwapModule(_collateral, _swapModule);
}
function setShares(
address _pool,
uint64 _daoInterestShare,
uint64 _jrtBuybackShare
) external override onlyMaintainer nonReentrant {
ILendingStorageManager poolStorageManager = getStorageManager();
poolStorageManager.setShares(_pool, _daoInterestShare, _jrtBuybackShare);
}
// to migrate liquidity to another lending module
function migrateLendingModule(
string memory _newLendingID,
address _newInterestBearingToken,
uint256 _interestTokenAmount
) external override nonReentrant returns (MigrateReturnValues memory) {
(
ILendingStorageManager.PoolStorage memory poolData,
ILendingStorageManager.LendingInfo memory lendingInfo,
ILendingStorageManager poolStorageManager
) = _getPoolInfo();
uint256 prevDepositedCollateral = poolData.collateralDeposited;
// delegate call withdraw collateral from old module
ILendingModule.ReturnValues memory res;
{
bytes memory withdrawRes = address(lendingInfo.lendingModule)
.functionDelegateCall(
abi.encodeWithSignature(
WITHDRAW_SIG,
poolData,
msg.sender,
lendingInfo.args,
_interestTokenAmount,
address(this)
)
);
res = abi.decode(withdrawRes, (ILendingModule.ReturnValues));
}
// split interest
InterestSplit memory interestSplit = splitGeneratedInterest(
res.totalInterest,
poolData.daoInterestShare,
poolData.jrtBuybackShare
);
// add interest to pool data
uint256 newDaoJRT = poolData.unclaimedDaoJRT + interestSplit.jrtInterest;
uint256 newDaoCommission = poolData.unclaimedDaoCommission +
interestSplit.commissionInterest;
// temporary set pool data collateral and interest to 0 to freshly deposit
poolStorageManager.updateValues(msg.sender, 0, 0, 0);
// set new lending module and obtain new pool data
ILendingStorageManager.LendingInfo memory newLendingInfo;
(poolData, newLendingInfo) = poolStorageManager.migrateLendingModule(
_newLendingID,
msg.sender,
_newInterestBearingToken
);
// delegate call deposit into new module
bytes memory result = address(newLendingInfo.lendingModule)
.functionDelegateCall(
abi.encodeWithSignature(
DEPOSIT_SIG,
poolData,
newLendingInfo.args,
res.tokensTransferred,
msg.sender
)
);
ILendingModule.ReturnValues memory depositRes = abi.decode(
result,
(ILendingModule.ReturnValues)
);
// update storage with accumulated interest
uint256 actualCollateralDeposited = depositRes.tokensOut -
newDaoJRT -
newDaoCommission;
poolStorageManager.updateValues(
msg.sender,
actualCollateralDeposited,
newDaoJRT,
newDaoCommission
);
return (
MigrateReturnValues(
prevDepositedCollateral,
interestSplit.poolInterest,
actualCollateralDeposited
)
);
}
function migratePool(address _migrationPool, address _newPool)
external
override
onlyPoolFactory
nonReentrant
returns (uint256 sourceCollateralAmount, uint256 actualCollateralAmount)
{
ILendingStorageManager poolStorageManager = getStorageManager();
(
ILendingStorageManager.PoolLendingStorage memory lendingStorage,
ILendingStorageManager.LendingInfo memory lendingInfo
) = poolStorageManager.getLendingData(_migrationPool);
// delegate call deposit into new module
bytes memory result = address(lendingInfo.lendingModule)
.functionDelegateCall(
abi.encodeWithSignature(
TOTAL_TRANSFER_SIG,
_migrationPool,
_newPool,
lendingStorage.collateralToken,
lendingStorage.interestToken,
lendingInfo.args
)
);
(uint256 prevTotalAmount, uint256 newTotalAmount) = abi.decode(
result,
(uint256, uint256)
);
sourceCollateralAmount = poolStorageManager.getCollateralDeposited(
_migrationPool
);
actualCollateralAmount =
sourceCollateralAmount +
newTotalAmount -
prevTotalAmount;
poolStorageManager.migratePoolStorage(
_migrationPool,
_newPool,
actualCollateralAmount
);
}
function claimLendingRewards(address[] calldata _pools)
external
override
onlyMaintainer
nonReentrant
{
ILendingStorageManager poolStorageManager = getStorageManager();
ILendingStorageManager.PoolLendingStorage memory poolLendingStorage;
ILendingStorageManager.LendingInfo memory lendingInfo;
address recipient = synthereumFinder.getImplementationAddress(
SynthereumInterfaces.LendingRewardsReceiver
);
for (uint8 i = 0; i < _pools.length; i++) {
(poolLendingStorage, lendingInfo) = poolStorageManager.getLendingData(
_pools[i]
);
ISynthereumLendingRewards(_pools[i]).claimLendingRewards(
lendingInfo,
poolLendingStorage,
recipient
);
}
}
function interestTokenToCollateral(
address _pool,
uint256 _interestTokenAmount
)
external
view
override
returns (uint256 collateralAmount, address interestTokenAddr)
{
ILendingStorageManager poolStorageManager = getStorageManager();
(
ILendingStorageManager.PoolLendingStorage memory lendingStorage,
ILendingStorageManager.LendingInfo memory lendingInfo
) = poolStorageManager.getLendingData(_pool);
collateralAmount = ILendingModule(lendingInfo.lendingModule)
.interestTokenToCollateral(
_interestTokenAmount,
lendingStorage.collateralToken,
lendingStorage.interestToken,
lendingInfo.args
);
interestTokenAddr = lendingStorage.interestToken;
}
function getAccumulatedInterest(address _pool)
external
view
override
returns (
uint256 poolInterest,
uint256 commissionInterest,
uint256 buybackInterest,
uint256 collateralDeposited
)
{
ILendingStorageManager poolStorageManager = getStorageManager();
(
ILendingStorageManager.PoolStorage memory poolData,
ILendingStorageManager.LendingInfo memory lendingInfo
) = poolStorageManager.getPoolData(_pool);
uint256 totalInterest = ILendingModule(lendingInfo.lendingModule)
.getAccumulatedInterest(_pool, poolData, lendingInfo.args);
InterestSplit memory interestSplit = splitGeneratedInterest(
totalInterest,
poolData.daoInterestShare,
poolData.jrtBuybackShare
);
poolInterest = interestSplit.poolInterest;
commissionInterest = interestSplit.commissionInterest;
buybackInterest = interestSplit.jrtInterest;
collateralDeposited = poolData.collateralDeposited;
}
function collateralToInterestToken(address _pool, uint256 _collateralAmount)
public
view
override
returns (uint256 interestTokenAmount, address interestTokenAddr)
{
ILendingStorageManager poolStorageManager = getStorageManager();
(
ILendingStorageManager.PoolLendingStorage memory lendingStorage,
ILendingStorageManager.LendingInfo memory lendingInfo
) = poolStorageManager.getLendingData(_pool);
interestTokenAmount = ILendingModule(lendingInfo.lendingModule)
.collateralToInterestToken(
_collateralAmount,
lendingStorage.collateralToken,
lendingStorage.interestToken,
lendingInfo.args
);
interestTokenAddr = lendingStorage.interestToken;
}
function claimCommission(
address _pool,
uint256 _collateralAmount,
address _recipient
) internal {
ILendingStorageManager poolStorageManager = getStorageManager();
(
ILendingStorageManager.PoolStorage memory poolData,
ILendingStorageManager.LendingInfo memory lendingInfo
) = poolStorageManager.getPoolData(_pool);
// trigger transfer of funds from _pool
(uint256 interestTokenAmount, ) = collateralToInterestToken(
_pool,
_collateralAmount
);
interestTokenAmount = ISynthereumLendingTransfer(_pool)
.transferToLendingManager(interestTokenAmount);
// delegate call withdraw
bytes memory result = address(lendingInfo.lendingModule)
.functionDelegateCall(
abi.encodeWithSignature(
WITHDRAW_SIG,
poolData,
_pool,
lendingInfo.args,
interestTokenAmount,
_recipient
)
);
ILendingModule.ReturnValues memory res = abi.decode(
result,
(ILendingModule.ReturnValues)
);
// split interest
InterestSplit memory interestSplit = splitGeneratedInterest(
res.totalInterest,
poolData.daoInterestShare,
poolData.jrtBuybackShare
);
//update pool storage
poolStorageManager.updateValues(
_pool,
poolData.collateralDeposited + interestSplit.poolInterest,
poolData.unclaimedDaoJRT + interestSplit.jrtInterest,
poolData.unclaimedDaoCommission +
interestSplit.commissionInterest -
res.tokensOut
);
}
function _getPoolInfo()
internal
view
returns (
ILendingStorageManager.PoolStorage memory poolData,
ILendingStorageManager.LendingInfo memory lendingInfo,
ILendingStorageManager poolStorageManager
)
{
poolStorageManager = getStorageManager();
(poolData, lendingInfo) = poolStorageManager.getPoolData(msg.sender);
}
function getStorageManager() internal view returns (ILendingStorageManager) {
return
ILendingStorageManager(
synthereumFinder.getImplementationAddress(
SynthereumInterfaces.LendingStorageManager
)
);
}
function splitGeneratedInterest(
uint256 _totalInterestGenerated,
uint64 _daoRatio,
uint64 _jrtRatio
) internal pure returns (InterestSplit memory interestSplit) {
if (_totalInterestGenerated == 0) return interestSplit;
uint256 daoInterest = _totalInterestGenerated.mul(_daoRatio);
interestSplit.jrtInterest = daoInterest.mul(_jrtRatio);
interestSplit.commissionInterest = daoInterest - interestSplit.jrtInterest;
interestSplit.poolInterest = _totalInterestGenerated - daoInterest;
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ILendingStorageManager} from './ILendingStorageManager.sol';
interface ILendingManager {
struct Roles {
address admin;
address maintainer;
}
struct ReturnValues {
uint256 poolInterest; //accumulated pool interest since last state-changing operation;
uint256 daoInterest; //acccumulated dao interest since last state-changing operation;
uint256 tokensOut; //amount of collateral used for a money market operation
uint256 tokensTransferred; //amount of tokens finally transfered/received from money market (after eventual fees)
uint256 prevTotalCollateral; //total collateral in the pool (users + LPs) before new operation
}
struct InterestSplit {
uint256 poolInterest; // share of the total interest generated to the LPs;
uint256 jrtInterest; // share of the total interest generated for jrt buyback;
uint256 commissionInterest; // share of the total interest generated as dao commission;
}
struct MigrateReturnValues {
uint256 prevTotalCollateral; // prevDepositedCollateral collateral deposited (without last interests) before the migration
uint256 poolInterest; // poolInterests collateral interests accumalated before the migration
uint256 actualTotalCollateral; // actualCollateralDeposited collateral deposited after the migration
}
event BatchBuyback(
uint256 indexed collateralIn,
uint256 JRTOut,
address receiver
);
event BatchCommissionClaim(uint256 indexed collateralOut, address receiver);
/**
* @notice deposits collateral into the pool's associated money market
* @dev calculates and return the generated interest since last state-changing operation
* @param _collateralAmount amount of collateral to deposit
* @return returnValues check struct
*/
function deposit(uint256 _collateralAmount)
external
returns (ReturnValues memory returnValues);
/**
* @notice withdraw collateral from the pool's associated money market
* @dev calculates and return the generated interest since last state-changing operation
* @param _interestTokenAmount amount of interest tokens to redeem
* @param _recipient the address receiving the collateral from money market
* @return returnValues check struct
*/
function withdraw(uint256 _interestTokenAmount, address _recipient)
external
returns (ReturnValues memory returnValues);
/**
* @notice calculate, split and update the generated interest of the caller pool since last state-changing operation
* @return returnValues check struct
*/
function updateAccumulatedInterest()
external
returns (ReturnValues memory returnValues);
/**
* @notice batches calls to redeem poolData.commissionInterest from multiple pools
* @dev calculates and update the generated interest since last state-changing operation
* @param _pools array of pools to redeem commissions from
* @param _collateralAmounts array of amount of commission to redeem for each pool (matching pools order)
*/
function batchClaimCommission(
address[] calldata _pools,
uint256[] calldata _collateralAmounts
) external;
/**
* @notice batches calls to redeem poolData.jrtInterest from multiple pools
* @notice and executes a swap to buy Jarvis Reward Token
* @dev calculates and update the generated interest since last state-changing operation
* @param _pools array of pools to redeem collateral from
* @param _collateralAmounts array of amount of commission to redeem for each pool (matching pools order)
* @param _collateralAddress address of the pools collateral token (all pools must have the same collateral)
* @param _swapParams encoded bytes necessary for the swap module
*/
function batchBuyback(
address[] calldata _pools,
uint256[] calldata _collateralAmounts,
address _collateralAddress,
bytes calldata _swapParams
) external;
/**
* @notice sets the address of the implementation of a lending module and its extraBytes
* @param _id associated to the lending module to be set
* @param _lendingInfo see lendingInfo struct
*/
function setLendingModule(
string calldata _id,
ILendingStorageManager.LendingInfo calldata _lendingInfo
) external;
/**
* @notice Add a swap module to the whitelist
* @param _swapModule Swap module to add
*/
function addSwapProtocol(address _swapModule) external;
/**
* @notice Remove a swap module from the whitelist
* @param _swapModule Swap module to remove
*/
function removeSwapProtocol(address _swapModule) external;
/**
* @notice sets an address as the swap module associated to a specific collateral
* @dev the swapModule must implement the IJRTSwapModule interface
* @param _collateral collateral address associated to the swap module
* @param _swapModule IJRTSwapModule implementer contract
*/
function setSwapModule(address _collateral, address _swapModule) external;
/**
* @notice set shares on interest generated by a pool collateral on the lending storage manager
* @param _pool pool address to set shares on
* @param _daoInterestShare share of total interest generated assigned to the dao
* @param _jrtBuybackShare share of the total dao interest used to buyback jrt from an AMM
*/
function setShares(
address _pool,
uint64 _daoInterestShare,
uint64 _jrtBuybackShare
) external;
/**
* @notice migrates liquidity from one lending module (and money market), to a new one
* @dev calculates and return the generated interest since last state-changing operation.
* @dev The new lending module info must be have been previously set in the storage manager
* @param _newLendingID id associated to the new lending module info
* @param _newInterestBearingToken address of the interest token of the new money market
* @param _interestTokenAmount total amount of interest token to migrate from old to new money market
* @return migrateReturnValues check struct
*/
function migrateLendingModule(
string memory _newLendingID,
address _newInterestBearingToken,
uint256 _interestTokenAmount
) external returns (MigrateReturnValues memory);
/**
* @notice migrates pool storage from a deployed pool to a new pool
* @param _migrationPool Pool from which the storage is migrated
* @param _newPool address of the new pool
* @return sourceCollateralAmount Collateral amount of the pool to migrate
* @return actualCollateralAmount Collateral amount of the new deployed pool
*/
function migratePool(address _migrationPool, address _newPool)
external
returns (uint256 sourceCollateralAmount, uint256 actualCollateralAmount);
/**
* @notice Claim leinding protocol rewards of a list of pools
* @notice _pools List of pools from which claim rewards
*/
function claimLendingRewards(address[] calldata _pools) external;
/**
* @notice returns the conversion between interest token and collateral of a specific money market
* @param _pool reference pool to check conversion
* @param _interestTokenAmount amount of interest token to calculate conversion on
* @return collateralAmount amount of collateral after conversion
* @return interestTokenAddr address of the associated interest token
*/
function interestTokenToCollateral(
address _pool,
uint256 _interestTokenAmount
) external view returns (uint256 collateralAmount, address interestTokenAddr);
/**
* @notice returns accumulated interest of a pool since state-changing last operation
* @dev does not update state
* @param _pool reference pool to check accumulated interest
* @return poolInterest amount of interest generated for the pool after splitting the dao share
* @return commissionInterest amount of interest generated for the dao commissions
* @return buybackInterest amount of interest generated for the buyback
* @return collateralDeposited total amount of collateral currently deposited by the pool
*/
function getAccumulatedInterest(address _pool)
external
view
returns (
uint256 poolInterest,
uint256 commissionInterest,
uint256 buybackInterest,
uint256 collateralDeposited
);
/**
* @notice returns the conversion between collateral and interest token of a specific money market
* @param _pool reference pool to check conversion
* @param _collateralAmount amount of collateral to calculate conversion on
* @return interestTokenAmount amount of interest token after conversion
* @return interestTokenAddr address of the associated interest token
*/
function collateralToInterestToken(address _pool, uint256 _collateralAmount)
external
view
returns (uint256 interestTokenAmount, address interestTokenAddr);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ILendingStorageManager} from './ILendingStorageManager.sol';
interface ILendingModule {
struct ReturnValues {
uint256 totalInterest; // total accumulated interest of the pool since last state-changing operation
uint256 tokensOut; //amount of tokens received from money market (before eventual fees)
uint256 tokensTransferred; //amount of tokens finally transfered from money market (after eventual fees)
}
/**
* @notice deposits collateral into the money market
* @dev calculates and return the generated interest since last state-changing operation
* @param _poolData pool storage information
* @param _lendingArgs encoded args needed by the specific implementation
* @param _amount of collateral to deposit
* @return totalInterest check ReturnValues struct
* @return tokensOut check ReturnValues struct
* @return tokensTransferred check ReturnValues struct
*/
function deposit(
ILendingStorageManager.PoolStorage calldata _poolData,
bytes calldata _lendingArgs,
uint256 _amount
)
external
returns (
uint256 totalInterest,
uint256 tokensOut,
uint256 tokensTransferred
);
/**
* @notice withdraw collateral from the money market
* @dev calculates and return the generated interest since last state-changing operation
* @param _poolData pool storage information
* @param _pool pool address to calculate interest on
* @param _lendingArgs encoded args needed by the specific implementation
* @param _amount of interest tokens to redeem
* @param _recipient address receiving the collateral from money market
* @return totalInterest check ReturnValues struct
* @return tokensOut check ReturnValues struct
* @return tokensTransferred check ReturnValues struct
*/
function withdraw(
ILendingStorageManager.PoolStorage calldata _poolData,
address _pool,
bytes calldata _lendingArgs,
uint256 _amount,
address _recipient
)
external
returns (
uint256 totalInterest,
uint256 tokensOut,
uint256 tokensTransferred
);
/**
* @notice transfer all interest token balance from an old pool to a new one
* @param _oldPool Address of the old pool
* @param _newPool Address of the new pool
* @param _collateral address of collateral token
* @param _interestToken address of interest token
* @param _extraArgs encoded args the ILendingModule implementer might need. see ILendingManager.LendingInfo struct
* @return prevTotalCollateral Total collateral in the old pool
* @return actualTotalCollateral Total collateral in the new pool
*/
function totalTransfer(
address _oldPool,
address _newPool,
address _collateral,
address _interestToken,
bytes calldata _extraArgs
)
external
returns (uint256 prevTotalCollateral, uint256 actualTotalCollateral);
/**
* @notice Claim the rewards associated to the bearing tokens of the caller(pool)
* @param _lendingArgs encoded args needed by the specific implementation
* @param _collateral Address of the collateral of the pool
* @param _bearingToken Address of the bearing token of the pool
* @param _recipient address to which send rewards
*/
function claimRewards(
bytes calldata _lendingArgs,
address _collateral,
address _bearingToken,
address _recipient
) external;
/**
* @notice updates eventual state and returns updated accumulated interest
* @param _poolAddress reference pool to check accumulated interest
* @param _poolData pool storage information
* @param _extraArgs encoded args the ILendingModule implementer might need. see ILendingManager.LendingInfo struct
* @return totalInterest total amount of interest accumulated
*/
function getUpdatedInterest(
address _poolAddress,
ILendingStorageManager.PoolStorage calldata _poolData,
bytes calldata _extraArgs
) external returns (uint256 totalInterest);
/**
* @notice returns accumulated interest of a pool since state-changing last operation
* @dev does not update state
* @param _poolAddress reference pool to check accumulated interest
* @param _poolData pool storage information
* @param _extraArgs encoded args the ILendingModule implementer might need. see ILendingManager.LendingInfo struct
* @return totalInterest total amount of interest accumulated
*/
function getAccumulatedInterest(
address _poolAddress,
ILendingStorageManager.PoolStorage calldata _poolData,
bytes calldata _extraArgs
) external view returns (uint256 totalInterest);
/**
* @notice returns bearing token associated to the collateral
* @dev does not update state
* @param _collateral collateral address to check bearing token
* @param _extraArgs encoded args the ILendingModule implementer might need. see ILendingManager.LendingInfo struct
* @return token bearing token
*/
function getInterestBearingToken(
address _collateral,
bytes calldata _extraArgs
) external view returns (address token);
/**
* @notice returns the conversion between collateral and interest token of a specific money market
* @param _collateralAmount amount of collateral to calculate conversion on
* @param _collateral address of collateral token
* @param _interestToken address of interest token
* @param _extraArgs encoded args the ILendingModule implementer might need. see ILendingManager.LendingInfo struct
* @return interestTokenAmount amount of interest token after conversion
*/
function collateralToInterestToken(
uint256 _collateralAmount,
address _collateral,
address _interestToken,
bytes calldata _extraArgs
) external view returns (uint256 interestTokenAmount);
/**
* @notice returns the conversion between interest token and collateral of a specific money market
* @param _interestTokenAmount amount of interest token to calculate conversion on
* @param _collateral address of collateral token
* @param _interestToken address of interest token
* @param _extraArgs encoded args the ILendingModule implementer might need. see ILendingManager.LendingInfo struct
* @return collateralAmount amount of collateral token after conversion
*/
function interestTokenToCollateral(
uint256 _interestTokenAmount,
address _collateral,
address _interestToken,
bytes calldata _extraArgs
) external view returns (uint256 collateralAmount);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
interface ILendingStorageManager {
struct PoolStorage {
bytes32 lendingModuleId; // hash of the lending module id associated with the LendingInfo the pool currently is using
uint256 collateralDeposited; // amount of collateral currently deposited in the MoneyMarket
uint256 unclaimedDaoJRT; // amount of interest to be claimed to buyback JRT
uint256 unclaimedDaoCommission; // amount of interest to be claimed as commission (in collateral)
address collateral; // collateral address of the pool
uint64 jrtBuybackShare; // share of dao interest used to buyback JRT
address interestBearingToken; // interest token address of the pool
uint64 daoInterestShare; // share of total interest generated by the pool directed to the DAO
}
struct PoolLendingStorage {
address collateralToken; // address of the collateral token of a pool
address interestToken; // address of interest token of a pool
}
struct LendingInfo {
address lendingModule; // address of the ILendingModule interface implementer
bytes args; // encoded args the ILendingModule implementer might need
}
/**
* @notice sets a ILendingModule implementer info
* @param _id string identifying a specific ILendingModule implementer
* @param _lendingInfo see lendingInfo struct
*/
function setLendingModule(
string calldata _id,
LendingInfo calldata _lendingInfo
) external;
/**
* @notice Add a swap module to the whitelist
* @param _swapModule Swap module to add
*/
function addSwapProtocol(address _swapModule) external;
/**
* @notice Remove a swap module from the whitelist
* @param _swapModule Swap module to remove
*/
function removeSwapProtocol(address _swapModule) external;
/**
* @notice sets an address as the swap module associated to a specific collateral
* @dev the swapModule must implement the IJRTSwapModule interface
* @param _collateral collateral address associated to the swap module
* @param _swapModule IJRTSwapModule implementer contract
*/
function setSwapModule(address _collateral, address _swapModule) external;
/**
* @notice set shares on interest generated by a pool collateral on the lending storage manager
* @param _pool pool address to set shares on
* @param _daoInterestShare share of total interest generated assigned to the dao
* @param _jrtBuybackShare share of the total dao interest used to buyback jrt from an AMM
*/
function setShares(
address _pool,
uint64 _daoInterestShare,
uint64 _jrtBuybackShare
) external;
/**
* @notice store data for lending manager associated to a pool
* @param _lendingID string identifying the associated ILendingModule implementer
* @param _pool pool address to set info
* @param _collateral collateral address of the pool
* @param _interestBearingToken address of the interest token in use
* @param _daoInterestShare share of total interest generated assigned to the dao
* @param _jrtBuybackShare share of the total dao interest used to buyback jrt from an AMM
*/
function setPoolStorage(
string calldata _lendingID,
address _pool,
address _collateral,
address _interestBearingToken,
uint64 _daoInterestShare,
uint64 _jrtBuybackShare
) external;
/**
* @notice assign oldPool storage information and state to newPool address and deletes oldPool storage slot
* @dev is used when a pool is redeployed and the liquidity transferred over
* @param _oldPool address of old pool to migrate storage from
* @param _newPool address of the new pool receiving state of oldPool
* @param _newCollateralDeposited Amount of collateral deposited in the new pool after the migration
*/
function migratePoolStorage(
address _oldPool,
address _newPool,
uint256 _newCollateralDeposited
) external;
/**
* @notice sets new lending info on a pool
* @dev used when migrating liquidity from one lending module (and money market), to a new one
* @dev The new lending module info must be have been previously set in the storage manager
* @param _newLendingID id associated to the new lending module info
* @param _pool address of the pool whose associated lending module is being migrated
* @param _newInterestToken address of the interest token of the new Lending Module (can be set blank)
* @return poolData with the updated state
* @return lendingInfo of the new lending module
*/
function migrateLendingModule(
string calldata _newLendingID,
address _pool,
address _newInterestToken
) external returns (PoolStorage memory, LendingInfo memory);
/**
* @notice updates storage of a pool
* @dev should be callable only by LendingManager after state-changing operations
* @param _pool address of the pool to update values
* @param _collateralDeposited updated amount of collateral deposited
* @param _daoJRT updated amount of unclaimed interest for JRT buyback
* @param _daoInterest updated amount of unclaimed interest as dao commission
*/
function updateValues(
address _pool,
uint256 _collateralDeposited,
uint256 _daoJRT,
uint256 _daoInterest
) external;
/**
* @notice Returns info about a supported lending module
* @param _id Name of the module
* @return lendingInfo Address and bytes associated to the lending mdodule
*/
function getLendingModule(string calldata _id)
external
view
returns (LendingInfo memory lendingInfo);
/**
* @notice reads PoolStorage of a pool
* @param _pool address of the pool to read storage
* @return poolData pool struct info
*/
function getPoolStorage(address _pool)
external
view
returns (PoolStorage memory poolData);
/**
* @notice reads PoolStorage and LendingInfo of a pool
* @param _pool address of the pool to read storage
* @return poolData pool struct info
* @return lendingInfo information of the lending module associated with the pool
*/
function getPoolData(address _pool)
external
view
returns (PoolStorage memory poolData, LendingInfo memory lendingInfo);
/**
* @notice reads lendingStorage and LendingInfo of a pool
* @param _pool address of the pool to read storage
* @return lendingStorage information of the addresses of collateral and intrestToken
* @return lendingInfo information of the lending module associated with the pool
*/
function getLendingData(address _pool)
external
view
returns (
PoolLendingStorage memory lendingStorage,
LendingInfo memory lendingInfo
);
/**
* @notice Return the list containing every swap module supported
* @return List of swap modules
*/
function getSwapModules() external view returns (address[] memory);
/**
* @notice reads the JRT Buyback module associated to a collateral
* @param _collateral address of the collateral to retrieve module
* @return swapModule address of interface implementer of the IJRTSwapModule
*/
function getCollateralSwapModule(address _collateral)
external
view
returns (address swapModule);
/**
* @notice reads the interest beaaring token address associated to a pool
* @param _pool address of the pool to retrieve interest token
* @return interestTokenAddr address of the interest token
*/
function getInterestBearingToken(address _pool)
external
view
returns (address interestTokenAddr);
/**
* @notice reads the shares used for splitting interests between pool, dao and buyback
* @param _pool address of the pool to retrieve interest token
* @return jrtBuybackShare Percentage of interests claimable by th DAO
* @return daoInterestShare Percentage of interests used for the buyback
*/
function getShares(address _pool)
external
view
returns (uint256 jrtBuybackShare, uint256 daoInterestShare);
/**
* @notice reads the last collateral amount deposited in the pool
* @param _pool address of the pool to retrieve collateral amount
* @return collateralAmount Amount of collateral deposited in the pool
*/
function getCollateralDeposited(address _pool)
external
view
returns (uint256 collateralAmount);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/**
* @title Provides addresses of the contracts implementing certain interfaces.
*/
interface ISynthereumFinder {
/**
* @notice Updates the address of the contract that implements `interfaceName`.
* @param interfaceName bytes32 encoding of the interface name that is either changed or registered.
* @param implementationAddress address of the deployed contract that implements the interface.
*/
function changeImplementationAddress(
bytes32 interfaceName,
address implementationAddress
) external;
/**
* @notice Gets the address of the contract that implements the given `interfaceName`.
* @param interfaceName queried interface.
* @return implementationAddress Address of the deployed contract that implements the interface.
*/
function getImplementationAddress(bytes32 interfaceName)
external
view
returns (address);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.9;
/**
* @title Stores common interface names used throughout Synthereum.
*/
library SynthereumInterfaces {
bytes32 public constant Deployer = 'Deployer';
bytes32 public constant PoolRegistry = 'PoolRegistry';
bytes32 public constant SelfMintingRegistry = 'SelfMintingRegistry';
bytes32 public constant FixedRateRegistry = 'FixedRateRegistry';
bytes32 public constant VaultRegistry = 'VaultRegistry';
bytes32 public constant StakingLPVaultRegistry = 'StakingLPVaultRegistry';
bytes32 public constant FactoryVersioning = 'FactoryVersioning';
bytes32 public constant Manager = 'Manager';
bytes32 public constant TokenFactory = 'TokenFactory';
bytes32 public constant CreditLineController = 'CreditLineController';
bytes32 public constant CollateralWhitelist = 'CollateralWhitelist';
bytes32 public constant IdentifierWhitelist = 'IdentifierWhitelist';
bytes32 public constant LendingManager = 'LendingManager';
bytes32 public constant LendingStorageManager = 'LendingStorageManager';
bytes32 public constant CommissionReceiver = 'CommissionReceiver';
bytes32 public constant BuybackProgramReceiver = 'BuybackProgramReceiver';
bytes32 public constant LendingRewardsReceiver = 'LendingRewardsReceiver';
bytes32 public constant StakingRewardsReceiver = 'StakingRewardsReceiver';
bytes32 public constant JarvisToken = 'JarvisToken';
bytes32 public constant DebtTokenFactory = 'DebtTokenFactory';
bytes32 public constant VaultFactory = 'VaultFactory';
bytes32 public constant StakingLPVaultFactory = 'StakingLPVaultFactory';
bytes32 public constant PriceFeed = 'PriceFeed';
bytes32 public constant StakedJarvisToken = 'StakedJarvisToken';
bytes32 public constant StakingLPVaultData = 'StakingLPVaultData';
bytes32 public constant JarvisBrrrrr = 'JarvisBrrrrr';
bytes32 public constant MoneyMarketManager = 'MoneyMarketManager';
bytes32 public constant CrossChainBridge = 'CrossChainBridge';
bytes32 public constant TrustedForwarder = 'TrustedForwarder';
}
library FactoryInterfaces {
bytes32 public constant PoolFactory = 'PoolFactory';
bytes32 public constant SelfMintingFactory = 'SelfMintingFactory';
bytes32 public constant FixedRateFactory = 'FixedRateFactory';
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/**
* @title Pool interface for making lending manager interacting with the pool
*/
interface ISynthereumLendingTransfer {
/**
* @notice Transfer a bearing amount to the lending manager
* @notice Only the lending manager can call the function
* @param _bearingAmount Amount of bearing token to transfer
* @return bearingAmountOut Real bearing amount transferred to the lending manager
*/
function transferToLendingManager(uint256 _bearingAmount)
external
returns (uint256 bearingAmountOut);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ILendingStorageManager} from '../../../lending-module/interfaces/ILendingStorageManager.sol';
/**
* @title Pool interface for claiming lending rewards
*/
interface ISynthereumLendingRewards {
/**
* @notice Claim rewards, associaated to the lending module supported by the pool
* @notice Only the lending manager can call the function
* @param _lendingInfo Address of lending module implementation and global args
* @param _poolLendingStorage Addresses of collateral and bearing token of the pool
* @param _recipient Address of recipient receiving rewards
*/
function claimLendingRewards(
ILendingStorageManager.LendingInfo calldata _lendingInfo,
ILendingStorageManager.PoolLendingStorage calldata _poolLendingStorage,
address _recipient
) external;
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.9;
/**
* @title PreciseUnitMath
* @author Synthereum Protocol
*
* Arithmetic for fixed-point numbers with 18 decimals of precision.
*
*/
library PreciseUnitMath {
// The number One in precise units.
uint256 internal constant PRECISE_UNIT = 10**18;
// The number One in precise units multiplied for 10^18.
uint256 internal constant DOUBLE_PRECISE_UNIT = 10**36;
// Max unsigned integer value
uint256 internal constant MAX_UINT_256 = type(uint256).max;
/**
* @dev Getter function since constants can't be read directly from libraries.
*/
function preciseUnit() internal pure returns (uint256) {
return PRECISE_UNIT;
}
/**
* @dev Getter function since constants can't be read directly from libraries.
*/
function maxUint256() internal pure returns (uint256) {
return MAX_UINT_256;
}
/**
* @dev Multiplies value a by value b (result is rounded down). It's assumed that the value b is the significand
* of a number with 18 decimals precision.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return (a * b) / PRECISE_UNIT;
}
/**
* @dev Multiplies value a by value b (result is rounded up). It's assumed that the value b is the significand
* of a number with 18 decimals precision.
*/
function mulCeil(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0 || b == 0) {
return 0;
}
return (((a * b) - 1) / PRECISE_UNIT) + 1;
}
/**
* @dev Divides value a by value b (result is rounded down).
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return (a * PRECISE_UNIT) / b;
}
/**
* @dev Divides value a by value b (result is rounded up or away from 0).
*/
function divCeil(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, 'Cant divide by 0');
return a > 0 ? (((a * PRECISE_UNIT) - 1) / b) + 1 : 0;
}
/**
* @dev Performs the power on a specified value, reverts on overflow.
*/
function safePower(uint256 a, uint256 pow) internal pure returns (uint256) {
require(a > 0, 'Value must be positive');
uint256 result = 1;
for (uint256 i = 0; i < pow; i++) {
uint256 previousResult = result;
result = previousResult * a;
}
return result;
}
/**
* @dev The minimum of `a` and `b`.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev The maximum of `a` and `b`.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.9;
import {ISynthereumFinder} from '../../core/interfaces/IFinder.sol';
import {ISynthereumFactoryVersioning} from '../../core/interfaces/IFactoryVersioning.sol';
import {SynthereumInterfaces, FactoryInterfaces} from '../../core/Constants.sol';
/** @title Library to use for controlling the access of a functions from the factories
*/
library SynthereumFactoryAccess {
/**
*@notice Revert if caller is not a Pool factory
* @param _finder Synthereum finder
*/
function _onlyPoolFactory(ISynthereumFinder _finder) internal view {
ISynthereumFactoryVersioning factoryVersioning
= ISynthereumFactoryVersioning(
_finder.getImplementationAddress(SynthereumInterfaces.FactoryVersioning)
);
uint8 numberOfPoolFactories = factoryVersioning.numberOfFactoryVersions(
FactoryInterfaces.PoolFactory
);
require(
_checkSenderIsFactory(
factoryVersioning,
numberOfPoolFactories,
FactoryInterfaces.PoolFactory
),
'Not allowed'
);
}
/**
* @notice Revert if caller is not a Pool factory or a Fixed rate factory
* @param _finder Synthereum finder
*/
function _onlyPoolFactoryOrFixedRateFactory(ISynthereumFinder _finder)
internal
view
{
ISynthereumFactoryVersioning factoryVersioning
= ISynthereumFactoryVersioning(
_finder.getImplementationAddress(SynthereumInterfaces.FactoryVersioning)
);
uint8 numberOfPoolFactories = factoryVersioning.numberOfFactoryVersions(
FactoryInterfaces.PoolFactory
);
uint8 numberOfFixedRateFactories = factoryVersioning
.numberOfFactoryVersions(FactoryInterfaces.FixedRateFactory);
bool isPoolFactory = _checkSenderIsFactory(
factoryVersioning,
numberOfPoolFactories,
FactoryInterfaces.PoolFactory
);
if (isPoolFactory) {
return;
}
bool isFixedRateFactory = _checkSenderIsFactory(
factoryVersioning,
numberOfFixedRateFactories,
FactoryInterfaces.FixedRateFactory
);
if (isFixedRateFactory) {
return;
}
revert('Sender must be a Pool or FixedRate factory');
}
/**
* @notice Check if sender is a factory
* @param _factoryVersioning SynthereumFactoryVersioning contract
* @param _numberOfFactories Total number of versions of a factory type
* @param _factoryKind Type of the factory
* @return isFactory True if sender is a factory, otherwise false
*/
function _checkSenderIsFactory(
ISynthereumFactoryVersioning _factoryVersioning,
uint8 _numberOfFactories,
bytes32 _factoryKind
) private view returns (bool isFactory) {
uint8 counterFactory;
for (uint8 i = 0; counterFactory < _numberOfFactories; i++) {
try _factoryVersioning.getFactoryVersion(_factoryKind, i) returns (
address factory
) {
if (msg.sender == factory) {
isFactory = true;
break;
} else {
counterFactory++;
if (counterFactory == _numberOfFactories) {
isFactory = false;
}
}
} catch {}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/**
* @title Provides addresses of different versions of pools factory and derivative factory
*/
interface ISynthereumFactoryVersioning {
/** @notice Sets a Factory
* @param factoryType Type of factory
* @param version Version of the factory to be set
* @param factory The pool factory address to be set
*/
function setFactory(
bytes32 factoryType,
uint8 version,
address factory
) external;
/** @notice Removes a factory
* @param factoryType The type of factory to be removed
* @param version Version of the factory to be removed
*/
function removeFactory(bytes32 factoryType, uint8 version) external;
/** @notice Gets a factory contract address
* @param factoryType The type of factory to be checked
* @param version Version of the factory to be checked
* @return factory Address of the factory contract
*/
function getFactoryVersion(bytes32 factoryType, uint8 version)
external
view
returns (address factory);
/** @notice Gets the number of factory versions for a specific type
* @param factoryType The type of factory to be checked
* @return numberOfVersions Total number of versions for a specific factory
*/
function numberOfFactoryVersions(bytes32 factoryType)
external
view
returns (uint8 numberOfVersions);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.9;
import {ISynthereumFinder} from '../../../core/interfaces/IFinder.sol';
import {SynthereumFactoryAccess} from '../../../common/libs/FactoryAccess.sol';
/**
* @title Abstract contract inherited by pools for moving storage from one pool to another
*/
contract SynthereumPoolMigration {
ISynthereumFinder internal finder;
modifier onlyPoolFactory() {
SynthereumFactoryAccess._onlyPoolFactory(finder);
_;
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.9;
import {ISynthereumFinder} from '../../../core/interfaces/IFinder.sol';
import {SynthereumPoolMigration} from './PoolMigration.sol';
/**
* @title Abstract contract inherit by pools for moving storage from one pool to another
*/
abstract contract SynthereumPoolMigrationFrom is SynthereumPoolMigration {
/**
* @notice Migrate storage from this pool resetting and cleaning data
* @notice This can be called only by a pool factory
* @return poolVersion Version of the pool
* @return price Actual price of the pair
* @return storageBytes Pool storage encoded in bytes
*/
function migrateStorage()
external
virtual
onlyPoolFactory
returns (
uint8 poolVersion,
uint256 price,
bytes memory storageBytes
)
{
_modifyStorageFrom();
(poolVersion, price, storageBytes) = _encodeStorage();
_cleanStorage();
}
/**
* @notice Transfer all bearing tokens to another address
* @notice Only the lending manager can call the function
* @param _recipient Address receving bearing amount
* @return migrationAmount Total balance of the pool in bearing tokens before migration
*/
function migrateTotalFunds(address _recipient)
external
virtual
returns (uint256 migrationAmount);
/**
* @notice Function to implement for modifying storage before the encoding
*/
function _modifyStorageFrom() internal virtual;
/**
* @notice Function to implement for cleaning and resetting the storage to the initial state
*/
function _cleanStorage() internal virtual;
/**
* @notice Function to implement for encoding storage in bytes
* @return poolVersion Version of the pool
* @return price Actual price of the pair
* @return storageBytes Pool storage encoded in bytes
*/
function _encodeStorage()
internal
view
virtual
returns (
uint8 poolVersion,
uint256 price,
bytes memory storageBytes
);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.9;
import {IERC20} from '../../../@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {ILendingModule} from '../interfaces/ILendingModule.sol';
import {ILendingStorageManager} from '../interfaces/ILendingStorageManager.sol';
import {SafeERC20} from '../../../@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import {SynthereumPoolMigrationFrom} from '../../synthereum-pool/common/migration/PoolMigrationFrom.sol';
// this module serves as a mock module
// it can be attached to any pool in order to avoid using a lending protocol
contract TransparentModule is ILendingModule {
using SafeERC20 for IERC20;
function deposit(
ILendingStorageManager.PoolStorage calldata _poolData,
bytes calldata,
uint256 _amount
)
external
override
returns (
uint256 totalInterest,
uint256 tokensOut,
uint256 tokensTransferred
)
{
// transfer back collateral to the pool (msg.sender)
IERC20 collateral = IERC20(_poolData.collateral);
require(collateral.balanceOf(address(this)) >= _amount, 'Wrong balance');
tokensTransferred = _amount;
tokensOut = tokensTransferred;
collateral.safeTransfer(msg.sender, tokensTransferred);
}
function withdraw(
ILendingStorageManager.PoolStorage calldata _poolData,
address,
bytes calldata,
uint256 _amount,
address _recipient
)
external
override
returns (
uint256 totalInterest,
uint256 tokensOut,
uint256 tokensTransferred
)
{
// proxy should have received interest tokens (same as collateral in this case) from the pool
tokensTransferred = _amount;
tokensOut = tokensTransferred;
// transfer collateral to recipient
IERC20(_poolData.interestBearingToken).safeTransfer(
_recipient,
tokensTransferred
);
}
function totalTransfer(
address _oldPool,
address _newPool,
address,
address,
bytes calldata
)
external
returns (uint256 prevTotalCollateral, uint256 actualTotalCollateral)
{
prevTotalCollateral = SynthereumPoolMigrationFrom(_oldPool)
.migrateTotalFunds(_newPool);
actualTotalCollateral = prevTotalCollateral;
}
function claimRewards(
bytes calldata,
address,
address,
address
) external pure override {
revert('Claim rewards not supported');
}
function getUpdatedInterest(
address,
ILendingStorageManager.PoolStorage calldata,
bytes calldata
) external pure override returns (uint256 totalInterest) {}
function getAccumulatedInterest(
address,
ILendingStorageManager.PoolStorage calldata,
bytes calldata
) external pure override returns (uint256 totalInterest) {}
function getInterestBearingToken(address _collateral, bytes calldata)
external
pure
override
returns (address token)
{
token = _collateral;
}
function collateralToInterestToken(
uint256 _collateralAmount,
address,
address,
bytes calldata
) external pure override returns (uint256 interestTokenAmount) {
interestTokenAmount = _collateralAmount;
}
function interestTokenToCollateral(
uint256 _interestTokenAmount,
address,
address,
bytes calldata
) external pure override returns (uint256 collateralAmount) {
collateralAmount = _interestTokenAmount;
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.9;
import {Address} from '../../../@openzeppelin/contracts/utils/Address.sol';
import {IERC20} from '../../../@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from '../../../@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import {IJRTSwapModule} from '../interfaces/IJrtSwapModule.sol';
import {IUniswapV2Router02} from '../../../@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol';
contract UniV2JRTSwapModule is IJRTSwapModule {
using SafeERC20 for IERC20;
struct SwapInfo {
address routerAddress;
address[] tokenSwapPath;
uint256 expiration;
uint256 minTokensOut;
}
function swapToJRT(
address _recipient,
address _collateral,
address _jarvisToken,
uint256 _amountIn,
bytes calldata _params
) external override returns (uint256 amountOut) {
// decode swapInfo
SwapInfo memory swapInfo = abi.decode(_params, (SwapInfo));
uint256 pathLength = swapInfo.tokenSwapPath.length;
require(
swapInfo.tokenSwapPath[pathLength - 1] == _jarvisToken,
'Wrong token swap path'
);
// swap to JRT to final recipient
IUniswapV2Router02 router = IUniswapV2Router02(swapInfo.routerAddress);
IERC20(_collateral).safeIncreaseAllowance(address(router), _amountIn);
amountOut = router.swapExactTokensForTokens(
_amountIn,
swapInfo.minTokensOut,
swapInfo.tokenSwapPath,
_recipient,
swapInfo.expiration
)[pathLength - 1];
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
interface IJRTSwapModule {
/**
* @notice executes an AMM swap from collateral to JRT
* @param _recipient address receiving JRT tokens
* @param _collateral address of the collateral token to swap
* @param _jarvisToken address of the jarvis token to buy
* @param _amountIn exact amount of collateral to swap
* @param _params extra params needed on the specific implementation (with different AMM)
* @return amountOut amount of JRT in output
*/
function swapToJRT(
address _recipient,
address _collateral,
address _jarvisToken,
uint256 _amountIn,
bytes calldata _params
) external returns (uint256 amountOut);
}pragma solidity >=0.6.2;
import './IUniswapV2Router01.sol';
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.9;
import {Address} from '../../../@openzeppelin/contracts/utils/Address.sol';
import {IERC20} from '../../../@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from '../../../@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import {ISynthereumDeployment} from '../../common/interfaces/IDeployment.sol';
import {IBalancerVault} from '../interfaces/IBalancerVault.sol';
import {IJRTSwapModule} from '../interfaces/IJrtSwapModule.sol';
contract BalancerJRTSwapModule is IJRTSwapModule {
using SafeERC20 for IERC20;
struct SwapInfo {
bytes32 poolId;
address routerAddress;
uint256 minTokensOut; // anti slippage
uint256 expiration;
}
function swapToJRT(
address _recipient,
address _collateral,
address _jarvisToken,
uint256 _amountIn,
bytes calldata _params
) external override returns (uint256 amountOut) {
// decode swapInfo
SwapInfo memory swapInfo = abi.decode(_params, (SwapInfo));
// build params
IBalancerVault.SingleSwap memory singleSwap = IBalancerVault.SingleSwap(
swapInfo.poolId,
IBalancerVault.SwapKind.GIVEN_IN,
_collateral,
_jarvisToken,
_amountIn,
'0x00'
);
IBalancerVault.FundManagement memory funds = IBalancerVault.FundManagement(
address(this),
false,
payable(_recipient),
false
);
// swap to JRT to final recipient
IBalancerVault router = IBalancerVault(swapInfo.routerAddress);
IERC20(_collateral).safeIncreaseAllowance(address(router), _amountIn);
amountOut = router.swap(
singleSwap,
funds,
swapInfo.minTokensOut,
swapInfo.expiration
);
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {IERC20} from '../../../@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {ISynthereumFinder} from '../../core/interfaces/IFinder.sol';
/**
* @title Interface that a pool MUST have in order to be included in the deployer
*/
interface ISynthereumDeployment {
/**
* @notice Get Synthereum finder of the pool/self-minting derivative
* @return finder Returns finder contract
*/
function synthereumFinder() external view returns (ISynthereumFinder finder);
/**
* @notice Get Synthereum version
* @return contractVersion Returns the version of this pool/self-minting derivative
*/
function version() external view returns (uint8 contractVersion);
/**
* @notice Get the collateral token of this pool/self-minting derivative
* @return collateralCurrency The ERC20 collateral token
*/
function collateralToken() external view returns (IERC20 collateralCurrency);
/**
* @notice Get the synthetic token associated to this pool/self-minting derivative
* @return syntheticCurrency The ERC20 synthetic token
*/
function syntheticToken() external view returns (IERC20 syntheticCurrency);
/**
* @notice Get the synthetic token symbol associated to this pool/self-minting derivative
* @return symbol The ERC20 synthetic token symbol
*/
function syntheticTokenSymbol() external view returns (string memory symbol);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
interface IBalancerVault {
enum SwapKind {
GIVEN_IN,
GIVEN_OUT
}
struct SingleSwap {
bytes32 poolId;
SwapKind kind;
address assetIn;
address assetOut;
uint256 amount;
bytes userData;
}
struct FundManagement {
address sender;
bool fromInternalBalance;
address payable recipient;
bool toInternalBalance;
}
function swap(
SingleSwap memory singleSwap,
FundManagement memory funds,
uint256 limit,
uint256 deadline
) external payable returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.9;
import {IERC20} from '../../../@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {ILendingModule} from '../interfaces/ILendingModule.sol';
import {ILendingStorageManager} from '../interfaces/ILendingStorageManager.sol';
import {ICompoundToken, IComptroller} from '../interfaces/ICToken.sol';
import {ExponentialNoError} from '../libs/ExponentialNoError.sol';
import {IRewardsController} from '../interfaces/IRewardsController.sol';
import {Address} from '../../../@openzeppelin/contracts/utils/Address.sol';
import {SafeERC20} from '../../../@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import {PreciseUnitMath} from '../../base/utils/PreciseUnitMath.sol';
import {SynthereumPoolMigrationFrom} from '../../synthereum-pool/common/migration/PoolMigrationFrom.sol';
contract CompoundModule is ILendingModule, ExponentialNoError {
using SafeERC20 for IERC20;
using SafeERC20 for ICompoundToken;
function deposit(
ILendingStorageManager.PoolStorage calldata _poolData,
bytes calldata,
uint256 _amount
)
external
override
returns (
uint256 totalInterest,
uint256 tokensOut,
uint256 tokensTransferred
)
{
// proxy should have received collateral from the pool
IERC20 collateral = IERC20(_poolData.collateral);
require(collateral.balanceOf(address(this)) >= _amount, 'Wrong balance');
// initialise compound interest token
ICompoundToken cToken = ICompoundToken(_poolData.interestBearingToken);
// get tokens balance before
uint256 cTokenBalanceBefore = cToken.balanceOf(address(this));
uint256 totalPrevDeposit;
// calculate accrued interest since last operation
(totalInterest, totalPrevDeposit) = calculateGeneratedInterest(
msg.sender,
_poolData,
0,
cToken,
true
);
// approve and deposit underlying
collateral.safeIncreaseAllowance(address(cToken), _amount);
require(cToken.mint(_amount) == 0, 'Failed mint');
uint256 cTokenBalanceAfter = cToken.balanceOf(address(this));
// set return values
tokensTransferred = cTokenBalanceAfter - cTokenBalanceBefore;
// transfer cToken to pool
cToken.transfer(msg.sender, tokensTransferred);
tokensOut =
cToken.balanceOfUnderlying(msg.sender) -
totalPrevDeposit -
totalInterest;
}
function withdraw(
ILendingStorageManager.PoolStorage calldata _poolData,
address _pool,
bytes calldata,
uint256 _cTokenAmount,
address _recipient
)
external
override
returns (
uint256 totalInterest,
uint256 tokensOut,
uint256 tokensTransferred
)
{
// initialise compound interest token
ICompoundToken cToken = ICompoundToken(_poolData.interestBearingToken);
IERC20 collateralToken = IERC20(_poolData.collateral);
uint256 totalPrevDeposit;
// calculate accrued interest since last operation
(totalInterest, totalPrevDeposit) = calculateGeneratedInterest(
_pool,
_poolData,
_cTokenAmount,
cToken,
false
);
// get balances before redeeming
uint256 collBalanceBefore = collateralToken.balanceOf(address(this));
// redeem
require(cToken.redeem(_cTokenAmount) == 0, 'Failed withdraw');
// get balances after redeeming
uint256 collBalanceAfter = collateralToken.balanceOf(address(this));
// set return values
tokensOut =
totalPrevDeposit +
totalInterest -
cToken.balanceOfUnderlying(_pool);
tokensTransferred = collBalanceAfter - collBalanceBefore;
// transfer underlying
collateralToken.safeTransfer(_recipient, tokensTransferred);
}
function totalTransfer(
address _oldPool,
address _newPool,
address,
address _interestToken,
bytes calldata
)
external
override
returns (uint256 prevTotalCollateral, uint256 actualTotalCollateral)
{
uint256 prevTotalcTokens = SynthereumPoolMigrationFrom(_oldPool)
.migrateTotalFunds(_newPool);
Exp memory exchangeRate = Exp({
mantissa: ICompoundToken(_interestToken).exchangeRateCurrent()
});
prevTotalCollateral = mul_ScalarTruncate(exchangeRate, prevTotalcTokens);
actualTotalCollateral = ICompoundToken(_interestToken).balanceOfUnderlying(
_newPool
);
}
function claimRewards(
bytes calldata,
address,
address,
address
) external override {
revert('Claim rewards not supported');
}
function getUpdatedInterest(
address _poolAddress,
ILendingStorageManager.PoolStorage calldata _poolData,
bytes calldata
) external override returns (uint256 totalInterest) {
// instantiate cToken
ICompoundToken cToken = ICompoundToken(_poolData.interestBearingToken);
// calculate collateral
uint256 totCollateral = cToken.balanceOfUnderlying(_poolAddress);
totalInterest =
totCollateral -
_poolData.collateralDeposited -
_poolData.unclaimedDaoCommission -
_poolData.unclaimedDaoJRT;
}
function getAccumulatedInterest(
address _poolAddress,
ILendingStorageManager.PoolStorage calldata _poolData,
bytes calldata
) external view override returns (uint256 totalInterest) {
ICompoundToken cToken = ICompoundToken(_poolData.interestBearingToken);
(, uint256 tokenBalance, , uint256 excMantissa) = cToken.getAccountSnapshot(
_poolAddress
);
Exp memory exchangeRate = Exp({mantissa: excMantissa});
uint256 totCollateral = mul_ScalarTruncate(exchangeRate, tokenBalance);
totalInterest =
totCollateral -
_poolData.collateralDeposited -
_poolData.unclaimedDaoCommission -
_poolData.unclaimedDaoJRT;
}
function getInterestBearingToken(
address _collateral,
bytes calldata _extraArgs
) external view override returns (address token) {
IComptroller comptroller = IComptroller(abi.decode(_extraArgs, (address)));
address[] memory markets = comptroller.getAllMarkets();
for (uint256 i = 0; i < markets.length; i++) {
try ICompoundToken(markets[i]).underlying() returns (address coll) {
if (coll == _collateral) {
token = markets[i];
break;
}
} catch {}
}
require(token != address(0), 'Token not found');
}
function collateralToInterestToken(
uint256 _collateralAmount,
address,
address _interestToken,
bytes calldata
) external view override returns (uint256 interestTokenAmount) {
uint256 excMantissa = ICompoundToken(_interestToken).exchangeRateStored();
Exp memory exchangeRate = Exp({mantissa: excMantissa});
return div_(_collateralAmount, exchangeRate);
}
function interestTokenToCollateral(
uint256 _interestTokenAmount,
address,
address _interestToken,
bytes calldata
) external view override returns (uint256 collateralAmount) {
uint256 excMantissa = ICompoundToken(_interestToken).exchangeRateStored();
Exp memory exchangeRate = Exp({mantissa: excMantissa});
return mul_ScalarTruncate(exchangeRate, _interestTokenAmount);
}
function calculateGeneratedInterest(
address _poolAddress,
ILendingStorageManager.PoolStorage calldata _pool,
uint256 _cTokenAmount,
ICompoundToken _cToken,
bool _isDeposit
)
internal
returns (uint256 totalInterestGenerated, uint256 totalPrevDeposit)
{
// get cToken pool balance and rate
Exp memory exchangeRate = Exp({mantissa: _cToken.exchangeRateCurrent()});
uint256 cTokenBalancePool = _cToken.balanceOf(_poolAddress);
// determine amount of collateral the pool had before this operation
uint256 poolBalance = mul_ScalarTruncate(
exchangeRate,
_isDeposit ? cTokenBalancePool : cTokenBalancePool + _cTokenAmount
);
totalPrevDeposit =
_pool.collateralDeposited +
_pool.unclaimedDaoCommission +
_pool.unclaimedDaoJRT;
totalInterestGenerated = poolBalance - totalPrevDeposit;
}
}// SPDX-License-Identifier: AGPL-3.0-only
import {IERC20} from '../../../@openzeppelin/contracts/token/ERC20/IERC20.sol';
pragma solidity ^0.8.9;
interface ICompoundToken is IERC20 {
function mint(uint256) external returns (uint256);
function borrow(uint256) external returns (uint256);
function borrowBalanceCurrent(address account) external returns (uint256);
function repayBorrow(uint256) external returns (uint256);
function exchangeRateCurrent() external returns (uint256);
function supplyRatePerBlock() external returns (uint256);
function redeem(uint256) external returns (uint256);
function redeemUnderlying(uint256) external returns (uint256);
function balanceOfUnderlying(address owner) external returns (uint256);
function getAccountSnapshot(address account)
external
view
returns (
uint256,
uint256,
uint256,
uint256
);
function underlying() external view returns (address);
function getOwner() external view returns (address);
function exchangeRateStored() external view returns (uint256);
}
interface IComptroller {
function getAllMarkets() external view returns (address[] memory);
}// SPDX-License-Identifier: BSD-3-Clause
pragma solidity ^0.8.9;
/**
* @title Exponential module for storing fixed-precision decimals
* @author Compound
* @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.
* Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:
* `Exp({mantissa: 5100000000000000000})`.
*/
contract ExponentialNoError {
uint256 constant expScale = 1e18;
uint256 constant doubleScale = 1e36;
uint256 constant halfExpScale = expScale / 2;
uint256 constant mantissaOne = expScale;
struct Exp {
uint256 mantissa;
}
struct Double {
uint256 mantissa;
}
/**
* @dev Truncates the given exp to a whole number value.
* For example, truncate(Exp{mantissa: 15 * expScale}) = 15
*/
function truncate(Exp memory exp) internal pure returns (uint256) {
// Note: We are not using careful math here as we're performing a division that cannot fail
return exp.mantissa / expScale;
}
/**
* @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.
*/
function mul_ScalarTruncate(Exp memory a, uint256 scalar)
internal
pure
returns (uint256)
{
Exp memory product = mul_(a, scalar);
return truncate(product);
}
/**
* @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.
*/
function mul_ScalarTruncateAddUInt(
Exp memory a,
uint256 scalar,
uint256 addend
) internal pure returns (uint256) {
Exp memory product = mul_(a, scalar);
return add_(truncate(product), addend);
}
/**
* @dev Checks if first Exp is less than second Exp.
*/
function lessThanExp(Exp memory left, Exp memory right)
internal
pure
returns (bool)
{
return left.mantissa < right.mantissa;
}
/**
* @dev Checks if left Exp <= right Exp.
*/
function lessThanOrEqualExp(Exp memory left, Exp memory right)
internal
pure
returns (bool)
{
return left.mantissa <= right.mantissa;
}
/**
* @dev Checks if left Exp > right Exp.
*/
function greaterThanExp(Exp memory left, Exp memory right)
internal
pure
returns (bool)
{
return left.mantissa > right.mantissa;
}
/**
* @dev returns true if Exp is exactly zero
*/
function isZeroExp(Exp memory value) internal pure returns (bool) {
return value.mantissa == 0;
}
function safe224(uint256 n, string memory errorMessage)
internal
pure
returns (uint224)
{
require(n < 2**224, errorMessage);
return uint224(n);
}
function safe32(uint256 n, string memory errorMessage)
internal
pure
returns (uint32)
{
require(n < 2**32, errorMessage);
return uint32(n);
}
function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {
return Exp({mantissa: add_(a.mantissa, b.mantissa)});
}
function add_(Double memory a, Double memory b)
internal
pure
returns (Double memory)
{
return Double({mantissa: add_(a.mantissa, b.mantissa)});
}
function add_(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {
return Exp({mantissa: sub_(a.mantissa, b.mantissa)});
}
function sub_(Double memory a, Double memory b)
internal
pure
returns (Double memory)
{
return Double({mantissa: sub_(a.mantissa, b.mantissa)});
}
function sub_(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {
return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});
}
function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {
return Exp({mantissa: mul_(a.mantissa, b)});
}
function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {
return mul_(a, b.mantissa) / expScale;
}
function mul_(Double memory a, Double memory b)
internal
pure
returns (Double memory)
{
return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});
}
function mul_(Double memory a, uint256 b)
internal
pure
returns (Double memory)
{
return Double({mantissa: mul_(a.mantissa, b)});
}
function mul_(uint256 a, Double memory b) internal pure returns (uint256) {
return mul_(a, b.mantissa) / doubleScale;
}
function mul_(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {
return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});
}
function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {
return Exp({mantissa: div_(a.mantissa, b)});
}
function div_(uint256 a, Exp memory b) internal pure returns (uint256) {
return div_(mul_(a, expScale), b.mantissa);
}
function div_(Double memory a, Double memory b)
internal
pure
returns (Double memory)
{
return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});
}
function div_(Double memory a, uint256 b)
internal
pure
returns (Double memory)
{
return Double({mantissa: div_(a.mantissa, b)});
}
function div_(uint256 a, Double memory b) internal pure returns (uint256) {
return div_(mul_(a, doubleScale), b.mantissa);
}
function div_(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function fraction(uint256 a, uint256 b)
internal
pure
returns (Double memory)
{
return Double({mantissa: div_(mul_(a, doubleScale), b)});
}
}// SPDX-License-Identifier: agpl-3.0
pragma solidity >0.8.0;
/**
* @title IRewardsController
* @author Aave
* @notice Defines the basic interface for a Rewards Controller.
*/
interface IRewardsController {
/**
* @dev Claims all rewards for a user to the desired address, on all the assets of the pool, accumulating the pending rewards
* @param assets The list of assets to check eligible distributions before claiming rewards
* @param to The address that will be receiving the rewards
* @return rewardsList List of addresses of the reward tokens
* @return claimedAmounts List that contains the claimed amount per reward, following same order as "rewardList"
**/
function claimAllRewards(address[] calldata assets, address to)
external
returns (address[] memory rewardsList, uint256[] memory claimedAmounts);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.9;
import {IERC20} from '../../../@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {ILendingModule} from '../interfaces/ILendingModule.sol';
import {ILendingStorageManager} from '../interfaces/ILendingStorageManager.sol';
import {IPool} from '../interfaces/IAaveV3.sol';
import {IRewardsController} from '../interfaces/IRewardsController.sol';
import {Address} from '../../../@openzeppelin/contracts/utils/Address.sol';
import {SafeERC20} from '../../../@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import {PreciseUnitMath} from '../../base/utils/PreciseUnitMath.sol';
import {SynthereumPoolMigrationFrom} from '../../synthereum-pool/common/migration/PoolMigrationFrom.sol';
contract AaveV3Module is ILendingModule {
using SafeERC20 for IERC20;
function deposit(
ILendingStorageManager.PoolStorage calldata _poolData,
bytes calldata _lendingArgs,
uint256 _amount
)
external
override
returns (
uint256 totalInterest,
uint256 tokensOut,
uint256 tokensTransferred
)
{
// calculate accrued interest since last operation
(uint256 interest, uint256 poolBalance) = calculateGeneratedInterest(
msg.sender,
_poolData,
_amount,
true
);
// proxy should have received collateral from the pool
IERC20 collateral = IERC20(_poolData.collateral);
require(collateral.balanceOf(address(this)) >= _amount, 'Wrong balance');
// aave deposit - approve
(address moneyMarket, ) = abi.decode(_lendingArgs, (address, address));
collateral.safeIncreaseAllowance(moneyMarket, _amount);
IPool(moneyMarket).supply(
address(collateral),
_amount,
msg.sender,
uint16(0)
);
// aave tokens are usually 1:1 (but in some case there is dust-wei of rounding)
uint256 netDeposit = IERC20(_poolData.interestBearingToken).balanceOf(
msg.sender
) - poolBalance;
totalInterest = interest;
tokensOut = netDeposit;
tokensTransferred = netDeposit;
}
function withdraw(
ILendingStorageManager.PoolStorage calldata _poolData,
address _pool,
bytes calldata _lendingArgs,
uint256 _aTokensAmount,
address _recipient
)
external
override
returns (
uint256 totalInterest,
uint256 tokensOut,
uint256 tokensTransferred
)
{
// proxy should have received interest tokens from the pool
IERC20 interestToken = IERC20(_poolData.interestBearingToken);
uint256 withdrawAmount = PreciseUnitMath.min(
interestToken.balanceOf(address(this)),
_aTokensAmount + 1
);
// calculate accrued interest since last operation
(totalInterest, ) = calculateGeneratedInterest(
_pool,
_poolData,
_aTokensAmount,
false
);
uint256 initialBalance = IERC20(_poolData.collateral).balanceOf(_recipient);
// aave withdraw - approve
(address moneyMarket, ) = abi.decode(_lendingArgs, (address, address));
interestToken.safeIncreaseAllowance(moneyMarket, withdrawAmount);
IPool(moneyMarket).withdraw(
_poolData.collateral,
withdrawAmount,
_recipient
);
// aave tokens are usually 1:1 (but in some case there is dust-wei of rounding)
uint256 netWithdrawal = IERC20(_poolData.collateral).balanceOf(_recipient) -
initialBalance;
tokensOut = _aTokensAmount;
tokensTransferred = netWithdrawal;
}
function totalTransfer(
address _oldPool,
address _newPool,
address,
address _interestToken,
bytes calldata
)
external
returns (uint256 prevTotalCollateral, uint256 actualTotalCollateral)
{
prevTotalCollateral = SynthereumPoolMigrationFrom(_oldPool)
.migrateTotalFunds(_newPool);
actualTotalCollateral = IERC20(_interestToken).balanceOf(_newPool);
}
/**
* @notice Claim the rewards associated to the bearing tokens of the caller(pool)
* @param _lendingArgs encoded args needed by the specific implementation
* @param _bearingToken Address of the bearing token of the pool
* @param _recipient address to which send rewards
*/
function claimRewards(
bytes calldata _lendingArgs,
address,
address _bearingToken,
address _recipient
) external override {
(, address rewardsController) = abi.decode(
_lendingArgs,
(address, address)
);
address[] memory assets = new address[](1);
assets[0] = _bearingToken;
IRewardsController(rewardsController).claimAllRewards(assets, _recipient);
}
function getUpdatedInterest(
address _poolAddress,
ILendingStorageManager.PoolStorage calldata _poolData,
bytes calldata
) external view override returns (uint256 totalInterest) {
(totalInterest, ) = calculateGeneratedInterest(
_poolAddress,
_poolData,
0,
true
);
}
function getAccumulatedInterest(
address _poolAddress,
ILendingStorageManager.PoolStorage calldata _poolData,
bytes calldata
) external view override returns (uint256 totalInterest) {
(totalInterest, ) = calculateGeneratedInterest(
_poolAddress,
_poolData,
0,
true
);
}
function getInterestBearingToken(address _collateral, bytes calldata _args)
external
view
override
returns (address token)
{
(address moneyMarket, ) = abi.decode(_args, (address, address));
token = IPool(moneyMarket).getReserveData(_collateral).aTokenAddress;
require(token != address(0), 'Interest token not found');
}
function collateralToInterestToken(
uint256 _collateralAmount,
address,
address,
bytes calldata
) external pure override returns (uint256 interestTokenAmount) {
interestTokenAmount = _collateralAmount;
}
function interestTokenToCollateral(
uint256 _interestTokenAmount,
address,
address,
bytes calldata
) external pure override returns (uint256 collateralAmount) {
collateralAmount = _interestTokenAmount;
}
function calculateGeneratedInterest(
address _poolAddress,
ILendingStorageManager.PoolStorage calldata _pool,
uint256 _amount,
bool _isDeposit
)
internal
view
returns (uint256 totalInterestGenerated, uint256 poolBalance)
{
// get current pool total amount of collateral
poolBalance = IERC20(_pool.interestBearingToken).balanceOf(_poolAddress);
// the total interest is delta between current balance and lastBalance
totalInterestGenerated = _isDeposit
? poolBalance -
_pool.collateralDeposited -
_pool.unclaimedDaoCommission -
_pool.unclaimedDaoJRT
: poolBalance +
_amount -
_pool.collateralDeposited -
_pool.unclaimedDaoCommission -
_pool.unclaimedDaoJRT;
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
interface IPool {
struct ReserveConfigurationMap {
uint256 data;
}
struct ReserveData {
//stores the reserve configuration
ReserveConfigurationMap configuration;
//the liquidity index. Expressed in ray
uint128 liquidityIndex;
//the current supply rate. Expressed in ray
uint128 currentLiquidityRate;
//variable borrow index. Expressed in ray
uint128 variableBorrowIndex;
//the current variable borrow rate. Expressed in ray
uint128 currentVariableBorrowRate;
//the current stable borrow rate. Expressed in ray
uint128 currentStableBorrowRate;
//timestamp of last update
uint40 lastUpdateTimestamp;
//the id of the reserve. Represents the position in the list of the active reserves
uint16 id;
//aToken address
address aTokenAddress;
//stableDebtToken address
address stableDebtTokenAddress;
//variableDebtToken address
address variableDebtTokenAddress;
//address of the interest rate strategy
address interestRateStrategyAddress;
//the current treasury balance, scaled
uint128 accruedToTreasury;
//the outstanding unbacked aTokens minted through the bridging feature
uint128 unbacked;
//the outstanding debt borrowed against this asset in isolation mode
uint128 isolationModeTotalDebt;
}
/**
* @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User supplies 100 USDC and gets in return 100 aUSDC
* @param _asset The address of the underlying asset to supply
* @param _amount The amount to be supplied
* @param _onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param _referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function supply(
address _asset,
uint256 _amount,
address _onBehalfOf,
uint16 _referralCode
) external;
/**
* @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
* E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
* @param _asset The address of the underlying asset to withdraw
* @param _amount The underlying amount to be withdrawn
* - Send the value type(uint256).max in order to withdraw the whole aToken balance
* @param _to The address that will receive the underlying, same as msg.sender if the user
* wants to receive it on his own wallet, or a different address if the beneficiary is a
* different wallet
* @return The final amount withdrawn
**/
function withdraw(
address _asset,
uint256 _amount,
address _to
) external returns (uint256);
/**
* @notice Returns the state and configuration of the reserve
* @param _asset The address of the underlying asset of the reserve
* @return The state and configuration data of the reserve
**/
function getReserveData(address _asset)
external
view
returns (ReserveData memory);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.9;
import {ISynthereumFinder} from './interfaces/IFinder.sol';
import {AccessControlEnumerable} from '../../@openzeppelin/contracts/access/AccessControlEnumerable.sol';
/**
* @title Provides addresses of contracts implementing certain interfaces.
*/
contract SynthereumFinder is ISynthereumFinder, AccessControlEnumerable {
bytes32 public constant MAINTAINER_ROLE = keccak256('Maintainer');
//Describe role structure
struct Roles {
address admin;
address maintainer;
}
//----------------------------------------
// Storage
//----------------------------------------
mapping(bytes32 => address) public interfacesImplemented;
//----------------------------------------
// Events
//----------------------------------------
event InterfaceImplementationChanged(
bytes32 indexed interfaceName,
address indexed newImplementationAddress
);
//----------------------------------------
// Modifiers
//----------------------------------------
modifier onlyMaintainer() {
require(
hasRole(MAINTAINER_ROLE, msg.sender),
'Sender must be the maintainer'
);
_;
}
//----------------------------------------
// Constructors
//----------------------------------------
constructor(Roles memory roles) {
_setRoleAdmin(DEFAULT_ADMIN_ROLE, DEFAULT_ADMIN_ROLE);
_setRoleAdmin(MAINTAINER_ROLE, DEFAULT_ADMIN_ROLE);
_setupRole(DEFAULT_ADMIN_ROLE, roles.admin);
_setupRole(MAINTAINER_ROLE, roles.maintainer);
}
//----------------------------------------
// External view
//----------------------------------------
/**
* @notice Updates the address of the contract that implements `interfaceName`.
* @param interfaceName bytes32 of the interface name that is either changed or registered.
* @param implementationAddress address of the implementation contract.
*/
function changeImplementationAddress(
bytes32 interfaceName,
address implementationAddress
) external override onlyMaintainer {
interfacesImplemented[interfaceName] = implementationAddress;
emit InterfaceImplementationChanged(interfaceName, implementationAddress);
}
/**
* @notice Gets the address of the contract that implements the given `interfaceName`.
* @param interfaceName queried interface.
* @return implementationAddress Address of the defined interface.
*/
function getImplementationAddress(bytes32 interfaceName)
external
view
override
returns (address)
{
address implementationAddress = interfacesImplemented[interfaceName];
require(implementationAddress != address(0x0), 'Implementation not found');
return implementationAddress;
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract ISynthereumFinder","name":"_finder","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"_swapModule","type":"address"}],"name":"addSwapProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"getCollateralDeposited","outputs":[{"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collateral","type":"address"}],"name":"getCollateralSwapModule","outputs":[{"internalType":"address","name":"swapModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"getInterestBearingToken","outputs":[{"internalType":"address","name":"interestTokenAddr","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"getLendingData","outputs":[{"components":[{"internalType":"address","name":"collateralToken","type":"address"},{"internalType":"address","name":"interestToken","type":"address"}],"internalType":"struct ILendingStorageManager.PoolLendingStorage","name":"lendingStorage","type":"tuple"},{"components":[{"internalType":"address","name":"lendingModule","type":"address"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct ILendingStorageManager.LendingInfo","name":"lendingInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_id","type":"string"}],"name":"getLendingModule","outputs":[{"components":[{"internalType":"address","name":"lendingModule","type":"address"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct ILendingStorageManager.LendingInfo","name":"lendingInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"getPoolData","outputs":[{"components":[{"internalType":"bytes32","name":"lendingModuleId","type":"bytes32"},{"internalType":"uint256","name":"collateralDeposited","type":"uint256"},{"internalType":"uint256","name":"unclaimedDaoJRT","type":"uint256"},{"internalType":"uint256","name":"unclaimedDaoCommission","type":"uint256"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint64","name":"jrtBuybackShare","type":"uint64"},{"internalType":"address","name":"interestBearingToken","type":"address"},{"internalType":"uint64","name":"daoInterestShare","type":"uint64"}],"internalType":"struct ILendingStorageManager.PoolStorage","name":"poolData","type":"tuple"},{"components":[{"internalType":"address","name":"lendingModule","type":"address"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct ILendingStorageManager.LendingInfo","name":"lendingInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"getPoolStorage","outputs":[{"components":[{"internalType":"bytes32","name":"lendingModuleId","type":"bytes32"},{"internalType":"uint256","name":"collateralDeposited","type":"uint256"},{"internalType":"uint256","name":"unclaimedDaoJRT","type":"uint256"},{"internalType":"uint256","name":"unclaimedDaoCommission","type":"uint256"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint64","name":"jrtBuybackShare","type":"uint64"},{"internalType":"address","name":"interestBearingToken","type":"address"},{"internalType":"uint64","name":"daoInterestShare","type":"uint64"}],"internalType":"struct ILendingStorageManager.PoolStorage","name":"poolData","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"getShares","outputs":[{"internalType":"uint256","name":"jrtBuybackShare","type":"uint256"},{"internalType":"uint256","name":"daoInterestShare","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSwapModules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_newLendingID","type":"string"},{"internalType":"address","name":"_pool","type":"address"},{"internalType":"address","name":"_newInterestBearingToken","type":"address"}],"name":"migrateLendingModule","outputs":[{"components":[{"internalType":"bytes32","name":"lendingModuleId","type":"bytes32"},{"internalType":"uint256","name":"collateralDeposited","type":"uint256"},{"internalType":"uint256","name":"unclaimedDaoJRT","type":"uint256"},{"internalType":"uint256","name":"unclaimedDaoCommission","type":"uint256"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint64","name":"jrtBuybackShare","type":"uint64"},{"internalType":"address","name":"interestBearingToken","type":"address"},{"internalType":"uint64","name":"daoInterestShare","type":"uint64"}],"internalType":"struct ILendingStorageManager.PoolStorage","name":"","type":"tuple"},{"components":[{"internalType":"address","name":"lendingModule","type":"address"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct ILendingStorageManager.LendingInfo","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_oldPool","type":"address"},{"internalType":"address","name":"_newPool","type":"address"},{"internalType":"uint256","name":"_newCollateralDeposited","type":"uint256"}],"name":"migratePoolStorage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_swapModule","type":"address"}],"name":"removeSwapProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_id","type":"string"},{"components":[{"internalType":"address","name":"lendingModule","type":"address"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct ILendingStorageManager.LendingInfo","name":"_lendingInfo","type":"tuple"}],"name":"setLendingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_lendingID","type":"string"},{"internalType":"address","name":"_pool","type":"address"},{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"address","name":"_interestBearingToken","type":"address"},{"internalType":"uint64","name":"_daoInterestShare","type":"uint64"},{"internalType":"uint64","name":"_jrtBuybackShare","type":"uint64"}],"name":"setPoolStorage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"uint64","name":"_daoInterestShare","type":"uint64"},{"internalType":"uint64","name":"_jrtBuybackShare","type":"uint64"}],"name":"setShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"address","name":"_swapModule","type":"address"}],"name":"setSwapModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"uint256","name":"_collateralDeposited","type":"uint256"},{"internalType":"uint256","name":"_daoJRT","type":"uint256"},{"internalType":"uint256","name":"_daoInterest","type":"uint256"}],"name":"updateValues","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60a06040523480156200001157600080fd5b5060405162002c0938038062002c0983398101604081905262000034916200004b565b60016000556001600160a01b03166080526200007d565b6000602082840312156200005e57600080fd5b81516001600160a01b03811681146200007657600080fd5b9392505050565b608051612b38620000d1600039600081816103460152818161092301528181610c3f01528181610e9b0152818161118601528181611307015281816114b0015281816117120152611a540152612b386000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c80637d9d518b116100a2578063de3627c711610071578063de3627c714610279578063e8e673691461028c578063ee3b3269146102a1578063f04da65b146102b4578063ff3b9e78146102dc57600080fd5b80637d9d518b1461021f57806381d878c214610240578063a2be10bd14610253578063db456b621461026657600080fd5b806338f6c371116100e957806338f6c3711461019b57806339584cf8146101ae5780634d52cd82146101d957806359a8b9db146101ec5780636c924f2f1461020c57600080fd5b8063120b8e501461011b57806313d21cdf14610130578063215516231461015a5780632a6509ce1461017b575b600080fd5b61012e610129366004612282565b6102ef565b005b61014361013e3660046122bd565b610466565b6040516101519291906123c9565b60405180910390f35b61016d6101683660046122bd565b6105ee565b6040516101519291906123f4565b61018e61018936600461246c565b61072d565b60405161015191906124ad565b61012e6101a93660046124c0565b6108d5565b6101c16101bc3660046122bd565b610a44565b6040516001600160a01b039091168152602001610151565b6101c16101e73660046122bd565b610a9c565b6101ff6101fa3660046122bd565b610b42565b60405161015191906124f9565b61012e61021a36600461251f565b610bf1565b61023261022d3660046122bd565b610df9565b604051908152602001610151565b61012e61024e366004612564565b610e4d565b61012e6102613660046122bd565b611138565b61012e6102743660046122bd565b6112b9565b61012e6102873660046125a5565b611462565b6102946115ff565b6040516101519190612614565b6101436102af366004612661565b6116a7565b6102c76102c23660046122bd565b6119b0565b60408051928352602083019190915201610151565b61012e6102ea3660046126c8565b611a27565b6002600054141561031b5760405162461bcd60e51b815260040161031290612763565b60405180910390fd5b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063aafd5e409060240160206040518083038186803b15801561039057600080fd5b505afa1580156103a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c8919061279a565b6001600160a01b0316336001600160a01b0316146103f85760405162461bcd60e51b8152600401610312906127b7565b6001600160a01b038416600090815260056020526040902080546104495760405162461bcd60e51b8152602060048201526008602482015267109859081c1bdbdb60c21b6044820152606401610312565b600180820194909455600281019290925560039091015560005550565b61046e612226565b6040805180820190915260008152606060208201526001600160a01b03808416600090815260056020818152604092839020835161010081018552815480825260018301549382019390935260028201549481019490945260038101546060850152600481015480861660808601526001600160401b03600160a01b91829004811660a0870152919093015494851660c0850152919093041660e0820152925061052a5760405162461bcd60e51b8152600401610312906127dc565b8151600090815260016020818152604092839020835180850190945280546001600160a01b0316845291820180549184019161056590612807565b80601f016020809104026020016040519081016040528092919081815260200182805461059190612807565b80156105de5780601f106105b3576101008083540402835291602001916105de565b820191906000526020600020905b8154815290600101906020018083116105c157829003601f168201915b5050505050815250509050915091565b60408051808201909152600080825260208201526040805180820190915260008152606060208201526001600160a01b0383166000908152600560205260409020805461064d5760405162461bcd60e51b8152600401610312906127dc565b60048101546001600160a01b03908116845260058201548116602080860191909152825460009081526001808352604091829020825180840190935280549094168252830180549193928401916106a390612807565b80601f01602080910402602001604051908101604052809291908181526020018280546106cf90612807565b801561071c5780601f106106f15761010080835404028352916020019161071c565b820191906000526020600020905b8154815290600101906020018083116106ff57829003601f168201915b505050505081525050915050915091565b60408051808201909152600081526060602082015260008383604051602001610757929190612842565b60408051601f1981840301815291905280516020909101209050806107b85760405162461bcd60e51b81526020600482015260176024820152762bb937b7339036b7b23ab6329034b232b73a34b334b2b960491b6044820152606401610312565b600081815260016020818152604092839020835180850190945280546001600160a01b031684529182018054918401916107f190612807565b80601f016020809104026020016040519081016040528092919081815260200182805461081d90612807565b801561086a5780601f1061083f5761010080835404028352916020019161086a565b820191906000526020600020905b81548152906001019060200180831161084d57829003601f168201915b5050509190925250508151919350506001600160a01b03166108ce5760405162461bcd60e51b815260206004820152601c60248201527f4c656e64696e67206d6f64756c65206e6f7420737570706f72746564000000006044820152606401610312565b5092915050565b600260005414156108f85760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063aafd5e409060240160206040518083038186803b15801561096d57600080fd5b505afa158015610981573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a5919061279a565b6001600160a01b0316336001600160a01b0316146109d55760405162461bcd60e51b8152600401610312906127b7565b6109e0600282611cf1565b806109f257506001600160a01b038116155b610a0e5760405162461bcd60e51b815260040161031290612871565b6001600160a01b03918216600090815260046020526040812080546001600160a01b031916929093169190911790915560019055565b6001600160a01b038116600090815260056020526040812054610a795760405162461bcd60e51b8152600401610312906127dc565b506001600160a01b03908116600090815260056020819052604090912001541690565b6001600160a01b038082166000908152600460205260409020541680610b165760405162461bcd60e51b815260206004820152602960248201527f53776170206d6f64756c65206e6f7420616464656420666f72207468697320636044820152681bdb1b185d195c985b60ba1b6064820152608401610312565b610b21600282611cf1565b610b3d5760405162461bcd60e51b815260040161031290612871565b919050565b610b4a612226565b506001600160a01b03808216600090815260056020818152604092839020835161010081018552815480825260018301549382019390935260028201549481019490945260038101546060850152600481015480861660808601526001600160401b03600160a01b91829004811660a0870152919093015494851660c0850152919093041660e082015290610b3d5760405162461bcd60e51b8152600401610312906127dc565b60026000541415610c145760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063aafd5e409060240160206040518083038186803b158015610c8957600080fd5b505afa158015610c9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc1919061279a565b6001600160a01b0316336001600160a01b031614610cf15760405162461bcd60e51b8152600401610312906127b7565b6001600160a01b03831660009081526005602052604090208054610d425760405162461bcd60e51b8152602060048201526008602482015267109859081c1bdbdb60c21b6044820152606401610312565b670de0b6b3a7640000826001600160401b031611158015610d745750670de0b6b3a7640000836001600160401b031611155b610db05760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420736861726560981b6044820152606401610312565b6004810180546001600160401b03938416600160a01b90810267ffffffffffffffff60a01b19928316179092556005909201805494909316029216919091179055506001600055565b6001600160a01b038116600090815260056020526040812054610e2e5760405162461bcd60e51b8152600401610312906127dc565b506001600160a01b031660009081526005602052604090206001015490565b60026000541415610e705760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063aafd5e409060240160206040518083038186803b158015610ee557600080fd5b505afa158015610ef9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1d919061279a565b6001600160a01b0316336001600160a01b031614610f4d5760405162461bcd60e51b8152600401610312906127b7565b6001600160a01b03808416600090815260056020818152604092839020835161010081018552815480825260018301549382019390935260028201549481019490945260038101546060850152600481015480861660808601526001600160401b03600160a01b91829004811660a0870152919093015494851660c0850152919093041660e082015290806110195760405162461bcd60e51b8152602060048201526012602482015271109859081b5a59dc985d1a5bdb881c1bdbdb60721b6044820152606401610312565b6001600160a01b038416600090815260056020526040902080541561106f5760405162461bcd60e51b815260206004820152600c60248201526b109859081b995dc81c1bdbdb60a21b6044820152606401610312565b90815560808201516004808301805460c08601516005808701805460a08a01516001600160401b03908116600160a01b9081026001600160e01b03199788166001600160a01b039b8c16171790975560e08b015116909502948416928716929092179390931790556001808601979097556040808701516002808801919091556060909701516003968701559890931660009081526020829052978820888155808701899055948501889055928401879055830180548216905591018054909116905590915550565b6002600054141561115b5760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063aafd5e409060240160206040518083038186803b1580156111d057600080fd5b505afa1580156111e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611208919061279a565b6001600160a01b0316336001600160a01b0316146112385760405162461bcd60e51b8152600401610312906127b7565b6001600160a01b03811661128a5760405162461bcd60e51b81526020600482015260196024820152780a6eec2e040dadec8ead8ca40c6c2dc40dcdee840c4ca4060f603b1b6044820152606401610312565b611295600282611d18565b6112b15760405162461bcd60e51b815260040161031290612871565b506001600055565b600260005414156112dc5760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063aafd5e409060240160206040518083038186803b15801561135157600080fd5b505afa158015611365573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611389919061279a565b6001600160a01b0316336001600160a01b0316146113b95760405162461bcd60e51b8152600401610312906127b7565b6001600160a01b03811661140b5760405162461bcd60e51b81526020600482015260196024820152780a6eec2e040dadec8ead8ca40c6c2dc40dcdee840c4ca4060f603b1b6044820152606401610312565b611416600282611d2d565b6112b15760405162461bcd60e51b815260206004820152601d60248201527f53776170206d6f64756c6520616c726561647920737570706f727465640000006044820152606401610312565b600260005414156114855760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063aafd5e409060240160206040518083038186803b1580156114fa57600080fd5b505afa15801561150e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611532919061279a565b6001600160a01b0316336001600160a01b0316146115625760405162461bcd60e51b8152600401610312906127b7565b60008383604051602001611577929190612842565b60408051601f1981840301815291905280516020909101209050806115d85760405162461bcd60e51b81526020600482015260176024820152762bb937b7339036b7b23ab6329034b232b73a34b334b2b960491b6044820152606401610312565b600081815260016020526040902082906115f2828261290c565b5050600160005550505050565b6060600061160d6002611d42565b90506000816001600160401b03811115611629576116296128a8565b604051908082528060200260200182016040528015611652578160200160208202803683370190505b50905060005b828110156108ce5761166b600282611d4c565b82828151811061167d5761167d612a27565b6001600160a01b03909216602092830291909101909101528061169f81612a53565b915050611658565b6116af612226565b604080518082019091526000815260606020820152600260005414156116e75760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063aafd5e409060240160206040518083038186803b15801561175c57600080fd5b505afa158015611770573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611794919061279a565b6001600160a01b0316336001600160a01b0316146117c45760405162461bcd60e51b8152600401610312906127b7565b600086866040516020016117d9929190612842565b60408051601f1981840301815282825280516020918201206000818152600180845284822086860190955284546001600160a01b03168652840180549296509094939284019161182890612807565b80601f016020809104026020016040519081016040528092919081815260200182805461185490612807565b80156118a15780601f10611876576101008083540402835291602001916118a1565b820191906000526020600020905b81548152906001019060200180831161188457829003601f168201915b5050509190925250508151919250506001600160a01b0381166118f85760405162461bcd60e51b815260206004820152600f60248201526e1259081b9bdd08195e1a5cdd195b9d608a1b6044820152606401610312565b6001600160a01b0380881660009081526005602052604090208481556004810154909161192a9183911684868b611d58565b60408051610100810182528254815260018084015460208301526002840154928201929092526003830154606082015260048301546001600160a01b0380821660808401526001600160401b03600160a01b92839004811660a085015260059095015490811660c08401520490921660e083015260005599919850909650505050505050565b6001600160a01b03811660009081526005602052604081205481906119e75760405162461bcd60e51b8152600401610312906127dc565b50506001600160a01b0316600090815260056020819052604090912060048101549101546001600160401b03600160a01b92839004811693929091041690565b60026000541415611a4a5760405162461bcd60e51b815260040161031290612763565b6002600055611a787f0000000000000000000000000000000000000000000000000000000000000000611e77565b60008787604051602001611a8d929190612842565b60408051601f1981840301815282825280516020918201206000818152600180845284822086860190955284546001600160a01b031686528401805492965090949392840191611adc90612807565b80601f0160208091040260200160405190810160405280929190818152602001828054611b0890612807565b8015611b555780601f10611b2a57610100808354040283529160200191611b55565b820191906000526020600020905b815481529060010190602001808311611b3857829003601f168201915b5050509190925250508151919250506001600160a01b038116611bb15760405162461bcd60e51b8152602060048201526014602482015273135bd91d5b19481b9bdd081cdd5c1c1bdc9d195960621b6044820152606401610312565b670de0b6b3a7640000846001600160401b031611158015611be35750670de0b6b3a7640000856001600160401b031611155b611c1f5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420736861726560981b6044820152606401610312565b6001600160a01b0388166000908152600560205260409020805415611c7c5760405162461bcd60e51b8152602060048201526013602482015272506f6f6c20616c72656164792065786973747360681b6044820152606401610312565b8381556004810180546001600160a01b038a166001600160e01b031990911617600160a01b6001600160401b0388811682029290921790925560058301805467ffffffffffffffff60a01b1916918916909202179055611cdf818984868b611d58565b50506001600055505050505050505050565b6001600160a01b038116600090815260018301602052604081205415155b90505b92915050565b6000611d0f836001600160a01b038416611fcc565b6000611d0f836001600160a01b0384166120bf565b6000611d12825490565b6000611d0f838361210e565b602082015160405163959a6a8360e01b81526001600160a01b0385169163959a6a8391611d89918891600401612a6e565b60206040518083038186803b158015611da157600080fd5b505afa925050508015611dd1575060408051601f3d908101601f19168201909252611dce9181019061279a565b60015b611e4d576001600160a01b038116611e2b5760405162461bcd60e51b815260206004820152601760248201527f4e6f2062656172696e6720746f6b656e207061737365640000000000000000006044820152606401610312565b6005850180546001600160a01b0319166001600160a01b038316179055611e70565b6005860180546001600160a01b0319166001600160a01b03929092169190911790555b5050505050565b6040516302abf57960e61b815270466163746f727956657273696f6e696e6760781b60048201526000906001600160a01b0383169063aafd5e409060240160206040518083038186803b158015611ecd57600080fd5b505afa158015611ee1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f05919061279a565b604051636d2721a360e11b81526a506f6f6c466163746f727960a81b60048201529091506000906001600160a01b0383169063da4e43469060240160206040518083038186803b158015611f5857600080fd5b505afa158015611f6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f909190612a92565b9050611fab82826a506f6f6c466163746f727960a81b612138565b611fc75760405162461bcd60e51b8152600401610312906127b7565b505050565b600081815260018301602052604081205480156120b5576000611ff0600183612ab5565b855490915060009061200490600190612ab5565b905081811461206957600086600001828154811061202457612024612a27565b906000526020600020015490508087600001848154811061204757612047612a27565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061207a5761207a612acc565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611d12565b6000915050611d12565b600081815260018301602052604081205461210657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611d12565b506000611d12565b600082600001828154811061212557612125612a27565b9060005260206000200154905092915050565b60008060005b8460ff168260ff16101561221d57604051636839980160e11b81526004810185905260ff821660248201526001600160a01b0387169063d07330029060440160206040518083038186803b15801561219557600080fd5b505afa9250505080156121c5575060408051601f3d908101601f191682019092526121c29181019061279a565b60015b6121ce5761220b565b336001600160a01b03821614156121e957600193505061221d565b826121f381612ae2565b9350508560ff168360ff16141561220957600093505b505b8061221581612ae2565b91505061213e565b50509392505050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b6001600160a01b038116811461227f57600080fd5b50565b6000806000806080858703121561229857600080fd5b84356122a38161226a565b966020860135965060408601359560600135945092505050565b6000602082840312156122cf57600080fd5b81356122da8161226a565b9392505050565b80518252602081015160208301526040810151604083015260608101516060830152608081015160018060a01b03808216608085015260a083015191506001600160401b0380831660a08601528160c08501511660c08601528060e08501511660e08601525050505050565b6000815180845260005b8181101561237357602081850181015186830182015201612357565b81811115612385576000602083870101525b50601f01601f19169290920160200192915050565b60018060a01b03815116825260006020820151604060208501526123c1604085018261234d565b949350505050565b60006101206123d883866122e1565b806101008401526123eb8184018561239a565b95945050505050565b600060018060a01b0380855116835280602086015116602084015250606060408301526123c1606083018461239a565b60008083601f84011261243657600080fd5b5081356001600160401b0381111561244d57600080fd5b60208301915083602082850101111561246557600080fd5b9250929050565b6000806020838503121561247f57600080fd5b82356001600160401b0381111561249557600080fd5b6124a185828601612424565b90969095509350505050565b602081526000611d0f602083018461239a565b600080604083850312156124d357600080fd5b82356124de8161226a565b915060208301356124ee8161226a565b809150509250929050565b6101008101611d1282846122e1565b80356001600160401b0381168114610b3d57600080fd5b60008060006060848603121561253457600080fd5b833561253f8161226a565b925061254d60208501612508565b915061255b60408501612508565b90509250925092565b60008060006060848603121561257957600080fd5b83356125848161226a565b925060208401356125948161226a565b929592945050506040919091013590565b6000806000604084860312156125ba57600080fd5b83356001600160401b03808211156125d157600080fd5b6125dd87838801612424565b909550935060208601359150808211156125f657600080fd5b5084016040818703121561260957600080fd5b809150509250925092565b6020808252825182820181905260009190848201906040850190845b818110156126555783516001600160a01b031683529284019291840191600101612630565b50909695505050505050565b6000806000806060858703121561267757600080fd5b84356001600160401b0381111561268d57600080fd5b61269987828801612424565b90955093505060208501356126ad8161226a565b915060408501356126bd8161226a565b939692955090935050565b600080600080600080600060c0888a0312156126e357600080fd5b87356001600160401b038111156126f957600080fd5b6127058a828b01612424565b90985096505060208801356127198161226a565b945060408801356127298161226a565b935060608801356127398161226a565b925061274760808901612508565b915061275560a08901612508565b905092959891949750929550565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6000602082840312156127ac57600080fd5b81516122da8161226a565b6020808252600b908201526a139bdd08185b1b1bddd95960aa1b604082015260600190565b602080825260119082015270139bdd08195e1a5cdd1a5b99c81c1bdbdb607a1b604082015260600190565b600181811c9082168061281b57607f821691505b6020821081141561283c57634e487b7160e01b600052602260045260246000fd5b50919050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60208082526019908201527f53776170206d6f64756c65206e6f7420737570706f7274656400000000000000604082015260600190565b634e487b7160e01b600052604160045260246000fd5b601f821115611fc757600081815260208120601f850160051c810160208610156128e55750805b601f850160051c820191505b81811015612904578281556001016128f1565b505050505050565b81356129178161226a565b81546001600160a01b0319166001600160a01b0391909116178155600181810160208481013536869003601e1901811261295057600080fd5b850180356001600160401b0381111561296857600080fd5b803603838301131561297957600080fd5b61298d816129878654612807565b866128be565b6000601f8211600181146129c357600083156129ab57508382018501355b600019600385901b1c1916600184901b178655612a1c565b600086815260209020601f19841690835b828110156129f3578685018801358255938701939089019087016129d4565b5084821015612a125760001960f88660031b161c198785880101351681555b50508683881b0186555b505050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415612a6757612a67612a3d565b5060010190565b6001600160a01b03831681526040602082018190526000906123c19083018461234d565b600060208284031215612aa457600080fd5b815160ff811681146122da57600080fd5b600082821015612ac757612ac7612a3d565b500390565b634e487b7160e01b600052603160045260246000fd5b600060ff821660ff811415612af957612af9612a3d565b6001019291505056fea2646970667358221220ce9cd1fca3f4e7639d913ad732c8b643fbdb2df101004a298da09637b965ca2064736f6c6343000809003300000000000000000000000080d629cf2d775cb9b97c4a95fe2269e0e8459d3a
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101165760003560e01c80637d9d518b116100a2578063de3627c711610071578063de3627c714610279578063e8e673691461028c578063ee3b3269146102a1578063f04da65b146102b4578063ff3b9e78146102dc57600080fd5b80637d9d518b1461021f57806381d878c214610240578063a2be10bd14610253578063db456b621461026657600080fd5b806338f6c371116100e957806338f6c3711461019b57806339584cf8146101ae5780634d52cd82146101d957806359a8b9db146101ec5780636c924f2f1461020c57600080fd5b8063120b8e501461011b57806313d21cdf14610130578063215516231461015a5780632a6509ce1461017b575b600080fd5b61012e610129366004612282565b6102ef565b005b61014361013e3660046122bd565b610466565b6040516101519291906123c9565b60405180910390f35b61016d6101683660046122bd565b6105ee565b6040516101519291906123f4565b61018e61018936600461246c565b61072d565b60405161015191906124ad565b61012e6101a93660046124c0565b6108d5565b6101c16101bc3660046122bd565b610a44565b6040516001600160a01b039091168152602001610151565b6101c16101e73660046122bd565b610a9c565b6101ff6101fa3660046122bd565b610b42565b60405161015191906124f9565b61012e61021a36600461251f565b610bf1565b61023261022d3660046122bd565b610df9565b604051908152602001610151565b61012e61024e366004612564565b610e4d565b61012e6102613660046122bd565b611138565b61012e6102743660046122bd565b6112b9565b61012e6102873660046125a5565b611462565b6102946115ff565b6040516101519190612614565b6101436102af366004612661565b6116a7565b6102c76102c23660046122bd565b6119b0565b60408051928352602083019190915201610151565b61012e6102ea3660046126c8565b611a27565b6002600054141561031b5760405162461bcd60e51b815260040161031290612763565b60405180910390fd5b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000080d629cf2d775cb9b97c4a95fe2269e0e8459d3a6001600160a01b03169063aafd5e409060240160206040518083038186803b15801561039057600080fd5b505afa1580156103a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c8919061279a565b6001600160a01b0316336001600160a01b0316146103f85760405162461bcd60e51b8152600401610312906127b7565b6001600160a01b038416600090815260056020526040902080546104495760405162461bcd60e51b8152602060048201526008602482015267109859081c1bdbdb60c21b6044820152606401610312565b600180820194909455600281019290925560039091015560005550565b61046e612226565b6040805180820190915260008152606060208201526001600160a01b03808416600090815260056020818152604092839020835161010081018552815480825260018301549382019390935260028201549481019490945260038101546060850152600481015480861660808601526001600160401b03600160a01b91829004811660a0870152919093015494851660c0850152919093041660e0820152925061052a5760405162461bcd60e51b8152600401610312906127dc565b8151600090815260016020818152604092839020835180850190945280546001600160a01b0316845291820180549184019161056590612807565b80601f016020809104026020016040519081016040528092919081815260200182805461059190612807565b80156105de5780601f106105b3576101008083540402835291602001916105de565b820191906000526020600020905b8154815290600101906020018083116105c157829003601f168201915b5050505050815250509050915091565b60408051808201909152600080825260208201526040805180820190915260008152606060208201526001600160a01b0383166000908152600560205260409020805461064d5760405162461bcd60e51b8152600401610312906127dc565b60048101546001600160a01b03908116845260058201548116602080860191909152825460009081526001808352604091829020825180840190935280549094168252830180549193928401916106a390612807565b80601f01602080910402602001604051908101604052809291908181526020018280546106cf90612807565b801561071c5780601f106106f15761010080835404028352916020019161071c565b820191906000526020600020905b8154815290600101906020018083116106ff57829003601f168201915b505050505081525050915050915091565b60408051808201909152600081526060602082015260008383604051602001610757929190612842565b60408051601f1981840301815291905280516020909101209050806107b85760405162461bcd60e51b81526020600482015260176024820152762bb937b7339036b7b23ab6329034b232b73a34b334b2b960491b6044820152606401610312565b600081815260016020818152604092839020835180850190945280546001600160a01b031684529182018054918401916107f190612807565b80601f016020809104026020016040519081016040528092919081815260200182805461081d90612807565b801561086a5780601f1061083f5761010080835404028352916020019161086a565b820191906000526020600020905b81548152906001019060200180831161084d57829003601f168201915b5050509190925250508151919350506001600160a01b03166108ce5760405162461bcd60e51b815260206004820152601c60248201527f4c656e64696e67206d6f64756c65206e6f7420737570706f72746564000000006044820152606401610312565b5092915050565b600260005414156108f85760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000080d629cf2d775cb9b97c4a95fe2269e0e8459d3a6001600160a01b03169063aafd5e409060240160206040518083038186803b15801561096d57600080fd5b505afa158015610981573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a5919061279a565b6001600160a01b0316336001600160a01b0316146109d55760405162461bcd60e51b8152600401610312906127b7565b6109e0600282611cf1565b806109f257506001600160a01b038116155b610a0e5760405162461bcd60e51b815260040161031290612871565b6001600160a01b03918216600090815260046020526040812080546001600160a01b031916929093169190911790915560019055565b6001600160a01b038116600090815260056020526040812054610a795760405162461bcd60e51b8152600401610312906127dc565b506001600160a01b03908116600090815260056020819052604090912001541690565b6001600160a01b038082166000908152600460205260409020541680610b165760405162461bcd60e51b815260206004820152602960248201527f53776170206d6f64756c65206e6f7420616464656420666f72207468697320636044820152681bdb1b185d195c985b60ba1b6064820152608401610312565b610b21600282611cf1565b610b3d5760405162461bcd60e51b815260040161031290612871565b919050565b610b4a612226565b506001600160a01b03808216600090815260056020818152604092839020835161010081018552815480825260018301549382019390935260028201549481019490945260038101546060850152600481015480861660808601526001600160401b03600160a01b91829004811660a0870152919093015494851660c0850152919093041660e082015290610b3d5760405162461bcd60e51b8152600401610312906127dc565b60026000541415610c145760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000080d629cf2d775cb9b97c4a95fe2269e0e8459d3a6001600160a01b03169063aafd5e409060240160206040518083038186803b158015610c8957600080fd5b505afa158015610c9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc1919061279a565b6001600160a01b0316336001600160a01b031614610cf15760405162461bcd60e51b8152600401610312906127b7565b6001600160a01b03831660009081526005602052604090208054610d425760405162461bcd60e51b8152602060048201526008602482015267109859081c1bdbdb60c21b6044820152606401610312565b670de0b6b3a7640000826001600160401b031611158015610d745750670de0b6b3a7640000836001600160401b031611155b610db05760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420736861726560981b6044820152606401610312565b6004810180546001600160401b03938416600160a01b90810267ffffffffffffffff60a01b19928316179092556005909201805494909316029216919091179055506001600055565b6001600160a01b038116600090815260056020526040812054610e2e5760405162461bcd60e51b8152600401610312906127dc565b506001600160a01b031660009081526005602052604090206001015490565b60026000541415610e705760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000080d629cf2d775cb9b97c4a95fe2269e0e8459d3a6001600160a01b03169063aafd5e409060240160206040518083038186803b158015610ee557600080fd5b505afa158015610ef9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1d919061279a565b6001600160a01b0316336001600160a01b031614610f4d5760405162461bcd60e51b8152600401610312906127b7565b6001600160a01b03808416600090815260056020818152604092839020835161010081018552815480825260018301549382019390935260028201549481019490945260038101546060850152600481015480861660808601526001600160401b03600160a01b91829004811660a0870152919093015494851660c0850152919093041660e082015290806110195760405162461bcd60e51b8152602060048201526012602482015271109859081b5a59dc985d1a5bdb881c1bdbdb60721b6044820152606401610312565b6001600160a01b038416600090815260056020526040902080541561106f5760405162461bcd60e51b815260206004820152600c60248201526b109859081b995dc81c1bdbdb60a21b6044820152606401610312565b90815560808201516004808301805460c08601516005808701805460a08a01516001600160401b03908116600160a01b9081026001600160e01b03199788166001600160a01b039b8c16171790975560e08b015116909502948416928716929092179390931790556001808601979097556040808701516002808801919091556060909701516003968701559890931660009081526020829052978820888155808701899055948501889055928401879055830180548216905591018054909116905590915550565b6002600054141561115b5760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000080d629cf2d775cb9b97c4a95fe2269e0e8459d3a6001600160a01b03169063aafd5e409060240160206040518083038186803b1580156111d057600080fd5b505afa1580156111e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611208919061279a565b6001600160a01b0316336001600160a01b0316146112385760405162461bcd60e51b8152600401610312906127b7565b6001600160a01b03811661128a5760405162461bcd60e51b81526020600482015260196024820152780a6eec2e040dadec8ead8ca40c6c2dc40dcdee840c4ca4060f603b1b6044820152606401610312565b611295600282611d18565b6112b15760405162461bcd60e51b815260040161031290612871565b506001600055565b600260005414156112dc5760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000080d629cf2d775cb9b97c4a95fe2269e0e8459d3a6001600160a01b03169063aafd5e409060240160206040518083038186803b15801561135157600080fd5b505afa158015611365573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611389919061279a565b6001600160a01b0316336001600160a01b0316146113b95760405162461bcd60e51b8152600401610312906127b7565b6001600160a01b03811661140b5760405162461bcd60e51b81526020600482015260196024820152780a6eec2e040dadec8ead8ca40c6c2dc40dcdee840c4ca4060f603b1b6044820152606401610312565b611416600282611d2d565b6112b15760405162461bcd60e51b815260206004820152601d60248201527f53776170206d6f64756c6520616c726561647920737570706f727465640000006044820152606401610312565b600260005414156114855760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000080d629cf2d775cb9b97c4a95fe2269e0e8459d3a6001600160a01b03169063aafd5e409060240160206040518083038186803b1580156114fa57600080fd5b505afa15801561150e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611532919061279a565b6001600160a01b0316336001600160a01b0316146115625760405162461bcd60e51b8152600401610312906127b7565b60008383604051602001611577929190612842565b60408051601f1981840301815291905280516020909101209050806115d85760405162461bcd60e51b81526020600482015260176024820152762bb937b7339036b7b23ab6329034b232b73a34b334b2b960491b6044820152606401610312565b600081815260016020526040902082906115f2828261290c565b5050600160005550505050565b6060600061160d6002611d42565b90506000816001600160401b03811115611629576116296128a8565b604051908082528060200260200182016040528015611652578160200160208202803683370190505b50905060005b828110156108ce5761166b600282611d4c565b82828151811061167d5761167d612a27565b6001600160a01b03909216602092830291909101909101528061169f81612a53565b915050611658565b6116af612226565b604080518082019091526000815260606020820152600260005414156116e75760405162461bcd60e51b815260040161031290612763565b60026000556040516302abf57960e61b81526d2632b73234b733a6b0b730b3b2b960911b60048201527f00000000000000000000000080d629cf2d775cb9b97c4a95fe2269e0e8459d3a6001600160a01b03169063aafd5e409060240160206040518083038186803b15801561175c57600080fd5b505afa158015611770573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611794919061279a565b6001600160a01b0316336001600160a01b0316146117c45760405162461bcd60e51b8152600401610312906127b7565b600086866040516020016117d9929190612842565b60408051601f1981840301815282825280516020918201206000818152600180845284822086860190955284546001600160a01b03168652840180549296509094939284019161182890612807565b80601f016020809104026020016040519081016040528092919081815260200182805461185490612807565b80156118a15780601f10611876576101008083540402835291602001916118a1565b820191906000526020600020905b81548152906001019060200180831161188457829003601f168201915b5050509190925250508151919250506001600160a01b0381166118f85760405162461bcd60e51b815260206004820152600f60248201526e1259081b9bdd08195e1a5cdd195b9d608a1b6044820152606401610312565b6001600160a01b0380881660009081526005602052604090208481556004810154909161192a9183911684868b611d58565b60408051610100810182528254815260018084015460208301526002840154928201929092526003830154606082015260048301546001600160a01b0380821660808401526001600160401b03600160a01b92839004811660a085015260059095015490811660c08401520490921660e083015260005599919850909650505050505050565b6001600160a01b03811660009081526005602052604081205481906119e75760405162461bcd60e51b8152600401610312906127dc565b50506001600160a01b0316600090815260056020819052604090912060048101549101546001600160401b03600160a01b92839004811693929091041690565b60026000541415611a4a5760405162461bcd60e51b815260040161031290612763565b6002600055611a787f00000000000000000000000080d629cf2d775cb9b97c4a95fe2269e0e8459d3a611e77565b60008787604051602001611a8d929190612842565b60408051601f1981840301815282825280516020918201206000818152600180845284822086860190955284546001600160a01b031686528401805492965090949392840191611adc90612807565b80601f0160208091040260200160405190810160405280929190818152602001828054611b0890612807565b8015611b555780601f10611b2a57610100808354040283529160200191611b55565b820191906000526020600020905b815481529060010190602001808311611b3857829003601f168201915b5050509190925250508151919250506001600160a01b038116611bb15760405162461bcd60e51b8152602060048201526014602482015273135bd91d5b19481b9bdd081cdd5c1c1bdc9d195960621b6044820152606401610312565b670de0b6b3a7640000846001600160401b031611158015611be35750670de0b6b3a7640000856001600160401b031611155b611c1f5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420736861726560981b6044820152606401610312565b6001600160a01b0388166000908152600560205260409020805415611c7c5760405162461bcd60e51b8152602060048201526013602482015272506f6f6c20616c72656164792065786973747360681b6044820152606401610312565b8381556004810180546001600160a01b038a166001600160e01b031990911617600160a01b6001600160401b0388811682029290921790925560058301805467ffffffffffffffff60a01b1916918916909202179055611cdf818984868b611d58565b50506001600055505050505050505050565b6001600160a01b038116600090815260018301602052604081205415155b90505b92915050565b6000611d0f836001600160a01b038416611fcc565b6000611d0f836001600160a01b0384166120bf565b6000611d12825490565b6000611d0f838361210e565b602082015160405163959a6a8360e01b81526001600160a01b0385169163959a6a8391611d89918891600401612a6e565b60206040518083038186803b158015611da157600080fd5b505afa925050508015611dd1575060408051601f3d908101601f19168201909252611dce9181019061279a565b60015b611e4d576001600160a01b038116611e2b5760405162461bcd60e51b815260206004820152601760248201527f4e6f2062656172696e6720746f6b656e207061737365640000000000000000006044820152606401610312565b6005850180546001600160a01b0319166001600160a01b038316179055611e70565b6005860180546001600160a01b0319166001600160a01b03929092169190911790555b5050505050565b6040516302abf57960e61b815270466163746f727956657273696f6e696e6760781b60048201526000906001600160a01b0383169063aafd5e409060240160206040518083038186803b158015611ecd57600080fd5b505afa158015611ee1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f05919061279a565b604051636d2721a360e11b81526a506f6f6c466163746f727960a81b60048201529091506000906001600160a01b0383169063da4e43469060240160206040518083038186803b158015611f5857600080fd5b505afa158015611f6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f909190612a92565b9050611fab82826a506f6f6c466163746f727960a81b612138565b611fc75760405162461bcd60e51b8152600401610312906127b7565b505050565b600081815260018301602052604081205480156120b5576000611ff0600183612ab5565b855490915060009061200490600190612ab5565b905081811461206957600086600001828154811061202457612024612a27565b906000526020600020015490508087600001848154811061204757612047612a27565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061207a5761207a612acc565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611d12565b6000915050611d12565b600081815260018301602052604081205461210657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611d12565b506000611d12565b600082600001828154811061212557612125612a27565b9060005260206000200154905092915050565b60008060005b8460ff168260ff16101561221d57604051636839980160e11b81526004810185905260ff821660248201526001600160a01b0387169063d07330029060440160206040518083038186803b15801561219557600080fd5b505afa9250505080156121c5575060408051601f3d908101601f191682019092526121c29181019061279a565b60015b6121ce5761220b565b336001600160a01b03821614156121e957600193505061221d565b826121f381612ae2565b9350508560ff168360ff16141561220957600093505b505b8061221581612ae2565b91505061213e565b50509392505050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b6001600160a01b038116811461227f57600080fd5b50565b6000806000806080858703121561229857600080fd5b84356122a38161226a565b966020860135965060408601359560600135945092505050565b6000602082840312156122cf57600080fd5b81356122da8161226a565b9392505050565b80518252602081015160208301526040810151604083015260608101516060830152608081015160018060a01b03808216608085015260a083015191506001600160401b0380831660a08601528160c08501511660c08601528060e08501511660e08601525050505050565b6000815180845260005b8181101561237357602081850181015186830182015201612357565b81811115612385576000602083870101525b50601f01601f19169290920160200192915050565b60018060a01b03815116825260006020820151604060208501526123c1604085018261234d565b949350505050565b60006101206123d883866122e1565b806101008401526123eb8184018561239a565b95945050505050565b600060018060a01b0380855116835280602086015116602084015250606060408301526123c1606083018461239a565b60008083601f84011261243657600080fd5b5081356001600160401b0381111561244d57600080fd5b60208301915083602082850101111561246557600080fd5b9250929050565b6000806020838503121561247f57600080fd5b82356001600160401b0381111561249557600080fd5b6124a185828601612424565b90969095509350505050565b602081526000611d0f602083018461239a565b600080604083850312156124d357600080fd5b82356124de8161226a565b915060208301356124ee8161226a565b809150509250929050565b6101008101611d1282846122e1565b80356001600160401b0381168114610b3d57600080fd5b60008060006060848603121561253457600080fd5b833561253f8161226a565b925061254d60208501612508565b915061255b60408501612508565b90509250925092565b60008060006060848603121561257957600080fd5b83356125848161226a565b925060208401356125948161226a565b929592945050506040919091013590565b6000806000604084860312156125ba57600080fd5b83356001600160401b03808211156125d157600080fd5b6125dd87838801612424565b909550935060208601359150808211156125f657600080fd5b5084016040818703121561260957600080fd5b809150509250925092565b6020808252825182820181905260009190848201906040850190845b818110156126555783516001600160a01b031683529284019291840191600101612630565b50909695505050505050565b6000806000806060858703121561267757600080fd5b84356001600160401b0381111561268d57600080fd5b61269987828801612424565b90955093505060208501356126ad8161226a565b915060408501356126bd8161226a565b939692955090935050565b600080600080600080600060c0888a0312156126e357600080fd5b87356001600160401b038111156126f957600080fd5b6127058a828b01612424565b90985096505060208801356127198161226a565b945060408801356127298161226a565b935060608801356127398161226a565b925061274760808901612508565b915061275560a08901612508565b905092959891949750929550565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6000602082840312156127ac57600080fd5b81516122da8161226a565b6020808252600b908201526a139bdd08185b1b1bddd95960aa1b604082015260600190565b602080825260119082015270139bdd08195e1a5cdd1a5b99c81c1bdbdb607a1b604082015260600190565b600181811c9082168061281b57607f821691505b6020821081141561283c57634e487b7160e01b600052602260045260246000fd5b50919050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60208082526019908201527f53776170206d6f64756c65206e6f7420737570706f7274656400000000000000604082015260600190565b634e487b7160e01b600052604160045260246000fd5b601f821115611fc757600081815260208120601f850160051c810160208610156128e55750805b601f850160051c820191505b81811015612904578281556001016128f1565b505050505050565b81356129178161226a565b81546001600160a01b0319166001600160a01b0391909116178155600181810160208481013536869003601e1901811261295057600080fd5b850180356001600160401b0381111561296857600080fd5b803603838301131561297957600080fd5b61298d816129878654612807565b866128be565b6000601f8211600181146129c357600083156129ab57508382018501355b600019600385901b1c1916600184901b178655612a1c565b600086815260209020601f19841690835b828110156129f3578685018801358255938701939089019087016129d4565b5084821015612a125760001960f88660031b161c198785880101351681555b50508683881b0186555b505050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415612a6757612a67612a3d565b5060010190565b6001600160a01b03831681526040602082018190526000906123c19083018461234d565b600060208284031215612aa457600080fd5b815160ff811681146122da57600080fd5b600082821015612ac757612ac7612a3d565b500390565b634e487b7160e01b600052603160045260246000fd5b600060ff821660ff811415612af957612af9612a3d565b6001019291505056fea2646970667358221220ce9cd1fca3f4e7639d913ad732c8b643fbdb2df101004a298da09637b965ca2064736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000080d629cf2d775cb9b97c4a95fe2269e0e8459d3a
-----Decoded View---------------
Arg [0] : _finder (address): 0x80d629cf2D775cB9b97c4A95Fe2269e0E8459d3A
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000080d629cf2d775cb9b97c4a95fe2269e0e8459d3a
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in XDAI
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.