Skip to content

Commit e27196d

Browse files
committed
first commit, just a set of solidity contracts for study
1 parent ccc68a4 commit e27196d

10 files changed

+708
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

FeeCollectorV3PositionTimeLockV1.sol

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >=0.8.20;
3+
pragma abicoder v2;
4+
5+
6+
import "@openzeppelin/contracts/access/Ownable.sol";
7+
// import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol" as TH;
8+
import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
9+
// import "@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol";
10+
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
11+
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
12+
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
13+
// import "@openzeppelin/[email protected]/interfaces/IERC4626.sol";
14+
// import "@openzeppelin/contracts/utils/math/SafeMath.sol";
15+
16+
17+
18+
library TransferHelper {
19+
/// @notice Transfers tokens from the targeted address to the given destination
20+
/// @notice Errors with 'STF' if transfer fails
21+
/// @param token The contract address of the token to be transferred
22+
/// @param from The originating address from which the tokens will be transferred
23+
/// @param to The destination address of the transfer
24+
/// @param value The amount to be transferred
25+
function safeTransferFrom(
26+
address token,
27+
address from,
28+
address to,
29+
uint256 value
30+
) internal {
31+
(bool success, bytes memory data) =
32+
token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
33+
require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');
34+
}
35+
36+
/// @notice Transfers tokens from msg.sender to a recipient
37+
/// @dev Errors with ST if transfer fails
38+
/// @param token The contract address of the token which will be transferred
39+
/// @param to The recipient of the transfer
40+
/// @param value The value of the transfer
41+
function safeTransfer(
42+
address token,
43+
address to,
44+
uint256 value
45+
) internal {
46+
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
47+
require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');
48+
}
49+
50+
/// @notice Approves the stipulated contract to spend the given allowance in the given token
51+
/// @dev Errors with 'SA' if transfer fails
52+
/// @param token The contract address of the token to be approved
53+
/// @param to The target of the approval
54+
/// @param value The amount of the given token the target will be allowed to spend
55+
function safeApprove(
56+
address token,
57+
address to,
58+
uint256 value
59+
) internal {
60+
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));
61+
require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');
62+
}
63+
64+
/// @notice Transfers ETH to the recipient address
65+
/// @dev Fails with `STE`
66+
/// @param to The destination of the transfer
67+
/// @param value The value to be transferred
68+
function safeTransferETH(address to, uint256 value) internal {
69+
(bool success, ) = to.call{value: value}(new bytes(0));
70+
require(success, 'STE');
71+
}
72+
}
73+
74+
75+
interface INonfungiblePositionManager {
76+
77+
function positions(uint256 tokenId)
78+
external
79+
view
80+
returns (
81+
uint96 nonce,
82+
address operator,
83+
address token0,
84+
address token1,
85+
uint24 fee,
86+
int24 tickLower,
87+
int24 tickUpper,
88+
uint128 liquidity,
89+
uint256 feeGrowthInside0LastX128,
90+
uint256 feeGrowthInside1LastX128,
91+
uint128 tokensOwed0,
92+
uint128 tokensOwed1
93+
);
94+
95+
struct CollectParams {
96+
uint256 tokenId;
97+
address recipient;
98+
uint128 amount0Max;
99+
uint128 amount1Max;
100+
}
101+
102+
function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);
103+
104+
function transferFrom(address from, address to, uint256 tokenId) external;
105+
function safeTransferFrom(address from, address to, uint256 tokenId) external;
106+
}
107+
108+
contract FeeCollectorV3PositionTimeLockV1 is IERC721Receiver, Ownable, ReentrancyGuard {
109+
uint256 public defaultLockDuration = 7 days;
110+
111+
struct LockedPosition {
112+
INonfungiblePositionManager positionManager;
113+
address positionOwner;
114+
uint256 tokenId;
115+
uint256 releaseTime;
116+
}
117+
118+
// mapping(address => mapping(address => uint256)) public userLockedPositionsTokenId;
119+
mapping(address => mapping(bytes32 => LockedPosition)) public lockedPositions;
120+
121+
// INonfungiblePositionManager public positionManager;
122+
123+
constructor(address initialOwner) Ownable(initialOwner) {}
124+
125+
event FeesCollected(address indexed user, address indexed positionManager, uint256 tokenId, uint256 amount0, uint256 amount1);
126+
event PositionLocked(address indexed user, address indexed positionManager, uint256 tokenId, uint256 releaseTime);
127+
event PositionUnlocked(address indexed user, address indexed positionManager, uint256 tokenId);
128+
129+
function onERC721Received(
130+
address _operator,
131+
address _from,
132+
uint256 _tokenId,
133+
bytes calldata _data) external pure override returns (bytes4) {
134+
// require(address(whitelistedNftContract) == _msgSender());
135+
// _stakeNft(tokenId, from);
136+
return IERC721Receiver.onERC721Received.selector;
137+
}
138+
139+
140+
function _hashLockedPositionKey(address _positionManager, uint256 tokenId) private view returns(bytes32) {
141+
return keccak256(abi.encodePacked(_msgSender(), _positionManager, tokenId));
142+
}
143+
144+
function collectFees(address _positionManager, uint256 tokenId, address recipient) external nonReentrant returns (uint256 amount0Collected, uint256 amount1Collected) {
145+
LockedPosition storage lockedPosition = lockedPositions[_msgSender()][_hashLockedPositionKey(_positionManager, tokenId)];
146+
require(lockedPosition.positionOwner == _msgSender(), "failed to load position");
147+
148+
INonfungiblePositionManager positionManager = lockedPosition.positionManager;
149+
INonfungiblePositionManager.CollectParams memory params = INonfungiblePositionManager.CollectParams({
150+
tokenId: lockedPosition.tokenId,
151+
recipient: recipient,
152+
amount0Max: type(uint128).max,
153+
amount1Max: type(uint128).max
154+
});
155+
156+
(amount0Collected, amount1Collected) = positionManager.collect(params);
157+
emit FeesCollected(_msgSender(), _positionManager, tokenId, amount0Collected, amount1Collected);
158+
159+
return(amount0Collected, amount1Collected);
160+
}
161+
162+
function lockPosition(address _positionManager, uint256 tokenId, uint256 lockDurationInSeconds) external {
163+
uint256 _duration = lockDurationInSeconds;
164+
if(lockDurationInSeconds == 0) {
165+
_duration = defaultLockDuration;
166+
}
167+
// LockedPosition storage lockedposition = lockedPositions[_msgSender()][_hashLockedPositionKey(_positionManager, tokenId)];
168+
// require(lockedposition.tokenId != 0, "failed position already locked");
169+
uint256 releaseTime = (block.timestamp + (_duration));
170+
require(releaseTime > block.timestamp, "Release time must be in the future");
171+
172+
INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);
173+
positionManager.safeTransferFrom(_msgSender(), address(this), tokenId);
174+
175+
lockedPositions[_msgSender()][_hashLockedPositionKey(_positionManager, tokenId)] = LockedPosition(positionManager, _msgSender(), tokenId, releaseTime);
176+
177+
emit PositionLocked(_msgSender(), _positionManager, tokenId, releaseTime);
178+
}
179+
180+
function unlockPosition(address _positionManager, uint256 tokenId) external {
181+
LockedPosition storage lockedPosition = lockedPositions[_msgSender()][_hashLockedPositionKey(_positionManager, tokenId)];
182+
require(lockedPosition.positionOwner == _msgSender(), "failed to load position, not Owner");
183+
require(block.timestamp >= lockedPosition.releaseTime, "not in time to unlock");
184+
185+
INonfungiblePositionManager positionManager = lockedPosition.positionManager;
186+
positionManager.safeTransferFrom(address(this), _msgSender(), tokenId);
187+
188+
delete lockedPositions[_msgSender()][_hashLockedPositionKey(_positionManager, tokenId)];
189+
}
190+
191+
192+
}

