2. Integration

Learn about protecting your smart contracts using CUBE3 RASP interfaces.

Contents

Integration

At its core, basic integration only takes 2 steps:

  • Inherit either Cube3Protection or Cube3ProtectionUpgradeable abstract contracts provided in this repository. This gives you access to cube3Protected modifier.

  • Enforce cube3Protected modifier on functions you wish to protect.

cube3Protected modifier

cube3Protected takes in one parameter called cube3SecurePayload.

function myFunction(
    ...args,
    bytes calldata cube3SecurePayload
) cube3Protected(cube3Payload) { <...> }

Before initiating a transaction on-chain, an HTTP request has to be made to CUBE3 validation service in order to fetch the cube3SecurePayload, providing transaction data in a request body. If the CUBE3 backend finds that transaction to be malicious, cube3SecurePayload will not be provided and the transaction will not be possible.

To generate cube3SecurePayload you would use CUBE3 SDK (learn more about it here).

CUBE3 abstract contracts

Cube3Protection constructor and Cube3ProtectionUpgradeable initialize function takes 3 parameters:

  1. address - CUBE3 Router address, which you can find here

  2. address - admin address of your protected smart contract

  3. boolean - enable CUBE3 protection

Examples

Non-Upgradeable protection

Using cube3Protected modifier

Inherit from Cube3Protection to get access to cube3Protected modifier.

import "@cube3/Cube3Protection.sol";

contract MyContract is Cube3Protection {
    constructor(address _router)
     Cube3Protection(
      _router,
      msg.sender, // deployer becomes the integrationAdmin
      true // enable the connection to the protocol
     ) {}

    function myFunction(...args, bytes calldata cube3Payload) external cube3Protected(cube3Payload) {
        // Your logic here
    }
}

Using the inline assertion

Inherit from Cube3Protection to get access to _assertProtectWhenConnected function.

import "@cube3/Cube3Protection.sol";

contract MyContract is Cube3Protection {
    constructor(address _router)
     Cube3Protection(
      _router,
      msg.sender, // deployer becomes the integrationAdmin
      true // enable the connection to the protocol
     ) {}

    function myFunction(...args, bytes calldata cube3Payload) external  {
        _assertProtectWhenConnected(cube3Payload)
        // Your logic here
    }
}

Once you integrate with Cube3Protection, you are ready to move to deployment (read more here).

Upgradeable protection

Inherit from Cube3ProtectionUpgradeable to get access to cube3Protected modifier.

Important Note: This example is not an exhaustive demonstration of using the CUBE3 upgradeable contracts for all possible proxy patterns, but rather demonstrating usage in a single scenario.

Below is an example of inheriting the Cube3ProtectionUpgradeable.sol contract into an upgradeable contract using the UUPS proxy pattern. Because initializers are not linearized by the compiler like constructors, we want to avoid initializing the same contract twice. As such, we follow OpenZeppelin's standards for Multiple Inheritance utilizing the _init and _init_unchained pattern. Upgradeable integrations will call __Cube3ProtectionUpgradeable_init(...args) inside their own initialize functions. The integration MUST initialize Cube3ProtectionUpgradeable in its initialize function to set the protocol contract addresses (implicitly) and the security admin account (explicitly).

import "@cube3/upgradeable/Cube3ProtectionUpgradeable.sol";

contract MyContractUpgradeable is Cube3ProtectionUpgradeable, UUPSUpgradeable, OwnableUpgradeable {
    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    function initialize(address router, address admin, bool checkProtection) initializer public {
       // In this scenario, the contract owner is the same account as the integration's admin, which
       // has privileged access to the router.
        __Cube3ProtectionUpgradeable_init(router, admin, checkProtection);
        __Ownable_init(admin);
        __UUPSUpgradeable_init();
    }

    function _authorizeUpgrade(address newImplementation)
        internal
        onlyOwner
        override
    {}

    function myFunction(...args, bytes calldata cube3Payload) public cube3Protected(cube3Payload) {
      // Your logic here
    }
}

Once you integrate with Cube3ProtectionUpgradeable, you are ready to move to deployment (read more here).

Last updated