diff --git a/contracts/contracts/libraries/usdc/MasterMinter.sol.flatten b/contracts/contracts/libraries/usdc/MasterMinter.sol.flatten new file mode 100644 index 00000000..94eb3dc2 --- /dev/null +++ b/contracts/contracts/libraries/usdc/MasterMinter.sol.flatten @@ -0,0 +1,676 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity <0.8.0 =0.6.12 >=0.6.0; + +// contracts/minting/MinterManagementInterface.sol +/** + * Copyright 2023 Circle Internet Group, Inc. All rights reserved. + * + + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @dev A contract that implements the MinterManagementInterface has external + * functions for adding and removing minters and modifying their allowances. + * An example is the FiatTokenV1 contract. + */ +interface MinterManagementInterface { + function isMinter(address _account) external view returns (bool); + + function minterAllowance(address _minter) external view returns (uint256); + + function configureMinter(address _minter, uint256 _minterAllowedAmount) + external + returns (bool); + + function removeMinter(address _minter) external returns (bool); +} + +// contracts/v1/Ownable.sol +/** + + * + * Copyright (c) 2018 zOS Global Limited. + * Copyright (c) 2018-2020 CENTRE SECZ + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @notice The Ownable contract has an owner address, and provides basic + * authorization control functions + * @dev Forked from https://github.com/OpenZeppelin/openzeppelin-labs/blob/3887ab77b8adafba4a26ace002f3a684c1a3388b/upgradeability_ownership/contracts/ownership/Ownable.sol + * Modifications: + * 1. Consolidate OwnableStorage into this contract (7/13/18) + * 2. Reformat, conform to Solidity 0.6 syntax, and add error messages (5/13/20) + * 3. Make public functions external (5/27/20) + */ +contract Ownable { + // Owner of the contract + address private _owner; + + /** + * @dev Event to show ownership has been transferred + * @param previousOwner representing the address of the previous owner + * @param newOwner representing the address of the new owner + */ + event OwnershipTransferred(address previousOwner, address newOwner); + + /** + * @dev The constructor sets the original owner of the contract to the sender account. + */ + constructor() public { + setOwner(msg.sender); + } + + /** + * @dev Tells the address of the owner + * @return the address of the owner + */ + function owner() external view returns (address) { + return _owner; + } + + /** + * @dev Sets a new owner address + */ + function setOwner(address newOwner) internal { + _owner = newOwner; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == _owner, "Ownable: caller is not the owner"); + _; + } + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) external onlyOwner { + require( + newOwner != address(0), + "Ownable: new owner is the zero address" + ); + emit OwnershipTransferred(_owner, newOwner); + setOwner(newOwner); + } +} + +// node_modules/@openzeppelin/contracts/math/SafeMath.sol + +/** + * @dev Wrappers over Solidity's arithmetic operations with added overflow + * checks. + * + * Arithmetic operations in Solidity wrap on overflow. This can easily result + * in bugs, because programmers usually assume that an overflow raises an + * error, which is the standard behavior in high level programming languages. + * `SafeMath` restores this intuition by reverting the transaction when an + * operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + */ +library SafeMath { + /** + * @dev Returns the addition of two unsigned integers, with an overflow flag. + * + * _Available since v3.4._ + */ + function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { + uint256 c = a + b; + if (c < a) return (false, 0); + return (true, c); + } + + /** + * @dev Returns the substraction of two unsigned integers, with an overflow flag. + * + * _Available since v3.4._ + */ + function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { + if (b > a) return (false, 0); + return (true, a - b); + } + + /** + * @dev Returns the multiplication of two unsigned integers, with an overflow flag. + * + * _Available since v3.4._ + */ + function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) return (true, 0); + uint256 c = a * b; + if (c / a != b) return (false, 0); + return (true, c); + } + + /** + * @dev Returns the division of two unsigned integers, with a division by zero flag. + * + * _Available since v3.4._ + */ + function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { + if (b == 0) return (false, 0); + return (true, a / b); + } + + /** + * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. + * + * _Available since v3.4._ + */ + function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { + if (b == 0) return (false, 0); + return (true, a % b); + } + + /** + * @dev Returns the addition of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * + * - Addition cannot overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a, "SafeMath: addition overflow"); + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + require(b <= a, "SafeMath: subtraction overflow"); + return a - b; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * + * - Multiplication cannot overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + if (a == 0) return 0; + uint256 c = a * b; + require(c / a == b, "SafeMath: multiplication overflow"); + return c; + } + + /** + * @dev Returns the integer division of two unsigned integers, reverting on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + require(b > 0, "SafeMath: division by zero"); + return a / b; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * reverting when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b) internal pure returns (uint256) { + require(b > 0, "SafeMath: modulo by zero"); + return a % b; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting with custom message on + * overflow (when the result is negative). + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {trySub}. + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b <= a, errorMessage); + return a - b; + } + + /** + * @dev Returns the integer division of two unsigned integers, reverting with custom message on + * division by zero. The result is rounded towards zero. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryDiv}. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b > 0, errorMessage); + return a / b; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * reverting with custom message when dividing by zero. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryMod}. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b > 0, errorMessage); + return a % b; + } +} + +// contracts/minting/Controller.sol +/** + * Copyright 2023 Circle Internet Group, Inc. All rights reserved. + * + + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @title Controller + * @notice Generic implementation of the owner-controller-worker model. + * One owner manages many controllers. Each controller manages one worker. + * Workers may be reused across different controllers. + */ +contract Controller is Ownable { + /** + * @dev A controller manages a single worker address. + * controllers[controller] = worker + */ + mapping(address => address) internal controllers; + + event ControllerConfigured( + address indexed _controller, + address indexed _worker + ); + event ControllerRemoved(address indexed _controller); + + /** + * @notice Ensures that caller is the controller of a non-zero worker + * address. + */ + modifier onlyController() { + require( + controllers[msg.sender] != address(0), + "The value of controllers[msg.sender] must be non-zero" + ); + _; + } + + /** + * @notice Gets the worker at address _controller. + */ + function getWorker(address _controller) external view returns (address) { + return controllers[_controller]; + } + + // onlyOwner functions + + /** + * @notice Configure a controller with the given worker. + * @param _controller The controller to be configured with a worker. + * @param _worker The worker to be set for the newly configured controller. + * _worker must not be a non-zero address. To disable a worker, + * use removeController instead. + */ + function configureController(address _controller, address _worker) + public + onlyOwner + { + require( + _controller != address(0), + "Controller must be a non-zero address" + ); + require(_worker != address(0), "Worker must be a non-zero address"); + controllers[_controller] = _worker; + emit ControllerConfigured(_controller, _worker); + } + + /** + * @notice disables a controller by setting its worker to address(0). + * @param _controller The controller to disable. + */ + function removeController(address _controller) public onlyOwner { + require( + _controller != address(0), + "Controller must be a non-zero address" + ); + require( + controllers[_controller] != address(0), + "Worker must be a non-zero address" + ); + controllers[_controller] = address(0); + emit ControllerRemoved(_controller); + } +} + +// contracts/minting/MintController.sol +/** + * Copyright 2023 Circle Internet Group, Inc. All rights reserved. + * + + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// solhint-disable func-name-mixedcase + +/** + * @title MintController + * @dev The MintController contract manages minters for a contract that + * implements the MinterManagerInterface. It lets the owner designate certain + * addresses as controllers, and these controllers then manage the + * minters by adding and removing minters, as well as modifying their minting + * allowance. A controller may manage exactly one minter, but the same minter + * address may be managed by multiple controllers. + * MintController inherits from the Controller contract. It treats the + * Controller workers as minters. + */ +contract MintController is Controller { + using SafeMath for uint256; + + /** + * @dev MintController calls the minterManager to execute/record minter + * management tasks, as well as to query the status of a minter address. + */ + MinterManagementInterface internal minterManager; + + event MinterManagerSet( + address indexed _oldMinterManager, + address indexed _newMinterManager + ); + event MinterConfigured( + address indexed _msgSender, + address indexed _minter, + uint256 _allowance + ); + event MinterRemoved(address indexed _msgSender, address indexed _minter); + event MinterAllowanceIncremented( + address indexed _msgSender, + address indexed _minter, + uint256 _increment, + uint256 _newAllowance + ); + + event MinterAllowanceDecremented( + address indexed msgSender, + address indexed minter, + uint256 decrement, + uint256 newAllowance + ); + + /** + * @notice Initializes the minterManager. + * @param _minterManager The address of the minterManager contract. + */ + constructor(address _minterManager) public { + minterManager = MinterManagementInterface(_minterManager); + } + + /** + * @notice gets the minterManager + */ + function getMinterManager() + external + view + returns (MinterManagementInterface) + { + return minterManager; + } + + // onlyOwner functions + + /** + * @notice Sets the minterManager. + * @param _newMinterManager The address of the new minterManager contract. + */ + function setMinterManager(address _newMinterManager) public onlyOwner { + emit MinterManagerSet(address(minterManager), _newMinterManager); + minterManager = MinterManagementInterface(_newMinterManager); + } + + // onlyController functions + + /** + * @notice Removes the controller's own minter. + */ + function removeMinter() public onlyController returns (bool) { + address minter = controllers[msg.sender]; + emit MinterRemoved(msg.sender, minter); + return minterManager.removeMinter(minter); + } + + /** + * @notice Enables the minter and sets its allowance. + * @param _newAllowance New allowance to be set for minter. + */ + function configureMinter(uint256 _newAllowance) + public + onlyController + returns (bool) + { + address minter = controllers[msg.sender]; + emit MinterConfigured(msg.sender, minter, _newAllowance); + return internal_setMinterAllowance(minter, _newAllowance); + } + + /** + * @notice Increases the minter's allowance if and only if the minter is an + * active minter. + * @dev An minter is considered active if minterManager.isMinter(minter) + * returns true. + */ + function incrementMinterAllowance(uint256 _allowanceIncrement) + public + onlyController + returns (bool) + { + require( + _allowanceIncrement > 0, + "Allowance increment must be greater than 0" + ); + address minter = controllers[msg.sender]; + require( + minterManager.isMinter(minter), + "Can only increment allowance for minters in minterManager" + ); + + uint256 currentAllowance = minterManager.minterAllowance(minter); + uint256 newAllowance = currentAllowance.add(_allowanceIncrement); + + emit MinterAllowanceIncremented( + msg.sender, + minter, + _allowanceIncrement, + newAllowance + ); + + return internal_setMinterAllowance(minter, newAllowance); + } + + /** + * @notice decreases the minter allowance if and only if the minter is + * currently active. The controller can safely send a signed + * decrementMinterAllowance() transaction to a minter and not worry + * about it being used to undo a removeMinter() transaction. + */ + function decrementMinterAllowance(uint256 _allowanceDecrement) + public + onlyController + returns (bool) + { + require( + _allowanceDecrement > 0, + "Allowance decrement must be greater than 0" + ); + address minter = controllers[msg.sender]; + require( + minterManager.isMinter(minter), + "Can only decrement allowance for minters in minterManager" + ); + + uint256 currentAllowance = minterManager.minterAllowance(minter); + uint256 actualAllowanceDecrement = ( + currentAllowance > _allowanceDecrement + ? _allowanceDecrement + : currentAllowance + ); + uint256 newAllowance = currentAllowance.sub(actualAllowanceDecrement); + + emit MinterAllowanceDecremented( + msg.sender, + minter, + actualAllowanceDecrement, + newAllowance + ); + + return internal_setMinterAllowance(minter, newAllowance); + } + + // Internal functions + + /** + * @notice Uses the MinterManagementInterface to enable the minter and + * set its allowance. + * @param _minter Minter to set new allowance of. + * @param _newAllowance New allowance to be set for minter. + */ + function internal_setMinterAllowance(address _minter, uint256 _newAllowance) + internal + returns (bool) + { + return minterManager.configureMinter(_minter, _newAllowance); + } +} + +// contracts/minting/MasterMinter.sol +/** + * Copyright 2023 Circle Internet Group, Inc. All rights reserved. + * + + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @title MasterMinter + * @notice MasterMinter uses multiple controllers to manage minters for a + * contract that implements the MinterManagerInterface. + * @dev MasterMinter inherits all its functionality from MintController. + */ +contract MasterMinter is MintController { + constructor(address _minterManager) public MintController(_minterManager) {} +}