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

feat: add proveCashierShard and proveCashierRoot checks #18

Merged
merged 22 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
51f59a2
feat: add contracts determinant
ihoroleksiienko Oct 24, 2024
457a6b0
test: for `isRoot` and `isShard` functional
ihoroleksiienko Oct 24, 2024
b66eaaf
Merge branch 'main' into feat/add-contract-determinant
ihoroleksiienko Oct 28, 2024
26e6837
fix: empty lines
ihoroleksiienko Oct 28, 2024
44e7afd
fix: review contracts
ihoroleksiienko Oct 29, 2024
335d1a2
fix: review test
ihoroleksiienko Oct 29, 2024
fb7925e
fix: review test
EvgeniiZaitsevCW Oct 29, 2024
6afee03
fix: add upgradeToAndCall tests
ihoroleksiienko Oct 29, 2024
69bc777
fix: change error names
ihoroleksiienko Oct 29, 2024
be2a9ab
test: update error names in tests
ihoroleksiienko Oct 29, 2024
089184a
test: fix linter warnings, fix typos, remove redundant code
EvgeniiZaitsevCW Oct 29, 2024
ce24fe0
fix: typo
igorsenych-cw Oct 30, 2024
5e7ff5b
fest: rename `Cashier_ShardAddressNotShard` error to `Cashier_Contrac…
igorsenych-cw Oct 30, 2024
548a781
feat: don't return from `isCashierRoot` and `isCashierShard` functions
igorsenych-cw Oct 30, 2024
fdca2b3
feat: improve error handling during contract upgrade
igorsenych-cw Oct 31, 2024
c92a6e3
feat: check if the implementation address is contract
igorsenych-cw Nov 1, 2024
85f65ad
feat: sort errors alphabetically
igorsenych-cw Nov 1, 2024
f5641e4
test: add tests for not contract addresses
ihoroleksiienko Nov 1, 2024
19fff7e
fix: prettier on solidity files
ihoroleksiienko Nov 1, 2024
0ecf2bc
test: add tests for zero address
ihoroleksiienko Nov 1, 2024
df11ff8
fix: remove spaces
ihoroleksiienko Nov 1, 2024
d818ecd
feat: rename `isCashier..` to `proveCashier..`
igorsenych-cw Nov 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 47 additions & 13 deletions contracts/Cashier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ contract Cashier is
* - If the cash-out operation has the `Reversed` status its `account` field must equal the `account` argument.
*/
function forceCashOut(
address account,
address account, // Tools: This comment prevents Prettier from formatting into a single line.
uint256 amount,
bytes32 txId
) external whenNotPaused onlyRole(CASHIER_ROLE) {
Expand Down Expand Up @@ -417,6 +417,7 @@ contract Cashier is

uint256 count = shards.length;
for (uint256 i; i < count; i++) {
_validateShardContract(shards[i]);
_shards.push(ICashierShard(shards[i]));
emit ShardAdded(shards[i]);
}
Expand Down Expand Up @@ -445,6 +446,7 @@ contract Cashier is
uint256 k = fromIndex + i;
address oldShard = address(_shards[k]);
address newShard = shards[i];
_validateShardContract(newShard);
_shards[k] = ICashierShard(newShard);
emit ShardReplaced(newShard, oldShard);
}
Expand Down Expand Up @@ -633,6 +635,13 @@ contract Cashier is
return _cashOutHookConfigs[txId];
}

// ------------------ Pure functions -------------------------- //

/**
* @inheritdoc ICashierPrimary
*/
function proveCashierRoot() external pure {}

// ------------------ Internal functions ---------------------- //

/**
Expand Down Expand Up @@ -742,6 +751,42 @@ contract Cashier is
_validateReleaseTime(releaseTime);
}

/**
* @dev Validates the provided shard.
* @param shard The cashier shard contract address.
*/
function _validateShardContract(address shard) internal view {
if (shard == address(0)) {
revert Cashier_ShardAddressZero();
}

if (shard.code.length == 0) {
revert Cashier_ShardAddressNotContract();
}

try ICashierShard(shard).proveCashierShard() {} catch {
revert Cashier_ContractNotShard();
}
}

/**
* @dev Validates the provided root.
* @param root The cashier root contract address.
*/
function _validateRootContract(address root) internal view {
if (root == address(0)) {
revert Cashier_RootAddressZero();
}

if (root.code.length == 0) {
revert Cashier_RootAddressNotContract();
}

try ICashier(root).proveCashierRoot() {} catch {
revert Cashier_ContractNotRoot();
}
}

/**
* @dev Checks the error code returned by the shard contract and reverts with the appropriate error message.
* @param err The error code returned by the shard contract.
Expand Down Expand Up @@ -838,6 +883,7 @@ contract Cashier is
* @param newImplementation The address of the new implementation.
*/
function _authorizeUpgrade(address newImplementation) internal view override onlyRole(OWNER_ROLE) {
_validateRootContract(newImplementation);
newImplementation; // Suppresses a compiler warning about the unused variable.
}

Expand All @@ -856,10 +902,6 @@ contract Cashier is
* @param newImplementation The address of the new shard implementation.
*/
function upgradeShardsTo(address newImplementation) external onlyRole(OWNER_ROLE) {
if (newImplementation == address(0)) {
revert Cashier_ShardAddressZero();
}

for (uint256 i = 0; i < _shards.length; i++) {
_shards[i].upgradeTo(newImplementation);
}
Expand All @@ -871,15 +913,7 @@ contract Cashier is
* @param newShardImplementation The address of the new shard implementation.
*/
function upgradeRootAndShardsTo(address newRootImplementation, address newShardImplementation) external {
if (newRootImplementation == address(0)) {
revert Cashier_RootAddressZero();
}
if (newShardImplementation == address(0)) {
revert Cashier_ShardAddressZero();
}

upgradeToAndCall(newRootImplementation, "");

for (uint256 i = 0; i < _shards.length; i++) {
_shards[i].upgradeTo(newShardImplementation);
}
Expand Down
26 changes: 26 additions & 0 deletions contracts/CashierShard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,13 @@ contract CashierShard is CashierShardStorage, OwnableUpgradeable, UUPSUpgradeabl
return cashOutOperations;
}

// ------------------ Pure functions -------------------------- //

/**
* @inheritdoc ICashierShardPrimary
*/
function proveCashierShard() external pure {}

// ------------------ Internal functions ---------------------- //

/**
Expand Down Expand Up @@ -322,9 +329,28 @@ contract CashierShard is CashierShardStorage, OwnableUpgradeable, UUPSUpgradeabl
* @param newImplementation The address of the new implementation.
*/
function _authorizeUpgrade(address newImplementation) internal view override onlyOwnerOrAdmin {
_validateShardContract(newImplementation);
newImplementation; // Suppresses a compiler warning about the unused variable.
}

/**
* @dev Validates the provided shard.
* @param shard The cashier shard contract address.
*/
function _validateShardContract(address shard) internal view {
if (shard == address(0)) {
revert CashierShard_ShardAddressZero();
}

if (shard.code.length == 0) {
revert CashierShard_ShardAddressNotContract();
}

try ICashierShard(shard).proveCashierShard() {} catch {
revert CashierShard_ContractNotShard();
}
}

// ------------------ Service functions ----------------------- //

/**
Expand Down
45 changes: 31 additions & 14 deletions contracts/interfaces/ICashier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,6 @@ interface ICashierErrors {
/// @dev Thrown if the provided amount is zero.
error Cashier_AmountZero();

/// @dev The same hook flags for an operation are already configured.
error Cashier_HookFlagsAlreadyRegistered();

/// @dev The provided bit flags to configure the hook logic are invalid.
error Cashier_HookFlagsInvalid();

/// @dev The provided address of the callable contract with the hook function is non-zero but must be.
error Cashier_HookCallableContractAddressNonZero();

/// @dev The provided address of the callable contract with the hook function is zero but must not be.
error Cashier_HookCallableContractAddressZero();

/// @dev Thrown if the cash-in operation with the provided txId is already executed.
error Cashier_CashInAlreadyExecuted();

Expand All @@ -43,12 +31,36 @@ interface ICashierErrors {
/// @dev Thrown if the cash-out operation with the provided txId has an inappropriate status.
error Cashier_CashOutStatusInappropriate();

/// @dev Thrown if the contract is not a cashier root contract.
error Cashier_ContractNotRoot();

/// @dev Thrown if the contract is not a cashier shard contract.
error Cashier_ContractNotShard();

/// @dev The provided address of the callable contract with the hook function is non-zero but must be.
error Cashier_HookCallableContractAddressNonZero();

/// @dev The provided address of the callable contract with the hook function is zero but must not be.
error Cashier_HookCallableContractAddressZero();

/// @dev The same hook flags for an operation are already configured.
error Cashier_HookFlagsAlreadyRegistered();

/// @dev The provided bit flags to configure the hook logic are invalid.
error Cashier_HookFlagsInvalid();

/// @dev Thrown if the provided release time for the premint operation is inappropriate.
error Cashier_PremintReleaseTimeInappropriate();

/// @dev Thrown if the provided root address is not a contract.
error Cashier_RootAddressNotContract();

/// @dev Thrown if the provided root address is zero.
error Cashier_RootAddressZero();

/// @dev Thrown if the provided shard address is not a contract.
error Cashier_ShardAddressNotContract();

/// @dev Thrown if the provided shard address is zero.
error Cashier_ShardAddressZero();

Expand Down Expand Up @@ -175,7 +187,7 @@ interface ICashierPrimary is ICashierTypes {
* @param amount The amount of tokens to cash-out.
*/
event ForcedCashOut(
address indexed account,
address indexed account, // Tools: This comment prevents Prettier from formatting into a single line.
bytes32 indexed txId,
uint256 amount
);
Expand Down Expand Up @@ -327,7 +339,7 @@ interface ICashierPrimary is ICashierTypes {
* @param txId The off-chain transaction identifier of the related operation.
*/
function forceCashOut(
address account,
address account, // Tools: This comment prevents Prettier from formatting into a single line.
uint256 amount,
bytes32 txId
) external;
Expand Down Expand Up @@ -395,6 +407,11 @@ interface ICashierPrimary is ICashierTypes {
* @dev Returns the address of the underlying token.
*/
function underlyingToken() external view returns (address);

/**
* @dev Proves that the contract is the cashier root contract.
*/
function proveCashierRoot() external pure;
}

/**
Expand Down
15 changes: 14 additions & 1 deletion contracts/interfaces/ICashierShard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@ import { ICashierTypes } from "./ICashierTypes.sol";
* @dev Defines the custom errors used in the cashier shard contract.
*/
interface ICashierShardErrors {
/// @dev Thrown if the contract is not a cashier shard contract.
error CashierShard_ContractNotShard();

/// @dev Thrown if the provided shard address is not a contract.
error CashierShard_ShardAddressNotContract();

/// @dev Thrown if the provided shard address is zero.
error CashierShard_ShardAddressZero();

/// @dev Thrown if the caller is not an admin.
error CashierShard_Unauthorized();
}

/**
* @title ICashierShardPrimary interface
* @author CloudWalk Inc. (See https://www.cloudwalk.io)
Expand Down Expand Up @@ -168,6 +176,11 @@ interface ICashierShardPrimary is ICashierTypes {
* @return operations The data of the cash-out operations in the form of a structure.
*/
function getCashOuts(bytes32[] memory txIds) external view returns (CashOutOperation[] memory operations);

/**
* @dev Proves that the contract is the cashier shard contract.
*/
function proveCashierShard() external pure;
}

/**
Expand Down
5 changes: 5 additions & 0 deletions contracts/mocks/CashierShardMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,9 @@ contract CashierShardMock is ICashierTypes {
targetStatus; // Silence the compilation warning about unused variable
err = REGISTER_OPERATION_UNEXPECTED_ERROR;
}

/**
* @dev Simulates real CashierShard contract.
*/
function proveCashierShard() external pure {}
}
Loading
Loading