-
Notifications
You must be signed in to change notification settings - Fork 2
/
PositionFactory.sol
79 lines (63 loc) · 2.95 KB
/
PositionFactory.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;
// Local
import { Position } from "src/Position.sol";
import { Ownable } from "src/dependencies/access/Ownable.sol";
import { SafeTransferLib, ERC20 } from "solmate/utils/SafeTransferLib.sol";
import { IPositionFactory } from "src/interfaces/IPositionFactory.sol";
import { IERC20 } from "src/interfaces/token/IERC20.sol";
/// @title The position factory contract
/// @author Chain Rule, LLC
/// @notice Creates user position contracts and stores their addresses for all users
contract PositionFactory is Ownable, IPositionFactory {
// Constants: no SLOAD to save gas
address private constant CONTRACT_DEPLOYER = 0x0a5B347509621337cDDf44CBCf6B6E7C9C908CD2;
// Factory Storage
/// @inheritdoc IPositionFactory
mapping(address => mapping(address => mapping(address => mapping(address => address)))) public positions;
/// @notice A mapping of all positions owned by a user.
mapping(address => address[]) public positionsLookup;
// Errors
error Unauthorized();
error PositionExists();
// Events
/// @notice An event emitted when a position contract is created.
/// @param owner The owner of the created Position contract.
/// @param position The address of the created Position contract.
event PositionCreated(address indexed owner, address indexed position);
/// @notice This function is called when the PositionFactory is deployed.
/// @param _owner The account address of the PositionFactory contract's owner.
constructor(address _owner) Ownable(_owner) {
if (msg.sender != CONTRACT_DEPLOYER) revert Unauthorized();
}
/// @inheritdoc IPositionFactory
function createPosition(address _cToken, address _dToken, address _bToken)
public
payable
returns (address position)
{
if (positions[msg.sender][_cToken][_dToken][_bToken] != address(0)) revert PositionExists();
position = address(new Position(msg.sender, _cToken, _dToken, _bToken));
positionsLookup[msg.sender].push(position);
positions[msg.sender][_cToken][_dToken][_bToken] = position;
emit PositionCreated(msg.sender, position);
}
/// @inheritdoc IPositionFactory
function getPositions(address _positionOwner) public view returns (address[] memory) {
return positionsLookup[_positionOwner];
}
/* ****************************************************************************
**
** ADMIN FUNCTIONS
**
******************************************************************************/
/// @inheritdoc IPositionFactory
function extractNative() public payable onlyOwner {
payable(msg.sender).transfer(address(this).balance);
}
/// @inheritdoc IPositionFactory
function extractERC20(address _token) public payable onlyOwner {
uint256 balance = IERC20(_token).balanceOf(address(this));
SafeTransferLib.safeTransfer(ERC20(_token), msg.sender, balance);
}
}