Skip to content

Commit

Permalink
Use storage slot for upgradeable contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
ScreamingHawk committed May 29, 2023
1 parent 9770473 commit a79ce8c
Show file tree
Hide file tree
Showing 19 changed files with 5,112 additions and 4,895 deletions.
2 changes: 1 addition & 1 deletion src/contracts/mocks/ERC1155MetadataUpgradeableMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@ contract ERC1155MetadataUpgradeableMockV2 is ERC1155MetadataUpgradeableMock {
}

function uri(uint256 _id) public override view returns (string memory) {
return string(abi.encodePacked(baseURI, _uint2str(idMapping[_id]))); // Removes .json extension, swaps ids
return string(abi.encodePacked(baseURI(), _uint2str(idMapping[_id]))); // Removes .json extension, swaps ids
}
}
7 changes: 4 additions & 3 deletions src/contracts/tokens/ERC1155/ERC1155Meta.sol
Original file line number Diff line number Diff line change
Expand Up @@ -294,12 +294,13 @@ contract ERC1155Meta is ERC1155, SignatureValidator {
// Complete data to pass to signer verifier
bytes memory fullData = abi.encodePacked(_encMembers, nonce, signedData);

//Update signature nonce
// Verify if _from is the signer
require(isValidSignature(_signer, hash, fullData, sig), "ERC1155Meta#_signatureValidation: INVALID_SIGNATURE");

// Update signature nonce
nonces[_signer] = nonce + 1;
emit NonceChange(_signer, nonce + 1);

// Verify if _from is the signer
require(isValidSignature(_signer, hash, fullData, sig), "ERC1155Meta#_signatureValidation: INVALID_SIGNATURE");
return signedData;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "../../interfaces/IERC20.sol";
import "../../interfaces/IERC1155.sol";
import "../../utils/LibBytes.sol";
import "../../utils/SignatureValidator.sol";

import '../../utils/StorageSlot.sol';

/**
* @dev ERC-1155 with native metatransaction methods. These additional functions allow users
Expand Down Expand Up @@ -45,7 +45,7 @@ contract ERC1155MetaPackedBalanceUpgradeable is ERC1155PackedBalanceUpgradeable,
}

// Signature nonce per address
mapping (address => uint256) internal nonces;
bytes32 constant private _NONCES_SLOT_KEY = keccak256("0xsequence.ERC1155MetaPackedBalanceUpgradeable.nonces");


/***********************************|
Expand Down Expand Up @@ -227,7 +227,7 @@ contract ERC1155MetaPackedBalanceUpgradeable is ERC1155PackedBalanceUpgradeable,
);

// Update operator status
operators[_owner][_operator] = _approved;
_setOperator(_owner, _operator, _approved);

// Emit event
emit ApprovalForAll(_owner, _operator, _approved);
Expand Down Expand Up @@ -284,8 +284,8 @@ contract ERC1155MetaPackedBalanceUpgradeable is ERC1155PackedBalanceUpgradeable,
(sig, signedData) = abi.decode(_sigData, (bytes, bytes));

// Get current nonce and nonce used for signature
uint256 currentNonce = nonces[_signer]; // Lowest valid nonce for signer
uint256 nonce = uint256(sig.readBytes32(65)); // Nonce passed in the signature object
uint256 currentNonce = _getNonce(_signer); // Lowest valid nonce for signer
uint256 nonce = uint256(sig.readBytes32(65)); // Nonce passed in the signature object

// Verify if nonce is valid
require(
Expand All @@ -300,8 +300,9 @@ contract ERC1155MetaPackedBalanceUpgradeable is ERC1155PackedBalanceUpgradeable,
bytes memory fullData = abi.encodePacked(_encMembers, nonce, signedData);

//Update signature nonce
nonces[_signer] = nonce + 1;
emit NonceChange(_signer, nonce + 1);
nonce++;
_setNonce(_signer, nonce);
emit NonceChange(_signer, nonce);

// Verify if _from is the signer
require(isValidSignature(_signer, hash, fullData, sig), "ERC1155MetaPackedBalance#_signatureValidation: INVALID_SIGNATURE");
Expand All @@ -315,7 +316,26 @@ contract ERC1155MetaPackedBalanceUpgradeable is ERC1155PackedBalanceUpgradeable,
function getNonce(address _signer)
public view returns (uint256 nonce)
{
return nonces[_signer];
return _getNonce(_signer);
}

/**
* @notice Returns the current nonce associated with a given address
* @param _signer Address to query signature nonce for
*/
function _getNonce(address _signer)
internal view returns (uint256 nonce)
{
return StorageSlot.getUint256Slot(keccak256(abi.encodePacked(_NONCES_SLOT_KEY, _signer))).value;
}

/**
* @notice Sets the nonce associated with a given address
* @param _signer Address to set signature nonce for
* @param _nonce Nonce value to set
*/
function _setNonce(address _signer, uint256 _nonce) internal {
StorageSlot.getUint256Slot(keccak256(abi.encodePacked(_NONCES_SLOT_KEY, _signer))).value = _nonce;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ contract ERC1155MintBurnPackedBalanceUpgradeable is ERC1155PackedBalanceUpgradea
(uint256 bin, uint256 index) = getIDBinIndex(_ids[0]);

// Balance for current bin in memory (initialized with first transfer)
uint256 balTo = _viewUpdateBinValue(balances[_to][bin], index, _amounts[0], Operations.Add);
uint256 balTo = _viewUpdateBinValue(_getBalance(_to, bin), index, _amounts[0], Operations.Add);

// Number of transfer to execute
uint256 nTransfer = _ids.length;
Expand All @@ -65,8 +65,8 @@ contract ERC1155MintBurnPackedBalanceUpgradeable is ERC1155PackedBalanceUpgradea
// If new bin
if (bin != lastBin) {
// Update storage balance of previous bin
balances[_to][lastBin] = balTo;
balTo = balances[_to][bin];
_setBalance(_to, lastBin, balTo);
balTo = _getBalance(_to, bin);

// Bin will be the most recent bin
lastBin = bin;
Expand All @@ -77,7 +77,7 @@ contract ERC1155MintBurnPackedBalanceUpgradeable is ERC1155PackedBalanceUpgradea
}

// Update storage of the last bin visited
balances[_to][bin] = balTo;
_setBalance(_to, bin, balTo);
}

// //Emit event
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "../../interfaces/IERC1155.sol";
import "../../utils/Address.sol";
import "../../utils/ContextUpgradeable.sol";
import "../../utils/ERC165.sol";
import '../../utils/StorageSlot.sol';

/**
* @dev Implementation of Multi-Token Standard contract. This implementation of the ERC-1155 standard
Expand Down Expand Up @@ -35,10 +36,10 @@ contract ERC1155PackedBalanceUpgradeable is ContextUpgradeable, IERC1155, ERC165
enum Operations { Add, Sub }

// Token IDs balances ; balances[address][id] => balance (using array instead of mapping for efficiency)
mapping (address => mapping(uint256 => uint256)) internal balances;
bytes32 constant private _BALANCES_SLOT_KEY = keccak256("0xsequence.ERC1155PackedBalanceUpgradeable.balances");

// Operators
mapping (address => mapping(address => bool)) internal operators;
bytes32 constant private _OPERATORS_SLOT_KEY = keccak256("0xsequence.ERC1155PackedBalanceUpgradeable.operators");


/***********************************|
Expand Down Expand Up @@ -140,8 +141,8 @@ contract ERC1155PackedBalanceUpgradeable is ContextUpgradeable, IERC1155, ERC165
(uint256 bin, uint256 index) = getIDBinIndex(_ids[0]);

// Balance for current bin in memory (initialized with first transfer)
uint256 balFrom = _viewUpdateBinValue(balances[_from][bin], index, _amounts[0], Operations.Sub);
uint256 balTo = _viewUpdateBinValue(balances[_to][bin], index, _amounts[0], Operations.Add);
uint256 balFrom = _viewUpdateBinValue(_getBalance(_from, bin), index, _amounts[0], Operations.Sub);
uint256 balTo = _viewUpdateBinValue(_getBalance(_to, bin), index, _amounts[0], Operations.Add);

// Last bin updated
uint256 lastBin = bin;
Expand All @@ -152,11 +153,11 @@ contract ERC1155PackedBalanceUpgradeable is ContextUpgradeable, IERC1155, ERC165
// If new bin
if (bin != lastBin) {
// Update storage balance of previous bin
balances[_from][lastBin] = balFrom;
balances[_to][lastBin] = balTo;
_setBalance(_from, lastBin, balFrom);
_setBalance(_to, lastBin, balTo);

balFrom = balances[_from][bin];
balTo = balances[_to][bin];
balFrom = _getBalance(_from, bin);
balTo = _getBalance(_to, bin);

// Bin will be the most recent bin
lastBin = bin;
Expand All @@ -168,8 +169,8 @@ contract ERC1155PackedBalanceUpgradeable is ContextUpgradeable, IERC1155, ERC165
}

// Update storage of the last bin visited
balances[_from][bin] = balFrom;
balances[_to][bin] = balTo;
_setBalance(_from, bin, balFrom);
_setBalance(_to, bin, balTo);

// If transfer to self, just make sure all amounts are valid
} else {
Expand Down Expand Up @@ -209,7 +210,7 @@ contract ERC1155PackedBalanceUpgradeable is ContextUpgradeable, IERC1155, ERC165
external override
{
// Update operator status
operators[_msgSender()][_operator] = _approved;
_setOperator(_msgSender(), _operator, _approved);
emit ApprovalForAll(_msgSender(), _operator, _approved);
}

Expand All @@ -222,7 +223,7 @@ contract ERC1155PackedBalanceUpgradeable is ContextUpgradeable, IERC1155, ERC165
function isApprovedForAll(address _owner, address _operator)
public override view returns (bool isOperator)
{
return operators[_owner][_operator];
return _getOperator(_owner, _operator);
}


Expand All @@ -244,7 +245,7 @@ contract ERC1155PackedBalanceUpgradeable is ContextUpgradeable, IERC1155, ERC165

//Get bin and index of _id
(bin, index) = getIDBinIndex(_id);
return getValueInBin(balances[_owner][bin], index);
return getValueInBin(_getBalance(_owner, bin), index);
}

/**
Expand All @@ -261,7 +262,7 @@ contract ERC1155PackedBalanceUpgradeable is ContextUpgradeable, IERC1155, ERC165

// First values
(uint256 bin, uint256 index) = getIDBinIndex(_ids[0]);
uint256 balance_bin = balances[_owners[0]][bin];
uint256 balance_bin = _getBalance(_owners[0], bin);
uint256 last_bin = bin;

// Initialization
Expand All @@ -274,7 +275,7 @@ contract ERC1155PackedBalanceUpgradeable is ContextUpgradeable, IERC1155, ERC165

// SLOAD if bin changed for the same owner or if owner changed
if (bin != last_bin || _owners[i-1] != _owners[i]) {
balance_bin = balances[_owners[i]][bin];
balance_bin = _getBalance(_owners[i], bin);
last_bin = bin;
}

Expand Down Expand Up @@ -308,7 +309,7 @@ contract ERC1155PackedBalanceUpgradeable is ContextUpgradeable, IERC1155, ERC165
(bin, index) = getIDBinIndex(_id);

// Update balance
balances[_address][bin] = _viewUpdateBinValue(balances[_address][bin], index, _amount, _operation);
_setBalance(_address, bin, _viewUpdateBinValue(_getBalance(_address, bin), index, _amount, _operation));
}

/**
Expand Down Expand Up @@ -379,6 +380,26 @@ contract ERC1155PackedBalanceUpgradeable is ContextUpgradeable, IERC1155, ERC165
return (_binValues >> rightShift) & mask;
}

/***********************************|
| Storage Functions |
|__________________________________*/

function _getBalance(address _owner, uint256 _id) internal view returns (uint256) {
return StorageSlot.getUint256Slot(keccak256(abi.encodePacked(_BALANCES_SLOT_KEY, _owner, _id))).value;
}

function _setBalance(address _owner, uint256 _id, uint256 _balance) internal {
StorageSlot.getUint256Slot(keccak256(abi.encodePacked(_BALANCES_SLOT_KEY, _owner, _id))).value = _balance;
}

function _getOperator(address _owner, address _operator) internal view returns (bool) {
return StorageSlot.getBooleanSlot(keccak256(abi.encodePacked(_OPERATORS_SLOT_KEY, _owner, _operator))).value;
}

function _setOperator(address _owner, address _operator, bool _approved) internal {
StorageSlot.getBooleanSlot(keccak256(abi.encodePacked(_OPERATORS_SLOT_KEY, _owner, _operator))).value = _approved;
}


/***********************************|
| ERC165 Functions |
Expand Down
41 changes: 31 additions & 10 deletions src/contracts/tokens/ERC1155Upgradeable/ERC1155MetaUpgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "../../interfaces/IERC20.sol";
import "../../interfaces/IERC1155.sol";
import "../../utils/LibBytes.sol";
import "../../utils/SignatureValidator.sol";
import '../../utils/StorageSlot.sol';

/**
* @dev ERC-1155 with native metatransaction methods. These additional functions allow users
Expand Down Expand Up @@ -41,8 +42,7 @@ contract ERC1155MetaUpgradeable is ERC1155Upgradeable, SignatureValidator {
}

// Signature nonce per address
mapping (address => uint256) internal nonces;

bytes32 constant private _NONCES_SLOT_KEY = keccak256("0xsequence.ERC1155MetaUpgradeable.nonces");

/***********************************|
| Events |
Expand Down Expand Up @@ -223,7 +223,7 @@ contract ERC1155MetaUpgradeable is ERC1155Upgradeable, SignatureValidator {
);

// Update operator status
operators[_owner][_operator] = _approved;
_setOperator(_owner, _operator, _approved);

// Emit event
emit ApprovalForAll(_owner, _operator, _approved);
Expand Down Expand Up @@ -279,8 +279,8 @@ contract ERC1155MetaUpgradeable is ERC1155Upgradeable, SignatureValidator {
(sig, signedData) = abi.decode(_sigData, (bytes, bytes));

// Get current nonce and nonce used for signature
uint256 currentNonce = nonces[_signer]; // Lowest valid nonce for signer
uint256 nonce = uint256(sig.readBytes32(65)); // Nonce passed in the signature object
uint256 currentNonce = _getNonce(_signer); // Lowest valid nonce for signer
uint256 nonce = uint256(sig.readBytes32(65)); // Nonce passed in the signature object

// Verify if nonce is valid
require(
Expand All @@ -294,12 +294,14 @@ contract ERC1155MetaUpgradeable is ERC1155Upgradeable, SignatureValidator {
// Complete data to pass to signer verifier
bytes memory fullData = abi.encodePacked(_encMembers, nonce, signedData);

//Update signature nonce
nonces[_signer] = nonce + 1;
emit NonceChange(_signer, nonce + 1);

// Verify if _from is the signer
require(isValidSignature(_signer, hash, fullData, sig), "ERC1155Meta#_signatureValidation: INVALID_SIGNATURE");

// Update signature nonce
nonce++;
_setNonce(_signer, nonce);
emit NonceChange(_signer, nonce);

return signedData;
}

Expand All @@ -310,7 +312,26 @@ contract ERC1155MetaUpgradeable is ERC1155Upgradeable, SignatureValidator {
function getNonce(address _signer)
public view returns (uint256 nonce)
{
return nonces[_signer];
return _getNonce(_signer);
}

/**
* @notice Returns the current nonce associated with a given address
* @param _signer Address to query signature nonce for
*/
function _getNonce(address _signer)
internal view returns (uint256 nonce)
{
return StorageSlot.getUint256Slot(keccak256(abi.encodePacked(_NONCES_SLOT_KEY, _signer))).value;
}

/**
* @notice Sets the nonce associated with a given address
* @param _signer Address to set signature nonce for
* @param _nonce Nonce value to set
*/
function _setNonce(address _signer, uint256 _nonce) internal {
StorageSlot.getUint256Slot(keccak256(abi.encodePacked(_NONCES_SLOT_KEY, _signer))).value = _nonce;
}


Expand Down
Loading

0 comments on commit a79ce8c

Please sign in to comment.