-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
43bae3e
commit a7af2d6
Showing
7 changed files
with
822 additions
and
0 deletions.
There are no files selected for viewing
129 changes: 129 additions & 0 deletions
129
...derCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Factory.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
// Contracts | ||
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; | ||
|
||
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; | ||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
|
||
// Interfaces | ||
import "../../../interfaces/ITellerV2.sol"; | ||
import "../../../interfaces/IProtocolFee.sol"; | ||
import "../../../interfaces/ITellerV2Storage.sol"; | ||
import "../../../libraries/NumbersLib.sol"; | ||
|
||
import {IUniswapPricingLibrary} from "../../../interfaces/IUniswapPricingLibrary.sol"; | ||
|
||
import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol"; | ||
|
||
import { ILenderCommitmentGroup } from "../../../interfaces/ILenderCommitmentGroup.sol"; | ||
|
||
contract LenderCommitmentGroupFactory is OwnableUpgradeable { | ||
using AddressUpgradeable for address; | ||
using NumbersLib for uint256; | ||
|
||
|
||
//this is the beacon proxy | ||
address public lenderGroupBeacon; | ||
|
||
|
||
mapping(address => uint256) public deployedLenderGroupContracts; | ||
|
||
event DeployedLenderGroupContract(address indexed groupContract); | ||
|
||
|
||
|
||
function initialize(address _lenderGroupBeacon ) | ||
external | ||
initializer | ||
{ | ||
lenderGroupBeacon = _lenderGroupBeacon; | ||
__Ownable_init_unchained(); | ||
} | ||
|
||
|
||
/* | ||
This should deploy a new lender commitment group pool contract. | ||
It will use create commitment args in order to define the pool contracts parameters such as its primary principal token. | ||
Shares will be distributed at a 1:1 ratio of the primary principal token so if 1e18 raw WETH are deposited, the depositor gets 1e18 shares for the group pool. | ||
*/ | ||
function deployLenderCommitmentGroupPool( | ||
uint256 _initialPrincipalAmount, | ||
ILenderCommitmentGroup.CommitmentGroupConfig calldata _commitmentGroupConfig, | ||
IUniswapPricingLibrary.PoolRouteConfig[] calldata _poolOracleRoutes | ||
) external returns (address newGroupContract_) { | ||
|
||
|
||
|
||
BeaconProxy newGroupContract_ = new BeaconProxy( | ||
lenderGroupBeacon, | ||
abi.encodeWithSelector( | ||
ILenderCommitmentGroup.initialize.selector, //this initializes | ||
_commitmentGroupConfig, | ||
_poolOracleRoutes | ||
|
||
) | ||
); | ||
|
||
deployedLenderGroupContracts[address(newGroupContract_)] = block.number; //consider changing this ? | ||
emit DeployedLenderGroupContract(address(newGroupContract_)); | ||
|
||
|
||
|
||
//it is not absolutely necessary to have this call here but it allows the user to potentially save a tx step so it is nice to have . | ||
if (_initialPrincipalAmount > 0) { | ||
//should pull in the creators initial committed principal tokens . | ||
|
||
//send the initial principal tokens to _newgroupcontract here ! | ||
// so it will have them for addPrincipalToCommitmentGroup which will pull them from here | ||
|
||
_addPrincipalToCommitmentGroup( | ||
address(newGroupContract_), | ||
_initialPrincipalAmount, | ||
_commitmentGroupConfig.principalTokenAddress | ||
|
||
); | ||
|
||
|
||
} | ||
|
||
|
||
//transfer ownership to msg.sender | ||
OwnableUpgradeable(address(newGroupContract_)) | ||
.transferOwnership(msg.sender); | ||
} | ||
|
||
|
||
|
||
function _addPrincipalToCommitmentGroup( | ||
address _newGroupContract, | ||
uint256 _initialPrincipalAmount, | ||
address _principalTokenAddress | ||
) internal { | ||
|
||
|
||
IERC20(_principalTokenAddress).transferFrom( | ||
msg.sender, | ||
address(this), | ||
_initialPrincipalAmount | ||
); | ||
IERC20(_principalTokenAddress).approve( | ||
_newGroupContract, | ||
_initialPrincipalAmount | ||
); | ||
|
||
address sharesRecipient = msg.sender; | ||
|
||
uint256 sharesAmount_ = ILenderCommitmentGroup(address(_newGroupContract)) | ||
.addPrincipalToCommitmentGroup( | ||
_initialPrincipalAmount, | ||
sharesRecipient, | ||
0 //_minShares | ||
); | ||
|
||
|
||
} | ||
|
||
} |
147 changes: 147 additions & 0 deletions
147
packages/contracts/contracts/oracleprotection/HypernativeOracle.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; | ||
|
||
contract HypernativeOracle is AccessControl { | ||
struct OracleRecord { | ||
uint256 registrationTime; | ||
bool isPotentialRisk; | ||
} | ||
|
||
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); | ||
bytes32 public constant CONSUMER_ROLE = keccak256("CONSUMER_ROLE"); | ||
uint256 internal threshold = 2 minutes; | ||
|
||
mapping(bytes32 /*hashedAccount*/ => OracleRecord) internal accountHashToRecord; | ||
|
||
event ConsumerAdded(address consumer); | ||
event ConsumerRemoved(address consumer); | ||
event Registered(address consumer, address account); | ||
event Whitelisted(bytes32[] hashedAccounts); | ||
event Allowed(bytes32[] hashedAccounts); | ||
event Blacklisted(bytes32[] hashedAccounts); | ||
event TimeThresholdChanged(uint256 threshold); | ||
|
||
modifier onlyAdmin() { | ||
require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Hypernative Oracle error: admin required"); | ||
_; | ||
} | ||
|
||
modifier onlyOperator() { | ||
require(hasRole(OPERATOR_ROLE, msg.sender), "Hypernative Oracle error: operator required"); | ||
_; | ||
} | ||
|
||
modifier onlyConsumer { | ||
require(hasRole(CONSUMER_ROLE, msg.sender), "Hypernative Oracle error: consumer required"); | ||
_; | ||
} | ||
|
||
constructor(address _admin) { | ||
_grantRole(DEFAULT_ADMIN_ROLE, _admin); | ||
} | ||
|
||
function register(address _account) external onlyConsumer() { | ||
bytes32 _hashedAccount = keccak256(abi.encodePacked(_account, address(this))); | ||
require(accountHashToRecord[_hashedAccount].registrationTime == 0, "Account already registered"); | ||
accountHashToRecord[_hashedAccount].registrationTime = block.timestamp; | ||
emit Registered(msg.sender, _account); | ||
} | ||
|
||
function registerStrict(address _account) external onlyConsumer() { | ||
bytes32 _hashedAccount = keccak256(abi.encodePacked(_account, address(this))); | ||
require(accountHashToRecord[_hashedAccount].registrationTime == 0, "Account already registered"); | ||
accountHashToRecord[_hashedAccount].registrationTime = block.timestamp; | ||
accountHashToRecord[_hashedAccount].isPotentialRisk = true; | ||
emit Registered(msg.sender, _account); | ||
} | ||
|
||
// ** | ||
// * @dev Operator only function, can be used to whitelist accounts in order to pre-approve them | ||
// * @param hashedAccounts array of hashed accounts | ||
// */ | ||
function whitelist(bytes32[] calldata hashedAccounts) public onlyOperator() { | ||
for (uint256 i; i < hashedAccounts.length; i++) { | ||
accountHashToRecord[hashedAccounts[i]].registrationTime = 1; | ||
accountHashToRecord[hashedAccounts[i]].isPotentialRisk = false; | ||
} | ||
emit Whitelisted(hashedAccounts); | ||
} | ||
|
||
// ** | ||
// * @dev Operator only function, can be used to blacklist accounts in order to prevent them from interacting with the protocol | ||
// * @param hashedAccounts array of hashed accounts | ||
// */ | ||
function blacklist(bytes32[] calldata hashedAccounts) public onlyOperator() { | ||
for (uint256 i; i < hashedAccounts.length; i++) { | ||
accountHashToRecord[hashedAccounts[i]].isPotentialRisk = true; | ||
} | ||
emit Blacklisted(hashedAccounts); | ||
} | ||
|
||
// ** | ||
// * @dev Operator only function, when strict mode is being used, this function can be used to allow accounts to interact with the protocol | ||
// * @param hashedAccounts array of hashed accounts | ||
// */ | ||
function allow(bytes32[] calldata hashedAccounts) public onlyOperator() { | ||
for (uint256 i; i < hashedAccounts.length; i++) { | ||
accountHashToRecord[hashedAccounts[i]].isPotentialRisk = false; | ||
} | ||
emit Allowed(hashedAccounts); | ||
} | ||
|
||
/** | ||
* @dev Admin only function, can be used to block any interaction with the protocol, meassured in seconds | ||
*/ | ||
function changeTimeThreshold(uint256 _newThreshold) public onlyAdmin() { | ||
require(_newThreshold >= 2 minutes, "Threshold must be greater than 2 minutes"); | ||
threshold = _newThreshold; | ||
emit TimeThresholdChanged(threshold); | ||
} | ||
|
||
function addConsumers(address[] memory consumers) public onlyAdmin() { | ||
for (uint256 i; i < consumers.length; i++) { | ||
_grantRole(CONSUMER_ROLE, consumers[i]); | ||
emit ConsumerAdded(consumers[i]); | ||
} | ||
} | ||
|
||
function revokeConsumers(address[] memory consumers) public onlyAdmin() { | ||
for (uint256 i; i < consumers.length; i++) { | ||
_revokeRole(CONSUMER_ROLE, consumers[i]); | ||
emit ConsumerRemoved(consumers[i]); | ||
} | ||
} | ||
|
||
function addOperator(address operator) public onlyAdmin() { | ||
_grantRole(OPERATOR_ROLE, operator); | ||
} | ||
|
||
function revokeOperator(address operator) public onlyAdmin() { | ||
_revokeRole(OPERATOR_ROLE, operator); | ||
} | ||
|
||
function changeAdmin(address _newAdmin) public onlyAdmin() { | ||
_grantRole(DEFAULT_ADMIN_ROLE, _newAdmin); | ||
_revokeRole(DEFAULT_ADMIN_ROLE, msg.sender); | ||
} | ||
|
||
//if true, the account has been registered for two minutes | ||
function isTimeExceeded(address account) external onlyConsumer() view returns (bool) { | ||
bytes32 hashedAccount = keccak256(abi.encodePacked(account, address(this))); | ||
require(accountHashToRecord[hashedAccount].registrationTime != 0, "Account not registered"); | ||
return block.timestamp - accountHashToRecord[hashedAccount].registrationTime > threshold; | ||
} | ||
|
||
function isBlacklistedContext(address _origin, address _sender) external onlyConsumer() view returns (bool) { | ||
bytes32 hashedOrigin = keccak256(abi.encodePacked(_origin, address(this))); | ||
bytes32 hashedSender = keccak256(abi.encodePacked(_sender, address(this))); | ||
return accountHashToRecord[hashedOrigin].isPotentialRisk || accountHashToRecord[hashedSender].isPotentialRisk; | ||
} | ||
|
||
function isBlacklistedAccount(address _account) external onlyConsumer() view returns (bool) { | ||
bytes32 hashedAccount = keccak256(abi.encodePacked(_account, address(this))); | ||
return accountHashToRecord[hashedAccount].isPotentialRisk; | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
packages/contracts/contracts/oracleprotection/OracleProtectedChild.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {IOracleProtectionManager} from "../interfaces/oracleprotection/IOracleProtectionManager.sol"; | ||
|
||
abstract contract OracleProtectedChild { | ||
address public immutable ORACLE_MANAGER; | ||
|
||
|
||
modifier onlyOracleApproved() { | ||
|
||
IOracleProtectionManager oracleManager = IOracleProtectionManager(ORACLE_MANAGER); | ||
require( oracleManager .isOracleApproved(msg.sender ) , "Oracle: Not Approved"); | ||
_; | ||
} | ||
|
||
modifier onlyOracleApprovedAllowEOA() { | ||
|
||
IOracleProtectionManager oracleManager = IOracleProtectionManager(ORACLE_MANAGER); | ||
require( oracleManager .isOracleApprovedAllowEOA(msg.sender ) , "Oracle: Not Approved"); | ||
_; | ||
} | ||
|
||
constructor(address oracleManager){ | ||
ORACLE_MANAGER = oracleManager; | ||
} | ||
|
||
} |
Oops, something went wrong.