Skip to content

Commit

Permalink
Merge pull request #12 from Uniswap/shuffle-city
Browse files Browse the repository at this point in the history
improve inheritance graph
  • Loading branch information
0age authored Oct 31, 2024
2 parents 9980d5b + 894012a commit bbea6e4
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 228 deletions.
6 changes: 2 additions & 4 deletions src/TheCompact.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import { Scope } from "./types/Scope.sol";
import { ResetPeriod } from "./types/ResetPeriod.sol";
import { ForcedWithdrawalStatus } from "./types/ForcedWithdrawalStatus.sol";

import { AllocatorLogic } from "./lib/AllocatorLogic.sol";
import { ClaimProcessor } from "./lib/ClaimProcessor.sol";
import { Extsload } from "./lib/Extsload.sol";
import { TheCompactLogic } from "./lib/TheCompactLogic.sol";

import { ERC6909 } from "solady/tokens/ERC6909.sol";
import { ISignatureTransfer } from "permit2/src/interfaces/ISignatureTransfer.sol";
Expand All @@ -26,7 +24,7 @@ import { ISignatureTransfer } from "permit2/src/interfaces/ISignatureTransfer.so
* formation and mediation of reusable "resource locks."
* This contract has not yet been properly tested, audited, or reviewed.
*/
contract TheCompact is ITheCompact, AllocatorLogic, ClaimProcessor, ERC6909, Extsload {
contract TheCompact is ITheCompact, ERC6909, TheCompactLogic {
function deposit(address allocator) external payable returns (uint256) {
return _performBasicNativeTokenDeposit(allocator);
}
Expand Down
5 changes: 3 additions & 2 deletions src/lib/ClaimProcessorLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ import { EfficiencyLib } from "./EfficiencyLib.sol";
import { FunctionCastLib } from "./FunctionCastLib.sol";
import { HashLib } from "./HashLib.sol";
import { IdLib } from "./IdLib.sol";
import { RegistrationLogic } from "./RegistrationLogic.sol";
import { ValidityLib } from "./ValidityLib.sol";
import { WithdrawalLogic } from "./WithdrawalLogic.sol";
import { SharedLogic } from "./SharedLogic.sol";

contract ClaimProcessorLogic is WithdrawalLogic {
contract ClaimProcessorLogic is SharedLogic, RegistrationLogic {
using HashLib for address;
using HashLib for bytes32;
using HashLib for uint256;
Expand Down
109 changes: 2 additions & 107 deletions src/lib/DepositLogic.sol
Original file line number Diff line number Diff line change
@@ -1,103 +1,18 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

import { ResetPeriod } from "../types/ResetPeriod.sol";
import { Scope } from "../types/Scope.sol";

import { EfficiencyLib } from "./EfficiencyLib.sol";
import { IdLib } from "./IdLib.sol";
import { RegistrationLogic } from "./RegistrationLogic.sol";
import { TransferLogic } from "./TransferLogic.sol";
import { ValidityLib } from "./ValidityLib.sol";
import { ConstructorLogic } from "./ConstructorLogic.sol";

import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol";
import { ISignatureTransfer } from "permit2/src/interfaces/ISignatureTransfer.sol";

contract DepositLogic is TransferLogic, RegistrationLogic {
using IdLib for uint96;
using IdLib for uint256;
using IdLib for address;
using EfficiencyLib for bool;
using ValidityLib for address;
contract DepositLogic is ConstructorLogic {
using SafeTransferLib for address;

uint256 private constant _ERC6909_MASTER_SLOT_SEED = 0xedcaa89a82293940;

/// @dev `keccak256(bytes("Transfer(address,address,address,uint256,uint256)"))`.
uint256 private constant _TRANSFER_EVENT_SIGNATURE = 0x1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859;

function _performBasicNativeTokenDeposit(address allocator) internal returns (uint256 id) {
id = address(0).toIdIfRegistered(Scope.Multichain, ResetPeriod.TenMinutes, allocator);

_deposit(msg.sender, id, msg.value);
}

function _processBatchDeposit(uint256[2][] calldata idsAndAmounts, address recipient) internal {
_setReentrancyGuard();
uint256 totalIds = idsAndAmounts.length;
bool firstUnderlyingTokenIsNative;
uint256 id;

assembly ("memory-safe") {
let idsAndAmountsOffset := idsAndAmounts.offset
id := calldataload(idsAndAmountsOffset)
firstUnderlyingTokenIsNative := iszero(shr(96, shl(96, id)))
// Revert if:
// * the array is empty
// * the callvalue is zero but the first token is native
// * the callvalue is nonzero but the first token is non-native
// * the first token is non-native and the callvalue doesn't equal the first amount
if or(iszero(totalIds), or(eq(firstUnderlyingTokenIsNative, iszero(callvalue())), and(firstUnderlyingTokenIsNative, iszero(eq(callvalue(), calldataload(add(idsAndAmountsOffset, 0x20)))))))
{
// revert InvalidBatchDepositStructure()
mstore(0, 0xca0fc08e)
revert(0x1c, 0x04)
}
}

uint96 currentAllocatorId = id.toRegisteredAllocatorId();

if (firstUnderlyingTokenIsNative) {
_deposit(recipient, id, msg.value);
}

unchecked {
for (uint256 i = firstUnderlyingTokenIsNative.asUint256(); i < totalIds; ++i) {
uint256[2] calldata idAndAmount = idsAndAmounts[i];
id = idAndAmount[0];
uint256 amount = idAndAmount[1];

uint96 newAllocatorId = id.toAllocatorId();
if (newAllocatorId != currentAllocatorId) {
newAllocatorId.mustHaveARegisteredAllocator();
currentAllocatorId = newAllocatorId;
}

_transferAndDeposit(id.toToken(), recipient, id, amount);
}
}

_clearReentrancyGuard();
}

function _performBasicERC20Deposit(address token, address allocator, uint256 amount) internal returns (uint256 id) {
id = token.excludingNative().toIdIfRegistered(Scope.Multichain, ResetPeriod.TenMinutes, allocator);

_transferAndDepositWithReentrancyGuard(token, msg.sender, id, amount);
}

function _performCustomNativeTokenDeposit(address allocator, ResetPeriod resetPeriod, Scope scope, address recipient) internal returns (uint256 id) {
id = address(0).toIdIfRegistered(scope, resetPeriod, allocator);

_deposit(recipient, id, msg.value);
}

function _performCustomERC20Deposit(address token, address allocator, ResetPeriod resetPeriod, Scope scope, uint256 amount, address recipient) internal returns (uint256 id) {
id = token.excludingNative().toIdIfRegistered(scope, resetPeriod, allocator);

_transferAndDepositWithReentrancyGuard(token, recipient, id, amount);
}

/// @dev Retrieves a token balance, compares against `initialBalance`, and mints the resulting balance
/// change of `id` to `to`. Emits a {Transfer} event.
function _checkBalanceAndDeposit(address token, address to, uint256 id, uint256 initialBalance) internal {
Expand Down Expand Up @@ -143,24 +58,4 @@ contract DepositLogic is TransferLogic, RegistrationLogic {
log4(0, 0x40, _TRANSFER_EVENT_SIGNATURE, 0, recipient, id)
}
}

/// @dev Transfers `amount` of `token` and mints the resulting balance change of `id` to `to`.
/// Emits a {Transfer} event.
function _transferAndDeposit(address token, address to, uint256 id, uint256 amount) private {
uint256 initialBalance = token.balanceOf(address(this));

token.safeTransferFrom(msg.sender, address(this), amount);

_checkBalanceAndDeposit(token, to, id, initialBalance);
}

/// @dev Transfers `amount` of `token` and mints the resulting balance change of `id` to `to`.
/// Emits a {Transfer} event.
function _transferAndDepositWithReentrancyGuard(address token, address to, uint256 id, uint256 amount) private {
_setReentrancyGuard();

_transferAndDeposit(token, to, id, amount);

_clearReentrancyGuard();
}
}
3 changes: 2 additions & 1 deletion src/lib/DepositViaPermit2Logic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,15 @@ import { ResetPeriod } from "../types/ResetPeriod.sol";
import { Scope } from "../types/Scope.sol";

import { DepositLogic } from "./DepositLogic.sol";
import { RegistrationLogic } from "./RegistrationLogic.sol";
import { EfficiencyLib } from "./EfficiencyLib.sol";
import { IdLib } from "./IdLib.sol";
import { ValidityLib } from "./ValidityLib.sol";

import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol";
import { ISignatureTransfer } from "permit2/src/interfaces/ISignatureTransfer.sol";

contract DepositViaPermit2Logic is DepositLogic {
contract DepositViaPermit2Logic is DepositLogic, RegistrationLogic {
using IdLib for uint256;
using IdLib for address;
using IdLib for ResetPeriod;
Expand Down
114 changes: 114 additions & 0 deletions src/lib/DirectDepositLogic.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

import { ResetPeriod } from "../types/ResetPeriod.sol";
import { Scope } from "../types/Scope.sol";

import { EfficiencyLib } from "./EfficiencyLib.sol";
import { IdLib } from "./IdLib.sol";
import { DepositLogic } from "./DepositLogic.sol";
import { ValidityLib } from "./ValidityLib.sol";

import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol";
import { ISignatureTransfer } from "permit2/src/interfaces/ISignatureTransfer.sol";

contract DirectDepositLogic is DepositLogic {
using IdLib for uint96;
using IdLib for uint256;
using IdLib for address;
using EfficiencyLib for bool;
using ValidityLib for address;
using SafeTransferLib for address;

function _performBasicNativeTokenDeposit(address allocator) internal returns (uint256 id) {
id = address(0).toIdIfRegistered(Scope.Multichain, ResetPeriod.TenMinutes, allocator);

_deposit(msg.sender, id, msg.value);
}

function _processBatchDeposit(uint256[2][] calldata idsAndAmounts, address recipient) internal {
_setReentrancyGuard();
uint256 totalIds = idsAndAmounts.length;
bool firstUnderlyingTokenIsNative;
uint256 id;

assembly ("memory-safe") {
let idsAndAmountsOffset := idsAndAmounts.offset
id := calldataload(idsAndAmountsOffset)
firstUnderlyingTokenIsNative := iszero(shr(96, shl(96, id)))
// Revert if:
// * the array is empty
// * the callvalue is zero but the first token is native
// * the callvalue is nonzero but the first token is non-native
// * the first token is non-native and the callvalue doesn't equal the first amount
if or(iszero(totalIds), or(eq(firstUnderlyingTokenIsNative, iszero(callvalue())), and(firstUnderlyingTokenIsNative, iszero(eq(callvalue(), calldataload(add(idsAndAmountsOffset, 0x20)))))))
{
// revert InvalidBatchDepositStructure()
mstore(0, 0xca0fc08e)
revert(0x1c, 0x04)
}
}

uint96 currentAllocatorId = id.toRegisteredAllocatorId();

if (firstUnderlyingTokenIsNative) {
_deposit(recipient, id, msg.value);
}

unchecked {
for (uint256 i = firstUnderlyingTokenIsNative.asUint256(); i < totalIds; ++i) {
uint256[2] calldata idAndAmount = idsAndAmounts[i];
id = idAndAmount[0];
uint256 amount = idAndAmount[1];

uint96 newAllocatorId = id.toAllocatorId();
if (newAllocatorId != currentAllocatorId) {
newAllocatorId.mustHaveARegisteredAllocator();
currentAllocatorId = newAllocatorId;
}

_transferAndDeposit(id.toToken(), recipient, id, amount);
}
}

_clearReentrancyGuard();
}

function _performBasicERC20Deposit(address token, address allocator, uint256 amount) internal returns (uint256 id) {
id = token.excludingNative().toIdIfRegistered(Scope.Multichain, ResetPeriod.TenMinutes, allocator);

_transferAndDepositWithReentrancyGuard(token, msg.sender, id, amount);
}

function _performCustomNativeTokenDeposit(address allocator, ResetPeriod resetPeriod, Scope scope, address recipient) internal returns (uint256 id) {
id = address(0).toIdIfRegistered(scope, resetPeriod, allocator);

_deposit(recipient, id, msg.value);
}

function _performCustomERC20Deposit(address token, address allocator, ResetPeriod resetPeriod, Scope scope, uint256 amount, address recipient) internal returns (uint256 id) {
id = token.excludingNative().toIdIfRegistered(scope, resetPeriod, allocator);

_transferAndDepositWithReentrancyGuard(token, recipient, id, amount);
}

/// @dev Transfers `amount` of `token` and mints the resulting balance change of `id` to `to`.
/// Emits a {Transfer} event.
function _transferAndDeposit(address token, address to, uint256 id, uint256 amount) private {
uint256 initialBalance = token.balanceOf(address(this));

token.safeTransferFrom(msg.sender, address(this), amount);

_checkBalanceAndDeposit(token, to, id, initialBalance);
}

/// @dev Transfers `amount` of `token` and mints the resulting balance change of `id` to `to`.
/// Emits a {Transfer} event.
function _transferAndDepositWithReentrancyGuard(address token, address to, uint256 id, uint256 amount) private {
_setReentrancyGuard();

_transferAndDeposit(token, to, id, amount);

_clearReentrancyGuard();
}
}
Loading

0 comments on commit bbea6e4

Please sign in to comment.