Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

immutable withdraw + split #428

Merged
merged 20 commits into from
Mar 13, 2025
Merged

immutable withdraw + split #428

merged 20 commits into from
Mar 13, 2025

Conversation

YouStillAlive
Copy link
Member

closes #393

@YouStillAlive YouStillAlive marked this pull request as draft March 6, 2025 09:59
Copy link

github-actions bot commented Mar 6, 2025

Slither report

THIS CHECKLIST IS NOT COMPLETE. Use --show-ignored-findings to show all the results.
Summary

incorrect-equality

Impact: Medium
Confidence: High

function _withdraw(
uint256 poolId,
uint256 amount
) internal override firewallProtectedSig(0x9e2bf22c) returns (uint256 withdrawnAmount, bool isFinal) {
if (amount == 0) return (0, false);
isFinal = true;
withdrawnAmount = amount;
uint256[] memory params = provider.getParams(poolId);
uint256 remainingAmount = params[0] - amount;
if (remainingAmount > 0 && lastPoolOwner[poolId] != address(0)) {
// create immutable NFT
uint256 newPoolId = lockDealNFT.mintForProvider(
lastPoolOwner[poolId],
lockDealNFT.poolIdToProvider(poolId)
);
// clone vault id
lockDealNFT.cloneVaultId(newPoolId, poolId);
// register new pool
params[0] = remainingAmount;
provider.registerPool(newPoolId, params);
poolIdToTime[newPoolId] = poolIdToTime[poolId];
poolIdToAmount[newPoolId] = poolIdToAmount[poolId];
delete lastPoolOwner[poolId];
}
// Reset and update the original pool
params[0] = 0;
provider.registerPool(poolId, params);
}

uninitialized-local

Impact: Medium
Confidence: Medium

unused-return

Impact: Medium
Confidence: Medium

function mintAndTransfer(
address owner,
address token,
uint256 amount,
IProvider provider
)
external
firewallProtected
onlyApprovedContract(address(provider))
notZeroAddress(owner)
notZeroAddress(token)
notZeroAmount(amount)
returns (uint256 poolId)
{
poolId = _mint(owner, provider);
IERC20(token).approve(address(vaultManager), amount);
poolIdToVaultId[poolId] = vaultManager.depositByToken(token, amount);
}

calls-loop

Impact: Low
Confidence: Medium

function _getData(uint256 poolId) internal view returns (BasePoolInfo memory poolInfo) {
IProvider provider = poolIdToProvider[poolId];
poolInfo = BasePoolInfo(
provider,
provider.name(),
poolId,
poolIdToVaultId[poolId],
ownerOf(poolId),
tokenOf(poolId),
provider.getParams(poolId)
);
}

function tokenOf(uint256 poolId) public view returns (address token) {
token = vaultManager.vaultIdToTokenAddress(poolIdToVaultId[poolId]);
}

timestamp

Impact: Low
Confidence: Medium

function _withdraw(
uint256 poolId,
uint256 amount
) internal override firewallProtectedSig(0x9e2bf22c) returns (uint256 withdrawnAmount, bool isFinal) {
if (amount == 0) return (0, false);
isFinal = true;
withdrawnAmount = amount;
uint256[] memory params = provider.getParams(poolId);
uint256 remainingAmount = params[0] - amount;
if (remainingAmount > 0 && lastPoolOwner[poolId] != address(0)) {
// create immutable NFT
uint256 newPoolId = lockDealNFT.mintForProvider(
lastPoolOwner[poolId],
lockDealNFT.poolIdToProvider(poolId)
);
// clone vault id
lockDealNFT.cloneVaultId(newPoolId, poolId);
// register new pool
params[0] = remainingAmount;
provider.registerPool(newPoolId, params);
poolIdToTime[newPoolId] = poolIdToTime[poolId];
poolIdToAmount[newPoolId] = poolIdToAmount[poolId];
delete lastPoolOwner[poolId];
}
// Reset and update the original pool
params[0] = 0;
provider.registerPool(poolId, params);
}

function getWithdrawableAmount(uint256 poolId) public view override returns (uint256) {
uint256[] memory params = getParams(poolId);
uint256 leftAmount = params[0];
uint256 startTime = params[1];
uint256 finishTime = params[2];
uint256 startAmount = params[3];
if (block.timestamp < startTime) return 0;
if (finishTime <= block.timestamp) return leftAmount;
uint256 totalPoolDuration = finishTime - startTime;
uint256 timePassed = block.timestamp - startTime;
uint256 debitableAmount = (startAmount * timePassed) / totalPoolDuration;
return debitableAmount - (startAmount - leftAmount);
}

