Sarunas Matulevicius

Sarunas Matulevicius

6min read

CUBE3 Launches Next Gen Fraud Blocking in Product Release v2.9

CUBE3 product release 2.9 has some impactful updates! The new version of the protocol includes both the [protocol-core-solidity] and the protection-solidity repositories, which together make up the new version of the protocol.

V2 is a complete rewrite of the original protocol. While functionally similar, this new version of the protocol contains significant differences when compared to the first version. The primary motivation for the re-write was to address customer concerns and focus on the following:

  • Reduce complexity
  • Improve readability
  • Lower contract size of inheritable protection contracts
  • Reduce gas usage
  • Improve the user and developer experience

Reducing Complexity

V1 had two distinct versions of the protection contracts, ie. different versions for upgradeable and non-upgradeable contracts. The Upgradeable version required a separate GateKeeper contract to manage the function protection state. This logic has since been moved to the router, meaning that both upgradeable and non-upgradeable contracts can share the same ProtectionBase contract.

Previously, this added complexity by requiring upgradeable and non-upgradeable contracts to manage function protection in different ways. It also meant that the protocol itself, along with the CUBE3 back-end, had to listen for different events on different contracts, depending on which was being used.

V2 also eliminates the concept of the contract’s _self. This was previously used as a reference to differentiate between a proxy and its implementation contract, and was required by the backend to differentiate between an upgradeable and non-upgradeable integration during the registration process. V2 eliminates this complexity and instead allows the back-end to treat proxies (upgradeable) and standalone (non-upgradeable) contracts as equals, without the need to differentiate.

All external dependencies have been removed from the protection contracts. In other words, there’s no longer a need to install third-party contracts, such as OpenZeppelin, which added complexity as far as installation, dependency management, and version compatibility.

Improve Readability

In addition to providing protection against storage collisions, following the ERC7201 namespaced storage spec means V2 uses dedicated getter and setter functions for all storage read/writes. This results in much more readable code. For example, all storage access for the Cube3Router is managed by the abstract RouterStorage.sol, which defines the storage layout and defines the getters and setters. Eg:

```solidity
    /// @inheritdoc IRouterStorage
    function getIntegrationAdmin(address integration) public view returns (address) {
        return _state().integrationToState[integration].admin;
    }

    /// @notice Sets the admin for an integration in storage.
    /// @param integration The integration address to set the admin for.
    /// @param newAdmin The new admin of the integration.
    function _setIntegrationAdmin(address integration, address newAdmin) internal {
        address oldAdmin = _state().integrationToState[integration].admin;
        _state().integrationToState[integration].admin = newAdmin;
        emit IntegrationAdminTransferred(integration, oldAdmin, newAdmin);
    }
```

The logic for CUBE3 administrative actions and user integration actions have been separated into isolated abstract contracts to isolate functionality.

contract Cube3RouterImpl is
    ICube3RouterImpl,
    ContextUpgradeable,
    AccessControlUpgradeable,
    UUPSUpgradeable,
    ProtocolManagement, // CUBE3 admin logic
    IntegrationManagement // User integration logic
{

Overall, the codebase for V2 is cleaner and significantly more organized. This is evidenced by the increased code rating from a respectable 7/10 in V1 to 9/10 in V2.

Lower Contract Size

One of the primary concerns of users who discussed the use of the integration contracts for V1 was the size of their contracts. Solidity has a maximum contract size limit of 24KB. As such, we want to make the inheritable protection contracts as small as possible, leaving the customer with as much of the available size limits to implement their own logic. The first step in making this improvement was removing all third-party contracts from the integration contracts.

Contracts sizes are as follows (WIP):

| Version    | Size (KB) |
| --------   | -------   |
| V1         | ? KB      |
| V2         | 1.55 KB   |

Reduce Gas Usage

Although V1 was designed with gas efficiency in mind, improvements in the design have reduced the amount of gas required to route transactions to the security modules and for the security modules to execute their logic. For example, take this contract transaction on Sepolia interacting with V1 of the protocol: https://www.tdly.co/tx/11155111/0x3ed6af1d68599117b1d3c226fd896234866a745513e442cb59d9407042b1acb5

The above screenshot shows the external call to the CUBE3 protocol where while protection is enabled. This call adds 75,165 gas to the call.

In the example below, calldata is routed through V2 of the protocol, executing similar logic and checking the validity of the payload and signature: https://www.tdly.co/tx/11155111/0x25964eb14166b69ba69a55cfd4ad3dbe8cd8051cdacf7717ff951ac2cab3a9b5

We can see that the external call to the V2 protocol, containing the same functionality, only uses 57,556 gas. That’s roughly a 24% improvement in efficiency. It should be noted that both transactions have nonce-tracking enabled, which helps prevent replay attacks. This adds roughly ~25,000 gas to each call due to the SLOAD and SSTORE operations required.

Improve the User & Developer Experiences

A big focus of the V2 protocol was improving the developer experience. All external dependencies have been removed from the inheritable Protection contracts. Not only does this drastically reduce contract size, creating less of a headache for developers with complex contracts that are close to the 24kb codesize limit, but it removes the need for complex version management of additional dependencies.

The contracts are easy to install as dependencies using foundry or a package manager such as npm.

Both singleton and proxy implementation’s using the Protection contracts inherit from the same base abstract contract – there’s no longer a need to apply different logic to different types of contracts.

CUBE3 wants your feedback!

Our users are a critical component of making web3 safer. Help us make the next CUBE3 product release effective and efficient as possible. You can continually check the summary of Ongoing CUBE3 Product Release Notes here.

Follow us and join the CUBE3 communities on Telegram, LinkedIn and X to engage and provide your ideas, thoughts, and opinions. Get involved and protect your contracts, business and communities with real-time transaction security with CUBE3.AI today.



Stay informed, stay protected.
Get the latest web3 security news first