MyUSD.sol

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.20;
4+
5+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
6+
7+
contract MyUSD is ERC20 {
8+
constructor() ERC20("MyUSD", "MUSD") {
9+
_mint(msg.sender, 1000000 * (10 ** decimals()));
10+
}
11+
}

NFTV3FeeCollector.sol

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >=0.8.20;
3+
pragma abicoder v2;
4+
5+
6+
import "@openzeppelin/contracts/access/Ownable.sol";
7+
// import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol" as TH;
8+
import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
9+
// import "@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol";
10+
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
11+
// import "@openzeppelin/[email protected]/interfaces/IERC4626.sol";
12+
// import "@openzeppelin/contracts/utils/math/SafeMath.sol";
13+
14+
15+
16+
library TransferHelper {
17+
/// @notice Transfers tokens from the targeted address to the given destination
18+
/// @notice Errors with 'STF' if transfer fails
19+
/// @param token The contract address of the token to be transferred
20+
/// @param from The originating address from which the tokens will be transferred
21+
/// @param to The destination address of the transfer
22+
/// @param value The amount to be transferred
23+
function safeTransferFrom(
24+
address token,
25+
address from,
26+
address to,
27+
uint256 value
28+
) internal {
29+
(bool success, bytes memory data) =
30+
token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
31+
require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');
32+
}
33+
34+
/// @notice Transfers tokens from msg.sender to a recipient
35+
/// @dev Errors with ST if transfer fails
36+
/// @param token The contract address of the token which will be transferred
37+
/// @param to The recipient of the transfer
38+
/// @param value The value of the transfer
39+
function safeTransfer(
40+
address token,
41+
address to,
42+
uint256 value
43+
) internal {
44+
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
45+
require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');
46+
}
47+
48+
/// @notice Approves the stipulated contract to spend the given allowance in the given token
49+
/// @dev Errors with 'SA' if transfer fails
50+
/// @param token The contract address of the token to be approved
51+
/// @param to The target of the approval
52+
/// @param value The amount of the given token the target will be allowed to spend
53+
function safeApprove(
54+
address token,
55+
address to,
56+
uint256 value
57+
) internal {
58+
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));
59+
require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');
60+
}
61+
62+
/// @notice Transfers ETH to the recipient address
63+
/// @dev Fails with `STE`
64+
/// @param to The destination of the transfer
65+
/// @param value The value to be transferred
66+
function safeTransferETH(address to, uint256 value) internal {
67+
(bool success, ) = to.call{value: value}(new bytes(0));
68+
require(success, 'STE');
69+
}
70+
}
71+
72+
73+
interface INonfungiblePositionManager {
74+
75+
function positions(uint256 tokenId)
76+
external
77+
view
78+
returns (
79+
uint96 nonce,
80+
address operator,
81+
address token0,
82+
address token1,
83+
uint24 fee,
84+
int24 tickLower,
85+
int24 tickUpper,
86+
uint128 liquidity,
87+
uint256 feeGrowthInside0LastX128,
88+
uint256 feeGrowthInside1LastX128,
89+
uint128 tokensOwed0,
90+
uint128 tokensOwed1
91+
);
92+
93+
struct CollectParams {
94+
uint256 tokenId;
95+
address recipient;
96+
uint128 amount0Max;
97+
uint128 amount1Max;
98+
}
99+
100+
function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);
101+
}
102+
103+
contract NFTV3FeeCollector is Ownable {
104+
105+
// event NewRevenueDistribution(uint256 totalRevenueTokens, uint256 totalAmountOutToken, uint256 totalTokenInVault, uint256 totalTotalSupply, uint256 totalToTreasury, uint256 totalToVault);
106+
107+
address payable private _treasury;
108+
INonfungiblePositionManager public positionManager;
109+
110+
constructor(address initialOwner, address _positionManager)
111+
Ownable(initialOwner)
112+
{
113+
positionManager = INonfungiblePositionManager(_positionManager);
114+
}
115+
116+
function collectFees(uint256 tokenId, address recipient) public onlyOwner returns (uint256 amount0Collected, uint256 amount1Collected) {
117+
// Criando os parâmetros de coleta
118+
INonfungiblePositionManager.CollectParams memory params = INonfungiblePositionManager.CollectParams({
119+
tokenId: tokenId,
120+
recipient: recipient,
121+
amount0Max: type(uint128).max, // Coletar o máximo possível de token0
122+
amount1Max: type(uint128).max // Coletar o máximo possível de token1
123+
});
124+
125+
// Chamando a função collect para retirar as taxas
126+
(amount0Collected, amount1Collected) = positionManager.collect(params);
127+
}
128+
129+
130+
}

0 commit comments

Comments
 (0)