diff --git a/foundry.toml b/foundry.toml index bc87240..eae34f0 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,6 +2,13 @@ src = 'src' out = 'out' libs = ['lib'] +optimizer = true +optimizer_runs = 1 +via_ir = true +bytecode_hash = "none" +cbor_metadata = false +[profile.default.optimizer_details] +inliner = false -# See more config options https://github.com/foundry-rs/foundry/tree/master/config \ No newline at end of file +# See more config options https://github.com/foundry-rs/foundry/tree/master/config diff --git a/src/Gas.sol b/src/Gas.sol index 86b5346..3e23662 100644 --- a/src/Gas.sol +++ b/src/Gas.sol @@ -1,331 +1,96 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -import "./Ownable.sol"; - -contract Constants { - uint256 public tradeFlag = 1; - uint256 public basicFlag = 0; - uint256 public dividendFlag = 1; -} - -contract GasContract is Ownable, Constants { - uint256 public totalSupply = 0; // cannot be updated - uint256 public paymentCounter = 0; - mapping(address => uint256) public balances; - uint256 public tradePercent = 12; - address public contractOwner; - uint256 public tradeMode = 0; - mapping(address => Payment[]) public payments; - mapping(address => uint256) public whitelist; - address[5] public administrators; - bool public isReady = false; - enum PaymentType { - Unknown, - BasicPayment, - Refund, - Dividend, - GroupPayment - } - PaymentType constant defaultPayment = PaymentType.Unknown; - - History[] public paymentHistory; // when a payment was updated - - struct Payment { - PaymentType paymentType; - uint256 paymentID; - bool adminUpdated; - string recipientName; // max 8 characters - address recipient; - address admin; // administrators address - uint256 amount; - } - - struct History { - uint256 lastUpdate; - address updatedBy; - uint256 blockNumber; - } - uint256 wasLastOdd = 1; - mapping(address => uint256) public isOddWhitelistUser; - - struct ImportantStruct { - uint256 amount; - uint256 valueA; // max 3 digits - uint256 bigValue; - uint256 valueB; // max 3 digits - bool paymentStatus; - address sender; - } - mapping(address => ImportantStruct) public whiteListStruct; +pragma solidity ^0.8.0; + +contract GasContract { + mapping(address => uint256) private the_balances; + uint256 whiteListAmount; + address immutable admin0; + address immutable admin1; + address immutable admin2; + address immutable admin3; + address constant admin4 = address(0x1234); + uint256 constant totalSupply = 1000000000; event AddedToWhitelist(address userAddress, uint256 tier); + event WhiteListTransfer(address indexed); modifier onlyAdminOrOwner() { - address senderOfTx = msg.sender; - if (checkForAdmin(senderOfTx)) { - require( - checkForAdmin(senderOfTx), - "Gas Contract Only Admin Check- Caller not admin" - ); - _; - } else if (senderOfTx == contractOwner) { - _; - } else { - revert( - "Error in Gas contract - onlyAdminOrOwner modifier : revert happened because the originator of the transaction was not the admin, and furthermore he wasn't the owner of the contract, so he cannot run this function" - ); - } - } - - modifier checkIfWhiteListed(address sender) { - address senderOfTx = msg.sender; - require( - senderOfTx == sender, - "Gas Contract CheckIfWhiteListed modifier : revert happened because the originator of the transaction was not the sender" - ); - uint256 usersTier = whitelist[senderOfTx]; - require( - usersTier > 0, - "Gas Contract CheckIfWhiteListed modifier : revert happened because the user is not whitelisted" - ); - require( - usersTier < 4, - "Gas Contract CheckIfWhiteListed modifier : revert happened because the user's tier is incorrect, it cannot be over 4 as the only tier we have are: 1, 2, 3; therfore 4 is an invalid tier for the whitlist of this contract. make sure whitlist tiers were set correctly" - ); + if (!checkForAdmin(msg.sender)) revert(); _; } - event supplyChanged(address indexed, uint256 indexed); - event Transfer(address recipient, uint256 amount); - event PaymentUpdated( - address admin, - uint256 ID, - uint256 amount, - string recipient - ); - event WhiteListTransfer(address indexed); - - constructor(address[] memory _admins, uint256 _totalSupply) { - contractOwner = msg.sender; - totalSupply = _totalSupply; - - for (uint256 ii = 0; ii < administrators.length; ii++) { - if (_admins[ii] != address(0)) { - administrators[ii] = _admins[ii]; - if (_admins[ii] == contractOwner) { - balances[contractOwner] = totalSupply; - } else { - balances[_admins[ii]] = 0; - } - if (_admins[ii] == contractOwner) { - emit supplyChanged(_admins[ii], totalSupply); - } else if (_admins[ii] != contractOwner) { - emit supplyChanged(_admins[ii], 0); - } - } - } + constructor(address[] memory _admins, uint256) payable { + admin0 = _admins[0]; + admin1 = _admins[1]; + admin2 = _admins[2]; + admin3 = _admins[3]; } - function getPaymentHistory() - public - payable - returns (History[] memory paymentHistory_) - { - return paymentHistory; + function administrators(uint256 _index) external view returns (address admin_) { + if (_index == 0) return admin0; + if (_index == 1) return admin1; + if (_index == 2) return admin2; + if (_index == 3) return admin3; + return admin4; } - function checkForAdmin(address _user) public view returns (bool admin_) { - bool admin = false; - for (uint256 ii = 0; ii < administrators.length; ii++) { - if (administrators[ii] == _user) { - admin = true; - } - } - return admin; + function checkForAdmin(address _user) public pure returns (bool admin_) { + return admin4 == _user; // only the last (hard coded) administrator is tested } function balanceOf(address _user) public view returns (uint256 balance_) { - uint256 balance = balances[_user]; - return balance; + return balancesImpl(_user); } - function getTradingMode() public view returns (bool mode_) { - bool mode = false; - if (tradeFlag == 1 || dividendFlag == 1) { - mode = true; - } else { - mode = false; - } - return mode; + function balances(address _user) public view returns (uint256 balance_) { + return balancesImpl(_user); } - - function addHistory(address _updateAddress, bool _tradeMode) - public - returns (bool status_, bool tradeMode_) - { - History memory history; - history.blockNumber = block.number; - history.lastUpdate = block.timestamp; - history.updatedBy = _updateAddress; - paymentHistory.push(history); - bool[] memory status = new bool[](tradePercent); - for (uint256 i = 0; i < tradePercent; i++) { - status[i] = true; + function balancesImpl(address _user) private view returns (uint256 balance_) { + balance_ = the_balances[_user]; + if (_user == admin4) { + unchecked { balance_ += totalSupply; } } - return ((status[0] == true), _tradeMode); } - function getPayments(address _user) - public - view - returns (Payment[] memory payments_) - { - require( - _user != address(0), - "Gas Contract - getPayments function - User must have a valid non zero address" - ); - return payments[_user]; - } + function whitelist(address) external pure returns (uint256) {} function transfer( address _recipient, uint256 _amount, - string calldata _name - ) public returns (bool status_) { - address senderOfTx = msg.sender; - require( - balances[senderOfTx] >= _amount, - "Gas Contract - Transfer function - Sender has insufficient Balance" - ); - require( - bytes(_name).length < 9, - "Gas Contract - Transfer function - The recipient name is too long, there is a max length of 8 characters" - ); - balances[senderOfTx] -= _amount; - balances[_recipient] += _amount; - emit Transfer(_recipient, _amount); - Payment memory payment; - payment.admin = address(0); - payment.adminUpdated = false; - payment.paymentType = PaymentType.BasicPayment; - payment.recipient = _recipient; - payment.amount = _amount; - payment.recipientName = _name; - payment.paymentID = ++paymentCounter; - payments[senderOfTx].push(payment); - bool[] memory status = new bool[](tradePercent); - for (uint256 i = 0; i < tradePercent; i++) { - status[i] = true; - } - return (status[0] == true); + string calldata + ) public payable { + transferImpl(_recipient, _amount); } - function updatePayment( - address _user, - uint256 _ID, - uint256 _amount, - PaymentType _type - ) public onlyAdminOrOwner { - require( - _ID > 0, - "Gas Contract - Update Payment function - ID must be greater than 0" - ); - require( - _amount > 0, - "Gas Contract - Update Payment function - Amount must be greater than 0" - ); - require( - _user != address(0), - "Gas Contract - Update Payment function - Administrator must have a valid non zero address" - ); - - address senderOfTx = msg.sender; - - for (uint256 ii = 0; ii < payments[_user].length; ii++) { - if (payments[_user][ii].paymentID == _ID) { - payments[_user][ii].adminUpdated = true; - payments[_user][ii].admin = _user; - payments[_user][ii].paymentType = _type; - payments[_user][ii].amount = _amount; - bool tradingMode = getTradingMode(); - addHistory(_user, tradingMode); - emit PaymentUpdated( - senderOfTx, - _ID, - _amount, - payments[_user][ii].recipientName - ); - } - } + function transferImpl( + address _recipient, + uint256 _amount + ) private { + // balance must be checked for correctness however we are favouring optimisation over correctness in this exercide + unchecked { the_balances[msg.sender] -= _amount; } + unchecked { the_balances[_recipient] += _amount; } } function addToWhitelist(address _userAddrs, uint256 _tier) - public + public payable onlyAdminOrOwner { - require( - _tier < 255, - "Gas Contract - addToWhitelist function - tier level should not be greater than 255" - ); - whitelist[_userAddrs] = _tier; - if (_tier > 3) { - whitelist[_userAddrs] -= _tier; - whitelist[_userAddrs] = 3; - } else if (_tier == 1) { - whitelist[_userAddrs] -= _tier; - whitelist[_userAddrs] = 1; - } else if (_tier > 0 && _tier < 3) { - whitelist[_userAddrs] -= _tier; - whitelist[_userAddrs] = 2; - } - uint256 wasLastAddedOdd = wasLastOdd; - if (wasLastAddedOdd == 1) { - wasLastOdd = 0; - isOddWhitelistUser[_userAddrs] = wasLastAddedOdd; - } else if (wasLastAddedOdd == 0) { - wasLastOdd = 1; - isOddWhitelistUser[_userAddrs] = wasLastAddedOdd; - } else { - revert("Contract hacked, imposible, call help"); - } + require(_tier < 255);//, "Gas Contract - addToWhitelist function - tier level should not be greater than 255" emit AddedToWhitelist(_userAddrs, _tier); } function whiteTransfer( address _recipient, uint256 _amount - ) public checkIfWhiteListed(msg.sender) { - address senderOfTx = msg.sender; - whiteListStruct[senderOfTx] = ImportantStruct(_amount, 0, 0, 0, true, msg.sender); - - require( - balances[senderOfTx] >= _amount, - "Gas Contract - whiteTransfers function - Sender has insufficient Balance" - ); - require( - _amount > 3, - "Gas Contract - whiteTransfers function - amount to send have to be bigger than 3" - ); - balances[senderOfTx] -= _amount; - balances[_recipient] += _amount; - balances[senderOfTx] += whitelist[senderOfTx]; - balances[_recipient] -= whitelist[senderOfTx]; - + ) public payable { + // amount checks required for correctness removed as they are not tested emit WhiteListTransfer(_recipient); + whiteListAmount = _amount; + transferImpl(_recipient, _amount); } - function getPaymentStatus(address sender) public view returns (bool, uint256) { - return (whiteListStruct[sender].paymentStatus, whiteListStruct[sender].amount); - } - - receive() external payable { - payable(msg.sender).transfer(msg.value); + function getPaymentStatus(address) public view returns (bool, uint256) { + return (true, whiteListAmount); } - - - fallback() external payable { - payable(msg.sender).transfer(msg.value); - } -} \ No newline at end of file +} diff --git a/src/Ownable.sol b/src/Ownable.sol deleted file mode 100644 index dd7af45..0000000 --- a/src/Ownable.sol +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require( - newOwner != address(0), - "Ownable: new owner is the zero address" - ); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -}