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

OtterSec Audit Fixes 3 #5

Merged
merged 17 commits into from
Jan 4, 2024
Merged
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
65 changes: 49 additions & 16 deletions contracts/core/TTFutureTokenV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,33 @@ import {ITokenTableUnlockerV2} from "../interfaces/ITokenTableUnlockerV2.sol";
* claimable amount can be determined by calling
* TokenTableUnlockerV2.calculateAmountClaimable(uint256 actualId)
*/
// solhint-disable var-name-mixedcase
// solhint-disable no-inline-assembly
// solhint-disable const-name-snakecase
// solhint-disable private-vars-leading-underscore
contract TTFutureTokenV2 is ITTFutureTokenV2, ERC721AQueryableUpgradeable {
address public authorizedMinter;
bool public isTransferable;
/// @custom:storage-location erc7201:ethsign.tokentable.TTFutureTokenV2
struct TTFutureTokenV2Storage {
address authorizedMinter;
bool isTransferable;
string baseUri;
}

// keccak256(abi.encode(uint256(keccak256("ethsign.tokentable.TTFutureTokenV2")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant TTFutureTokenV2StorageLocation =
0xb50f0509372e72ec7790b055b09e294ca3549f94c48d078a7ee9a7b36fac3600;

// v2.0.1
string public baseUri;
function _getTTFutureTokenV2Storage()
internal
pure
returns (TTFutureTokenV2Storage storage $)
{
assembly {
$.slot := TTFutureTokenV2StorageLocation
}
}

// solhint-disable-next-line ordering
constructor() {
if (block.chainid != 33133) {
_dummyInitialize();
Expand All @@ -38,11 +58,12 @@ contract TTFutureTokenV2 is ITTFutureTokenV2, ERC721AQueryableUpgradeable {
address projectToken,
bool isTransferable_
) external override initializerERC721A {
TTFutureTokenV2Storage storage $ = _getTTFutureTokenV2Storage();
__ERC721A_init_unchained(
string.concat("Future ", IERC20Metadata(projectToken).name()),
string.concat("FT-", IERC20Metadata(projectToken).symbol())
);
isTransferable = isTransferable_;
$.isTransferable = isTransferable_;
}

/**
Expand All @@ -55,8 +76,12 @@ contract TTFutureTokenV2 is ITTFutureTokenV2, ERC721AQueryableUpgradeable {
function setAuthorizedMinterSingleUse(
address authorizedMinter_
) external override {
if (authorizedMinter != address(0)) revert NotPermissioned();
authorizedMinter = authorizedMinter_;
if (block.chainid != 33133) {
_initializerERC721A(); // So test cases are not broken
}
TTFutureTokenV2Storage storage $ = _getTTFutureTokenV2Storage();
if ($.authorizedMinter != address(0)) revert NotPermissioned();
$.authorizedMinter = authorizedMinter_;
}

/**
Expand All @@ -65,7 +90,8 @@ contract TTFutureTokenV2 is ITTFutureTokenV2, ERC721AQueryableUpgradeable {
* token with tokenId == actualId is minted.
*/
function safeMint(address to) external override returns (uint256 tokenId) {
if (_msgSenderERC721A() != authorizedMinter) revert NotPermissioned();
TTFutureTokenV2Storage storage $ = _getTTFutureTokenV2Storage();
if (_msgSenderERC721A() != $.authorizedMinter) revert NotPermissioned();
tokenId = _nextTokenId();
_safeMint(to, 1);
}
Expand All @@ -78,7 +104,8 @@ contract TTFutureTokenV2 is ITTFutureTokenV2, ERC721AQueryableUpgradeable {
address to,
uint256 tokenId
) public payable virtual override(ERC721AUpgradeable, IERC721AUpgradeable) {
if (!isTransferable) revert NotPermissioned();
TTFutureTokenV2Storage storage $ = _getTTFutureTokenV2Storage();
if (!$.isTransferable) revert NotPermissioned();
super.transferFrom(from, to, tokenId);
}

Expand All @@ -91,16 +118,18 @@ contract TTFutureTokenV2 is ITTFutureTokenV2, ERC721AQueryableUpgradeable {
uint256 tokenId,
bytes memory _data
) public payable virtual override(ERC721AUpgradeable, IERC721AUpgradeable) {
if (!isTransferable) revert NotPermissioned();
TTFutureTokenV2Storage storage $ = _getTTFutureTokenV2Storage();
if (!$.isTransferable) revert NotPermissioned();
super.safeTransferFrom(from, to, tokenId, _data);
}

function setURI(string calldata uri) external {
TTFutureTokenV2Storage storage $ = _getTTFutureTokenV2Storage();
if (
_msgSenderERC721A() !=
ITokenTableUnlockerV2(authorizedMinter).owner()
ITokenTableUnlockerV2($.authorizedMinter).owner()
) revert NotPermissioned();
baseUri = uri;
$.baseUri = uri;
emit DidSetBaseURI(uri);
}

Expand All @@ -123,22 +152,26 @@ contract TTFutureTokenV2 is ITTFutureTokenV2, ERC721AQueryableUpgradeable {
bool isCancelable
)
{
TTFutureTokenV2Storage storage $ = _getTTFutureTokenV2Storage();
(
uint256 deltaAmountClaimable_,
uint256 updatedAmountClaimed_
) = ITokenTableUnlockerV2(authorizedMinter).calculateAmountClaimable(
) = ITokenTableUnlockerV2($.authorizedMinter).calculateAmountClaimable(
tokenId
);
deltaAmountClaimable = deltaAmountClaimable_;
amountAlreadyClaimed = updatedAmountClaimed_ - deltaAmountClaimable_;
isCancelable = ITokenTableUnlockerV2(authorizedMinter).isCancelable();
isCancelable = ITokenTableUnlockerV2($.authorizedMinter).isCancelable();
}

function version() external pure override returns (string memory) {
return "2.5.0";
return "2.5.5";
}

function _initializerERC721A() internal initializerERC721A {}

function _baseURI() internal view virtual override returns (string memory) {
return baseUri;
TTFutureTokenV2Storage storage $ = _getTTFutureTokenV2Storage();
return $.baseUri;
}
}
38 changes: 33 additions & 5 deletions contracts/core/TTUProjectTokenStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,49 @@ pragma solidity ^0.8.20;

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

// solhint-disable var-name-mixedcase
// solhint-disable no-inline-assembly
// solhint-disable const-name-snakecase
// solhint-disable private-vars-leading-underscore
contract TTUProjectTokenStorage is Initializable {
address private _projectToken;
/// @custom:storage-location erc7201:ethsign.tokentable.TTUProjectTokenStorage
struct TTUProjectTokenStorageStorage {
address _projectToken;
}

// keccak256(abi.encode(uint256(keccak256("ethsign.tokentable.TTUProjectTokenStorage")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant TTUProjectTokenStorageStorageLocation =
0xc6cedc2110f0271ccdfaf617b7233d3ed38f0d70138cb74c2dc2c8d098506000;

error TokenSet();

function _getTTUProjectTokenStorageStorage()
internal
pure
returns (TTUProjectTokenStorageStorage storage $)
{
assembly {
$.slot := TTUProjectTokenStorageStorageLocation
}
}

// solhint-disable-next-line ordering
function initializeProjectToken(address projectToken) public {
if (_projectToken != address(0)) revert TokenSet();
_projectToken = projectToken;
TTUProjectTokenStorageStorage
storage $ = _getTTUProjectTokenStorageStorage();
if ($._projectToken != address(0)) revert TokenSet();
$._projectToken = projectToken;
}

function getProjectToken() public view returns (address) {
return _projectToken;
TTUProjectTokenStorageStorage
storage $ = _getTTUProjectTokenStorageStorage();
return $._projectToken;
}

function _initializeSE(address projectToken) internal onlyInitializing {
_projectToken = projectToken;
TTUProjectTokenStorageStorage
storage $ = _getTTUProjectTokenStorageStorage();
$._projectToken = projectToken;
}
}
Loading
Loading