function _update(
address to,
uint256 poolId,
address auth
) internal override firewallProtectedSig(0x30e0789e) returns (address from) {
if (auth != address(0) && ERC165Checker.supportsInterface(address(poolIdToProvider[poolId]), type(IBeforeTransfer).interfaceId)) {
IBeforeTransfer(address(poolIdToProvider[poolId])).beforeTransfer(auth, to, poolId);
}
// check for split and withdraw transfers
if (auth != address(0) && !(approvedContracts[to] || approvedContracts[auth])) {
require(approvedPoolUserTransfers[auth], "Pool transfer not approved by user");
require(
vaultManager.vaultIdToTradeStartTime(poolIdToVaultId[poolId]) < block.timestamp,
"Can't transfer before trade start time"
);
}
from = super._update(to, poolId, auth);
}

function getWithdrawableAmount(uint256 poolId) public view override returns (uint256) {
return poolIdToTime[poolId] <= block.timestamp ? provider.getWithdrawableAmount(poolId) : 0;
}

dead-code

Impact: Informational
Confidence: Medium

function _validProvider(uint256 poolId, IProvider provider) internal view {
require(lockDealNFT.poolIdToProvider(poolId) == provider, "Invalid provider poolId");
}

function _validProviderInterface(IProvider provider, bytes4 interfaceId) internal view {
require(ERC165Checker.supportsInterface(address(provider), interfaceId), "invalid provider type");
}

function _withdraw(
uint256 poolId,
uint256 amount
) internal virtual returns (uint256 withdrawnAmount, bool isFinal) {}

naming-convention

Impact: Informational
Confidence: High

https://github.com/The-Poolz/LockDealNFT/blob/6b9f53fbfda372a2e19f436c766404a0d23ec0ab/node_modules/@poolzfinance/poolz-helper-v2/contracts/token/ERC20Token.sol#L22-L24

https://github.com/The-Poolz/LockDealNFT/blob/6b9f53fbfda372a2e19f436c766404a0d23ec0ab/node_modules/@poolzfinance/poolz-helper-v2/contracts/Array.sol#L11

https://github.com/The-Poolz/LockDealNFT/blob/6b9f53fbfda372a2e19f436c766404a0d23ec0ab/node_modules/@poolzfinance/poolz-helper-v2/contracts/Array.sol#L25

https://github.com/The-Poolz/LockDealNFT/blob/6b9f53fbfda372a2e19f436c766404a0d23ec0ab/node_modules/@poolzfinance/poolz-helper-v2/contracts/Array.sol#L81

https://github.com/The-Poolz/LockDealNFT/blob/6b9f53fbfda372a2e19f436c766404a0d23ec0ab/node_modules/@poolzfinance/poolz-helper-v2/contracts/Array.sol#L81

https://github.com/The-Poolz/LockDealNFT/blob/6b9f53fbfda372a2e19f436c766404a0d23ec0ab/node_modules/@poolzfinance/poolz-helper-v2/contracts/Array.sol#L25-L37

https://github.com/The-Poolz/LockDealNFT/blob/6b9f53fbfda372a2e19f436c766404a0d23ec0ab/node_modules/@poolzfinance/poolz-helper-v2/contracts/Array.sol#L11-L23

https://github.com/The-Poolz/LockDealNFT/blob/6b9f53fbfda372a2e19f436c766404a0d23ec0ab/node_modules/@poolzfinance/poolz-helper-v2/contracts/Array.sol#L25

https://github.com/The-Poolz/LockDealNFT/blob/6b9f53fbfda372a2e19f436c766404a0d23ec0ab/node_modules/@poolzfinance/poolz-helper-v2/contracts/Array.sol#L70

https://github.com/The-Poolz/LockDealNFT/blob/6b9f53fbfda372a2e19f436c766404a0d23ec0ab/node_modules/@poolzfinance/poolz-helper-v2/contracts/Array.sol#L11

https://github.com/The-Poolz/LockDealNFT/blob/6b9f53fbfda372a2e19f436c766404a0d23ec0ab/node_modules/@poolzfinance/poolz-helper-v2/contracts/Array.sol#L57

https://github.com/The-Poolz/LockDealNFT/blob/6b9f53fbfda372a2e19f436c766404a0d23ec0ab/node_modules/@poolzfinance/poolz-helper-v2/contracts/Array.sol#L40

https://github.com/The-Poolz/LockDealNFT/blob/6b9f53fbfda372a2e19f436c766404a0d23ec0ab/node_modules/@poolzfinance/poolz-helper-v2/contracts/Array.sol#L70

immutable-states

Impact: Optimization
Confidence: High

IVaultManager public vaultManager;

@YouStillAlive YouStillAlive changed the title immutable withdraw immutable withdraw + split Mar 6, 2025
Copy link

github-actions bot commented Mar 7, 2025

Methods

Symbol Meaning
Execution gas for this method does not include intrinsic gas overhead
Cost was non-zero but below the precision setting for the currency display (see options)
Min Max Avg Calls usd avg
DealProvider
       createNewPool(address[],uint256[],bytes) 258,262 289,062 269,821 66 0.78
ERC20Token
       approve(address,uint256) - - 45,928 1 0.13
LockDealNFT
       approvePoolTransfers(bool) 22,706 44,618 33,662 8 0.10
       renounceOwnership() - - 23,722 1 0.07
       safeTransferFrom(address,address,uint256,bytes) 482,309 721,390 607,831 16 1.76
       safeTransferFrom(address,address,uint256) 114,466 419,277 257,144 14 0.74
       setApprovedContract(address,bool) 28,264 48,164 44,432 16 0.13
       setBaseURI(string) 50,883 79,069 69,674 3 0.20
       transferFrom(address,address,uint256) 96,627 114,960 105,794 2 0.31
       transferOwnership(address) - - 29,439 1 0.09
       updateAllMetadata() - - 24,683 2 0.07
LockDealProvider
       createNewPool(address[],uint256[],bytes) 293,559 304,759 304,170 19 0.88
MockProvider
       createNewPool(address[],uint256[],bytes) - - 377,637 5 1.09
       createNewPoolWithTransfer(address[],uint256[]) - - 340,743 1 0.99
       withdraw(uint256,uint256) 74,299 76,477 75,388 2 0.22
MockTransfer
       createNewPool(address[],uint256[],bytes) - - 269,462 1 0.78
MockVaultManager
       setTransferStatus(bool) 21,710 43,622 32,666 2 0.09
TimedDealProvider
       createNewPool(address[],uint256[],bytes) 354,367 383,102 366,281 37 1.06

Deployments

Min Max Avg Block % usd avg
DealProvider - - 1,730,358 1.3 % 5.00
ERC20Token - - 658,352 0.5 % 1.90
LockDealNFT - - 4,361,099 3.4 % 12.61
LockDealProvider - - 1,667,308 1.3 % 4.82
MockProvider - - 860,176 0.7 % 2.49
MockTransfer - - 1,759,560 1.4 % 5.09
MockVaultManager - - 349,644 0.3 % 1.01
TimedDealProvider 2,018,768 2,018,780 2,018,774 1.6 % 5.84

Solidity and Network Config

Settings Value
Solidity: version 0.8.25
Solidity: optimized true
Solidity: runs 200
Solidity: viaIR true
Block Limit 130,000,000
L1 Gas Price 5 gwei
Token Price 578.41 usd/bnb
Network BINANCE
Toolchain hardhat

Copy link

codecov bot commented Mar 7, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 88.97%. Comparing base (529fb15) to head (dd0bc29).
Report is 21 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #428      +/-   ##
==========================================
+ Coverage   85.75%   88.97%   +3.21%     
==========================================
  Files          13       13              
  Lines         379      408      +29     
  Branches       91       67      -24     
==========================================
+ Hits          325      363      +38     
+ Misses         53       44       -9     
  Partials        1        1              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@YouStillAlive YouStillAlive marked this pull request as ready for review March 7, 2025 11:40
@@ -20,12 +21,23 @@ contract TimedDealProvider is LockDealState, DealProviderState, BasicProvider {
lockDealNFT = _lockDealNFT;
name = "TimedDealProvider";
}


function _withdraw(
uint256 poolId,
uint256 amount
) internal override firewallProtectedSig(0x9e2bf22c) returns (uint256 withdrawnAmount, bool isFinal) {
(withdrawnAmount, isFinal) = provider.withdraw(poolId, amount);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to skip this line.
on current version we make :
old.amount -= amount
new.amount = old.amount
old.amount = 0(missing)

lets set the new directly to old.amount - amount
and the old to 0

the if on line 31 can be simple

@YouStillAlive
Copy link
Member Author

YouStillAlive commented Mar 11, 2025

Gas tracking

Results from Hardhat Gas Reporter

Original TimedDealProvider

TimedDealProvider Withdraw Avg Calls
      now >=  startTime && now < finishTime 164,814 800
      now >  finishTime 167,469 800

Immutable version (version that was deployed to the testnet)

TimedDealProvider Withdraw Avg Calls
      now >=  startTime && now < finishTime 456,600 800
      now >  finishTime 192,073 800

Immutable version + "viaIR: true" setting

TimedDealProvider Withdraw Avg Calls
      now >=  startTime && now < finishTime 451,988 800
      now >  finishTime 187,014 800

Immutable version 2

TimedDealProvider Withdraw Avg Calls
      now >=  startTime && now < finishTime 450,874 800
      now >  finishTime 194,954 800

PR link

Immutable version 3

TimedDealProvider Withdraw Avg Calls
      now >=  startTime && now < finishTime 448,663 800
      now >  finishTime 193,502 800

PR link

Immutable version 4

TimedDealProvider Withdraw Avg Calls
      now >=  startTime && now < finishTime 430,742 800
      now >  finishTime 187,098 800

PR link

Immutable version 5

TimedDealProvider Withdraw Avg Calls
      now >=  startTime && now < finishTime 429,291 800
      now >  finishTime 193,737 800

PR link

@YouStillAlive YouStillAlive merged commit c5aa1e5 into master Mar 13, 2025
7 checks passed
@YouStillAlive YouStillAlive deleted the issue-393 branch March 13, 2025 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

add immutable amount
2 participants