// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import { ERC20, OwnerSettings } from "contracts/core/OwnerSettings.sol"; import { ECDSA } from "contracts/lib/utils/ECDSA.sol"; import { MerkleProofLib as Merkle } from "contracts/lib/utils/MerkleProofLib.sol"; import { ReentrancyGuard } from "contracts/lib/utils/ReentrancyGuard.sol"; abstract contract BaseUtils is OwnerSettings, ReentrancyGuard { /// ███ Storage ████████████████████████████████████████████████████████████ /// @dev List of Pix transactions already signed. /// mapping(bytes32 => bool) public usedTransactions; /// @dev Value in custom storage slot given by: /// let value := sload(bytes32). /// ███ Helper FX ██████████████████████████████████████████████████████████ function _setUsedTransactions(bytes32 message) internal { assembly ("memory-safe") { sstore(message, true) } } function usedTransactions( bytes32 message ) public view returns (bool used) { assembly ("memory-safe") { used := sload(message) } } function _signerCheck( bytes32 _message, bytes calldata _signature ) internal view { if (usedTransactions(_message)) revert TxAlreadyUsed(); if ( !validBacenSigners( _castAddrToKey( ECDSA.recoverCalldata( ECDSA.toEthSignedMessageHash( _message ), _signature ) ) ) ) revert InvalidSigner(); } function _merkleVerify( bytes32[] calldata _merkleProof, bytes32 _root, address _addr ) internal pure { if ( !Merkle.verify( _merkleProof, _root, bytes32(uint256(uint160(_addr))) ) ) revert AddressDenied(); } function _castBool( bool _valid ) internal pure returns (uint256 _validCasted) { assembly ("memory-safe") { _validCasted := _valid } } function getStr( string memory str ) public pure returns (bytes32 strEnc) { bytes memory enc = bytes(abi.encodePacked(str)); assembly ("memory-safe") { if lt(0x20, mload(enc)) { invalid() } strEnc := mload(add(enc, 0x20)) } } function _setSellerBalance( address _sellerKey, ERC20 _erc20, uint256 _packed, bytes32 _pixTarget ) internal { assembly ("memory-safe") { mstore(0x20, _erc20) mstore(0x0c, _SELLER_BALANCE_SLOT_SEED) mstore(0x00, _sellerKey) let _loc := keccak256(0x0c, 0x34) sstore(add(_loc, 0x01), _packed) sstore(_loc, _pixTarget) } } function _setValidState( address _sellerKey, ERC20 _erc20, uint256 _packed ) internal { assembly ("memory-safe") { mstore(0x20, _erc20) mstore(0x0c, _SELLER_BALANCE_SLOT_SEED) mstore(0x00, _sellerKey) let _loc := keccak256(0x0c, 0x34) sstore(add(_loc, 0x01), _packed) } } function _addSellerBalance( address _sellerKey, ERC20 _erc20, uint256 _amount ) internal { assembly ("memory-safe") { mstore(0x20, _erc20) mstore(0x0c, _SELLER_BALANCE_SLOT_SEED) mstore(0x00, _sellerKey) let _loc := add(keccak256(0x0c, 0x34), 0x01) sstore(_loc, add(sload(_loc), _amount)) } } function _decSellerBalance( address _sellerKey, ERC20 _erc20, uint256 _amount ) internal { assembly ("memory-safe") { mstore(0x20, _erc20) mstore(0x0c, _SELLER_BALANCE_SLOT_SEED) mstore(0x00, _sellerKey) let _loc := add(keccak256(0x0c, 0x34), 0x01) sstore(_loc, sub(sload(_loc), _amount)) } } function __sellerBalance( address _sellerKey, ERC20 _erc20 ) internal view returns (uint256 _packed) { assembly ("memory-safe") { mstore(0x20, _erc20) mstore(0x0c, _SELLER_BALANCE_SLOT_SEED) mstore(0x00, _sellerKey) _packed := sload(add(keccak256(0x0c, 0x34), 0x01)) } } /// @notice Public method that handles `address` /// to `uint256` safe type casting. /// @dev Function sighash: 0x4b2ae980. function _castAddrToKey( address _addr ) public pure returns (uint256 _key) { // _key = uint256(uint160(address(_addr))) << 12; assembly ("memory-safe") { _key := shl(0xc, _addr) } } function _castKeyToAddr( uint256 _key ) public pure returns (address _addr) { // _addr = address(uint160(uint256(_key >> 12))); assembly ("memory-safe") { _addr := shr(0xc, _key) } } }