Skip to content

Commit ba185ab

Browse files
committed
refactor: added pause protocol
1 parent 00702f5 commit ba185ab

6 files changed

Lines changed: 233 additions & 0 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity 0.8.26;
3+
4+
/// @title ILockClaimer
5+
/// @notice Interface for claiming locked funds in favor of an authorized claimer.
6+
interface ILockClaimer {
7+
/// @notice Emitted when locked funds are claimed.
8+
/// @param initiator Address that initiates the operation (claimer).
9+
/// @param from Account from which funds are claimed.
10+
/// @param amount Amount claimed.
11+
/// @param currency Currency address; use address(0) for native coin.
12+
event FundsClaimed(address indexed initiator, address indexed from, uint256 amount, address indexed currency);
13+
14+
/// @notice Error raised when there are not enough locked funds to claim.
15+
error NoFundsToClaim();
16+
17+
/// @notice Claims a specific amount of locked funds on behalf of an authorized claimer.
18+
/// @param account The address of the account whose funds are being claimed.
19+
/// @param amount The amount of funds to claim.
20+
/// @param currency The currency to associate with the claim; use address(0) for the native coin.
21+
/// @return An identifier or updated state depending on implementation.
22+
function claim(address account, uint256 amount, address currency) external returns (uint256);
23+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity 0.8.26;
3+
4+
/// @title ILockLocker
5+
/// @notice Interface for locking funds in an account.
6+
interface ILockLocker {
7+
8+
/// @notice Emitted when funds are locked.
9+
/// @param initiator Address that initiates the operation.
10+
/// @param from Account whose funds are being locked.
11+
/// @param amount Amount locked.
12+
/// @param currency Currency address; use address(0) for native coin.
13+
event FundsLocked(address indexed initiator, address indexed from, uint256 amount, address indexed currency);
14+
15+
/// @notice Error raised when there are not enough funds to lock.
16+
error NoFundsToLock();
17+
18+
/// @notice Locks a specific amount of funds for a given account.
19+
/// @param account The address of the account whose funds will be locked.
20+
/// @param amount The amount of funds to lock.
21+
/// @param currency The currency to associate with the lock; use address(0) for the native coin.
22+
/// @return An identifier or updated state depending on implementation.
23+
function lock(address account, uint256 amount, address currency) external returns (uint256);
24+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity 0.8.26;
3+
4+
import { ILockClaimer } from "@synaps3/core/interfaces/base/ILockClaimer.sol";
5+
import { ILockReleaser } from "@synaps3/core/interfaces/base/ILockReleaser.sol";
6+
import { ILockLocker } from "@synaps3/core/interfaces/base/ILockLocker.sol";
7+
8+
/// @title ILockOperator
9+
/// @notice Unified interface that composes locker, releaser, and claimer capabilities.
10+
/// @dev Adds a common read method to query the locked balance.
11+
interface ILockOperator is ILockClaimer, ILockLocker, ILockReleaser {
12+
13+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity 0.8.26;
3+
4+
/// @title ILockReleaser
5+
/// @notice Interface for releasing previously locked funds.
6+
interface ILockReleaser {
7+
/// @notice Emitted when locked funds are released.
8+
/// @param initiator Address that initiates the operation.
9+
/// @param recipient Account receiving the released funds.
10+
/// @param amount Amount released.
11+
/// @param currency Currency address; use address(0) for native coin.
12+
event FundsReleased(address indexed initiator, address indexed recipient, uint256 amount, address indexed currency);
13+
14+
/// @notice Error raised when there are not enough locked funds to release.
15+
error NoFundsToRelease();
16+
17+
/// @notice Releases a specific amount of funds from the locked pool.
18+
/// @param account The address of the account whose funds will be released.
19+
/// @param amount The amount of funds to release.
20+
/// @param currency The currency to associate with the release; use address(0) for the native coin.
21+
/// @return An identifier or updated state depending on implementation.
22+
function release(address account, uint256 amount, address currency) external returns (uint256);
23+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
// NatSpec format convention - https://docs.soliditylang.org/en/v0.5.10/natspec-format.html
3+
pragma solidity 0.8.26;
4+
5+
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
6+
import { LedgerUpgradeable } from "@synaps3/core/primitives/upgradeable/LedgerUpgradeable.sol";
7+
import { ILockOperator } from "@synaps3/core/interfaces/base/ILockOperator.sol";
8+
import { FinancialOps } from "@synaps3/core/libraries/FinancialOps.sol";
9+
10+
abstract contract LockOperatorUpgradeable is Initializable, LedgerUpgradeable, ILockOperator {
11+
using FinancialOps for address;
12+
13+
/// @custom:storage-location erc7201:lockoperatorupgradeable
14+
struct LockOperatorStorage {
15+
/// @dev Holds the relation between approved funds, the currency, and amount
16+
/// @dev Holds the registry of locked funds for accounts.
17+
mapping(address => mapping(address => uint256)) _locked;
18+
}
19+
20+
/// @dev Storage slot for LockOperatorUpgradeable, calculated using a unique namespace to avoid conflicts.
21+
/// The `LOCK_OPERATOR_SLOT` constant is used to point to the location of the storage.
22+
bytes32 private constant LOCK_OPERATOR_SLOT =
23+
0xece3ff917f3a3127e521e0c3f2f90ff09a3c8199be32f9b40bff79e776960800;
24+
25+
/// @dev Initializes the contract and ensures it is upgradeable.
26+
/// Even if the initialization is harmless, this ensures the contract follows upgradeable contract patterns.
27+
/// This is the method to initialize this contract and any other extended contracts.
28+
/// slither-disable-next-line naming-convention
29+
function __LockOperator_init() internal onlyInitializing {
30+
__Ledger_init();
31+
}
32+
33+
/// @dev Function to initialize the contract without chaining, typically used in child contracts.
34+
/// This is the method to initialize this contract as standalone.
35+
/// slither-disable-next-line naming-convention
36+
function __LockOperator_init_unchained() internal onlyInitializing {}
37+
38+
/// @notice Locks a specific amount of funds for a given account.
39+
/// @dev The funds are immobilized and cannot be withdrawn or transferred until released.
40+
/// Only operator role can handle this methods.
41+
/// An approval is not needed, the protocol operate directly on the user funds to simplify operations.
42+
/// @param account The address of the account for which the funds will be locked.
43+
/// @param amount The amount of funds to lock.
44+
/// @param currency The currency to associate lock with. Use address(0) for the native coin.
45+
function _lock(
46+
address account,
47+
uint256 amount,
48+
address currency
49+
) internal onlyValidOperation(account, amount) returns (uint256) {
50+
if (getLedgerBalance(account, currency) < amount) revert NoFundsToLock();
51+
_subLedgerEntry(account, amount, currency);
52+
_sumLockedAmount(account, amount, currency);
53+
emit FundsLocked(msg.sender, account, amount, currency);
54+
return amount;
55+
}
56+
57+
/// @notice Release a specific amount of funds from locked pool.
58+
/// @param account The address of the account for which the funds will be released.
59+
/// @param amount The amount of funds to release.
60+
/// @param currency The currency to associate release with. Use address(0) for the native coin.
61+
function _release(
62+
address account,
63+
uint256 amount,
64+
address currency
65+
) internal onlyValidOperation(account, amount) returns (uint256) {
66+
if (_getLockedAmount(account, currency) < amount) revert NoFundsToRelease();
67+
_subLockedAmount(account, amount, currency);
68+
_sumLedgerEntry(account, amount, currency);
69+
emit FundsReleased(msg.sender, account, amount, currency);
70+
return amount;
71+
}
72+
73+
/// @notice Claims a specific amount of locked funds on behalf of a claimer.
74+
/// @dev The claimer is authorized to process the funds from the account.
75+
/// Only operator role can handle this methods.
76+
/// @param account The address of the account whose funds are being claimed.
77+
/// @param amount The amount of funds to claim.
78+
/// @param currency The currency to associate claim with. Use address(0) for the native coin.
79+
function _claim(
80+
address account,
81+
uint256 amount,
82+
address currency
83+
) internal onlyValidOperation(account, amount) returns (uint256) {
84+
if (_getLockedAmount(account, currency) < amount) revert NoFundsToClaim();
85+
_subLockedAmount(account, amount, currency); //
86+
_sumLedgerEntry(msg.sender, amount, currency);
87+
emit FundsClaimed(msg.sender, account, amount, currency);
88+
return amount;
89+
}
90+
91+
/// @notice Reduces the locked funds of an account for a specific currency.
92+
/// @dev Deducts the specified `amount` from the `_locked` mapping for the given `account` and `currency`.
93+
/// @param account The address of the account whose locked funds are being reduced.
94+
/// @param amount The amount to subtract from the locked balance.
95+
/// @param currency The address of the currency being reduced.
96+
function _subLockedAmount(address account, uint256 amount, address currency) private {
97+
LockOperatorStorage storage $ = _getLockOperatorStorage();
98+
$._locked[account][currency] -= amount;
99+
}
100+
101+
/// @notice Increases the locked funds of an account for a specific currency.
102+
/// @dev Adds the specified `amount` to the `_locked` mapping for the given `account` and `currency`.
103+
/// @param account The address of the account whose locked funds are being increased.
104+
/// @param amount The amount to add to the locked balance.
105+
/// @param currency The address of the currency being increased.
106+
function _sumLockedAmount(address account, uint256 amount, address currency) private {
107+
LockOperatorStorage storage $ = _getLockOperatorStorage();
108+
$._locked[account][currency] += amount;
109+
}
110+
111+
/// @notice Retrieves the locked balance of an account for a specific currency.
112+
/// @dev Returns the value stored in the `_locked` mapping for the given `account` and `currency`.
113+
/// @param account The address of the account whose locked balance is being queried.
114+
/// @param currency The address of the currency to check the locked balance for.
115+
/// @return The locked balance of the specified account for the given currency.
116+
function _getLockedAmount(address account, address currency) private view returns (uint256) {
117+
LockOperatorStorage storage $ = _getLockOperatorStorage();
118+
return $._locked[account][currency];
119+
}
120+
121+
/// @notice Internal function to get the allowance operator storage.
122+
/// @dev Uses assembly to retrieve the storage at the pre-calculated storage slot.
123+
function _getLockOperatorStorage() private pure returns (LockOperatorStorage storage $) {
124+
assembly {
125+
$.slot := LOCK_OPERATOR_SLOT
126+
}
127+
}
128+
}

test/assets/AssetOwnership.sol

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity 0.8.26;
3+
4+
import "forge-std/Test.sol";
5+
import { IAccessControl } from "@openzeppelin/contracts/access/IAccessControl.sol";
6+
import { IAssetRegistrable } from "contracts/core/interfaces/assets/IAssetRegistrable.sol";
7+
import { IAssetRevokable } from "contracts/core/interfaces/assets/IAssetRevokable.sol";
8+
import { IAssetVerifiable } from "contracts/core/interfaces/assets/IAssetVerifiable.sol";
9+
import { AssetReferendum } from "contracts/assets/AssetReferendum.sol";
10+
11+
import { BaseTest } from "test/BaseTest.t.sol";
12+
import { T } from "contracts/core/primitives/Types.sol";
13+
import { C } from "contracts/core/primitives/Constants.sol";
14+
15+
contract AssetOwnershipTest is BaseTest {
16+
function setUp() public initialize {
17+
// setup the access manager to use during tests..
18+
deployAssetOwnership();
19+
}
20+
21+
22+
}

0 commit comments

Comments
 (0)