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

Transient storage implementation #113

Draft
wants to merge 6 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 5 additions & 3 deletions contracts/ProtocolReserve/ProtocolShareReserve.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import { SafeERC20Upgradeable, IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import { AccessControlledV8 } from "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol";
import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import { MaxLoopsLimitHelper } from "@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol";
import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol";

Expand All @@ -12,6 +11,8 @@
import { IPoolRegistry } from "../Interfaces/IPoolRegistry.sol";
import { IVToken } from "../Interfaces/IVToken.sol";
import { IIncomeDestination } from "../Interfaces/IIncomeDestination.sol";
import { ReentrancyGuardTransient } from "../Utils/ReentrancyGuardTransient.sol";
import { ReentrancyGuardUpgradeableStorage } from "../Utils/ReentrancyGuardUpgradeableStorage.sol";

error InvalidAddress();
error UnsupportedAsset();
Expand All @@ -20,9 +21,10 @@

contract ProtocolShareReserve is
AccessControlledV8,
ReentrancyGuardUpgradeable,
ReentrancyGuardUpgradeableStorage,
MaxLoopsLimitHelper,
IProtocolShareReserve
IProtocolShareReserve,
ReentrancyGuardTransient
{
using SafeERC20Upgradeable for IERC20Upgradeable;

Expand Down Expand Up @@ -51,7 +53,7 @@

/// @notice address of vBNB contract
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address public immutable vBNB;

Check warning on line 56 in contracts/ProtocolReserve/ProtocolShareReserve.sol

View workflow job for this annotation

GitHub Actions / Lint

Immutable variables name are set to be in capitalized SNAKE_CASE

/// @notice address of pool registry contract
address public poolRegistry;
Expand Down
5 changes: 3 additions & 2 deletions contracts/ProtocolReserve/RiskFundStorage.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.25;

Check warning on line 2 in contracts/ProtocolReserve/RiskFundStorage.sol

View workflow job for this annotation

GitHub Actions / Lint

Found more than One contract per file. 4 contracts found!

import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";

import { ReentrancyGuardUpgradeableStorage } from "../Utils/ReentrancyGuardUpgradeableStorage.sol";

/// @title ReserveHelpersStorage
/// @author Venus
Expand Down Expand Up @@ -61,7 +62,7 @@
/// @author Venus
/// @dev Risk fund V2 storage
/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion
contract RiskFundV2Storage is RiskFundV1Storage, ReentrancyGuardUpgradeable {
contract RiskFundV2Storage is RiskFundV1Storage, ReentrancyGuardUpgradeableStorage {
/// @notice Risk fund converter address
address public riskFundConverter;
}
3 changes: 2 additions & 1 deletion contracts/ProtocolReserve/RiskFundV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import { ensureNonzeroAddress, ensureNonzeroValue } from "@venusprotocol/solidit
import { IRiskFund } from "../Interfaces/IRiskFund.sol";
import { IRiskFundConverter } from "../Interfaces/IRiskFundConverter.sol";
import { RiskFundV2Storage } from "./RiskFundStorage.sol";
import { ReentrancyGuardTransient } from "../Utils/ReentrancyGuardTransient.sol";

/// @title RiskFundV2
/// @author Venus
/// @notice Contract with basic features to hold base asset for different Comptrollers
/// @dev This contract does not support BNB
/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion
contract RiskFundV2 is AccessControlledV8, RiskFundV2Storage, IRiskFund {
contract RiskFundV2 is AccessControlledV8, RiskFundV2Storage, IRiskFund, ReentrancyGuardTransient {
using SafeERC20Upgradeable for IERC20Upgradeable;

/// @notice Emitted when convertible base asset address is updated
Expand Down
5 changes: 3 additions & 2 deletions contracts/ProtocolReserve/XVSVaultTreasury.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ pragma solidity 0.8.25;
import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import { AccessControlledV8 } from "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol";
import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import { ensureNonzeroAddress, ensureNonzeroValue } from "@venusprotocol/solidity-utilities/contracts/validators.sol";

import { IXVSVault } from "../Interfaces/IXVSVault.sol";
import { ReentrancyGuardTransient } from "../Utils/ReentrancyGuardTransient.sol";
import { ReentrancyGuardUpgradeableStorage } from "../Utils/ReentrancyGuardUpgradeableStorage.sol";

/// @title XVSVaultTreasury
/// @author Venus
/// @notice XVSVaultTreasury stores the tokens sent by SingleTokenConverter(XVS) and funds XVSVault
/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion
contract XVSVaultTreasury is AccessControlledV8, ReentrancyGuardUpgradeable {
contract XVSVaultTreasury is AccessControlledV8, ReentrancyGuardUpgradeableStorage, ReentrancyGuardTransient {
using SafeERC20Upgradeable for IERC20Upgradeable;

/// @notice The xvs token address
Expand Down
10 changes: 8 additions & 2 deletions contracts/TokenConverter/AbstractTokenConverter.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.25;

import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import { AccessControlledV8 } from "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol";
import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
Expand All @@ -11,6 +10,8 @@ import { MANTISSA_ONE, EXP_SCALE } from "@venusprotocol/solidity-utilities/contr

import { IAbstractTokenConverter } from "./IAbstractTokenConverter.sol";
import { IConverterNetwork } from "../Interfaces/IConverterNetwork.sol";
import { ReentrancyGuardTransient } from "../Utils/ReentrancyGuardTransient.sol";
import { ReentrancyGuardUpgradeableStorage } from "../Utils/ReentrancyGuardUpgradeableStorage.sol";

/// @title AbstractTokenConverter
/// @author Venus
Expand Down Expand Up @@ -95,7 +96,12 @@ import { IConverterNetwork } from "../Interfaces/IConverterNetwork.sol";
*/

/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion
abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {
abstract contract AbstractTokenConverter is
AccessControlledV8,
IAbstractTokenConverter,
ReentrancyGuardUpgradeableStorage,
ReentrancyGuardTransient
{
using SafeERC20Upgradeable for IERC20Upgradeable;

/// @notice Maximum incentive could be
Expand Down
61 changes: 61 additions & 0 deletions contracts/Utils/ReentrancyGuardTransient.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuardTransient.sol)

pragma solidity ^0.8.25;

import { TransientSlot } from "./TransientSlot.sol";

/**
* @dev Variant of {ReentrancyGuard} that uses transient storage.
*
* NOTE: This variant only works on networks where EIP-1153 is available.
*
* _Available since v5.1._
*/
abstract contract ReentrancyGuardTransient {
using TransientSlot for *;

// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant REENTRANCY_GUARD_STORAGE =
0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;

/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();

/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}

/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return REENTRANCY_GUARD_STORAGE.asBoolean().tload();
}

function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_reentrancyGuardEntered()) {
revert ReentrancyGuardReentrantCall();
}

// Any calls to nonReentrant after this point will fail
REENTRANCY_GUARD_STORAGE.asBoolean().tstore(true);
}

function _nonReentrantAfter() private {
REENTRANCY_GUARD_STORAGE.asBoolean().tstore(false);
}
}
28 changes: 28 additions & 0 deletions contracts/Utils/ReentrancyGuardUpgradeableStorage.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.25;

import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

abstract contract ReentrancyGuardUpgradeableStorage is Initializable {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;

uint256 private _status;

/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;

function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}

function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
}
183 changes: 183 additions & 0 deletions contracts/Utils/TransientSlot.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/TransientSlot.sol)
// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.

pragma solidity ^0.8.25;

/**
* @dev Library for reading and writing value-types to specific transient storage slots.
*
* Transient slots are often used to store temporary values that are removed after the current transaction.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* * Example reading and writing values using transient storage:
* ```solidity
* contract Lock {
* using TransientSlot for *;
*
* // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
* bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;
*
* modifier locked() {
* require(!_LOCK_SLOT.asBoolean().tload());
*
* _LOCK_SLOT.asBoolean().tstore(true);
* _;
* _LOCK_SLOT.asBoolean().tstore(false);
* }
* }
* ```
*
* TIP: Consider using this library along with {SlotDerivation}.
*/
library TransientSlot {
/**
* @dev UDVT that represent a slot holding a address.
*/
type AddressSlot is bytes32;

/**
* @dev Cast an arbitrary slot to a AddressSlot.
*/
function asAddress(bytes32 slot) internal pure returns (AddressSlot) {
return AddressSlot.wrap(slot);
}

/**
* @dev UDVT that represent a slot holding a bool.
*/
type BooleanSlot is bytes32;

/**
* @dev Cast an arbitrary slot to a BooleanSlot.
*/
function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {
return BooleanSlot.wrap(slot);
}

/**
* @dev UDVT that represent a slot holding a bytes32.
*/
type Bytes32Slot is bytes32;

/**
* @dev Cast an arbitrary slot to a Bytes32Slot.
*/
function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {
return Bytes32Slot.wrap(slot);
}

/**
* @dev UDVT that represent a slot holding a uint256.
*/
type Uint256Slot is bytes32;

/**
* @dev Cast an arbitrary slot to a Uint256Slot.
*/
function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {
return Uint256Slot.wrap(slot);
}

/**
* @dev UDVT that represent a slot holding a int256.
*/
type Int256Slot is bytes32;

/**
* @dev Cast an arbitrary slot to a Int256Slot.
*/
function asInt256(bytes32 slot) internal pure returns (Int256Slot) {
return Int256Slot.wrap(slot);
}

/**
* @dev Load the value held at location `slot` in transient storage.
*/
function tload(AddressSlot slot) internal view returns (address value) {
assembly ("memory-safe") {
value := tload(slot)
}
}

/**
* @dev Store `value` at location `slot` in transient storage.
*/
function tstore(AddressSlot slot, address value) internal {
assembly ("memory-safe") {
tstore(slot, value)
}
}

/**
* @dev Load the value held at location `slot` in transient storage.
*/
function tload(BooleanSlot slot) internal view returns (bool value) {
assembly ("memory-safe") {
value := tload(slot)
}
}

/**
* @dev Store `value` at location `slot` in transient storage.
*/
function tstore(BooleanSlot slot, bool value) internal {
assembly ("memory-safe") {
tstore(slot, value)
}
}

/**
* @dev Load the value held at location `slot` in transient storage.
*/
function tload(Bytes32Slot slot) internal view returns (bytes32 value) {
assembly ("memory-safe") {
value := tload(slot)
}
}

/**
* @dev Store `value` at location `slot` in transient storage.
*/
function tstore(Bytes32Slot slot, bytes32 value) internal {
assembly ("memory-safe") {
tstore(slot, value)
}
}

/**
* @dev Load the value held at location `slot` in transient storage.
*/
function tload(Uint256Slot slot) internal view returns (uint256 value) {
assembly ("memory-safe") {
value := tload(slot)
}
}

/**
* @dev Store `value` at location `slot` in transient storage.
*/
function tstore(Uint256Slot slot, uint256 value) internal {
assembly ("memory-safe") {
tstore(slot, value)
}
}

/**
* @dev Load the value held at location `slot` in transient storage.
*/
function tload(Int256Slot slot) internal view returns (int256 value) {
assembly ("memory-safe") {
value := tload(slot)
}
}

/**
* @dev Store `value` at location `slot` in transient storage.
*/
function tstore(Int256Slot slot, int256 value) internal {
assembly ("memory-safe") {
tstore(slot, value)
}
}
}
2 changes: 1 addition & 1 deletion hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ const config: HardhatUserConfig = {
enabled: true,
runs: 10000,
},
evmVersion: "paris",
evmVersion: "cancun",
outputSelection: {
"*": {
"*": ["storageLayout"],
Expand Down
Loading
Loading