diff --git a/.github/workflows/contracts-tests.yml b/.github/workflows/contracts-tests.yml index 1bbf76d..347295b 100644 --- a/.github/workflows/contracts-tests.yml +++ b/.github/workflows/contracts-tests.yml @@ -25,3 +25,7 @@ jobs: - name: Run tests run: forge test -vvv working-directory: ./contracts + + - name: Enforce Formatting + run: forge fmt --check + working-directory: ./contracts diff --git a/contracts/script/IncredibleSquaringDeployer.s.sol b/contracts/script/IncredibleSquaringDeployer.s.sol index e8c661e..c79622b 100644 --- a/contracts/script/IncredibleSquaringDeployer.s.sol +++ b/contracts/script/IncredibleSquaringDeployer.s.sol @@ -11,16 +11,21 @@ import {StrategyBaseTVLLimits} from "@eigenlayer/contracts/strategies/StrategyBa import "@eigenlayer/test/mocks/EmptyContract.sol"; import "@eigenlayer-middleware/src/RegistryCoordinator.sol" as regcoord; -import {IBLSApkRegistry, IIndexRegistry, IStakeRegistry} from "@eigenlayer-middleware/src/RegistryCoordinator.sol"; +import { + IBLSApkRegistry, + IIndexRegistry, + IStakeRegistry, + IServiceManager +} from "@eigenlayer-middleware/src/RegistryCoordinator.sol"; import {BLSApkRegistry} from "@eigenlayer-middleware/src/BLSApkRegistry.sol"; import {IndexRegistry} from "@eigenlayer-middleware/src/IndexRegistry.sol"; import {StakeRegistry} from "@eigenlayer-middleware/src/StakeRegistry.sol"; import "@eigenlayer-middleware/src/OperatorStateRetriever.sol"; -import {IncredibleSquaringServiceManager, IServiceManager} from "../src/IncredibleSquaringServiceManager.sol"; +import {IncredibleSquaringServiceManager} from "../src/IncredibleSquaringServiceManager.sol"; import {IncredibleSquaringTaskManager} from "../src/IncredibleSquaringTaskManager.sol"; import {IIncredibleSquaringTaskManager} from "../src/IIncredibleSquaringTaskManager.sol"; -import "../src/ERC20Mock.sol"; +import {ERC20Mock} from "../src/ERC20Mock.sol"; import {Utils} from "./utils/Utils.sol"; @@ -37,10 +42,8 @@ contract IncredibleSquaringDeployer is Script, Utils { uint32 public constant TASK_RESPONSE_WINDOW_BLOCK = 30; uint32 public constant TASK_DURATION_BLOCKS = 0; // TODO: right now hardcoding these (this address is anvil's default address 9) - address public constant AGGREGATOR_ADDR = - 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720; - address public constant TASK_GENERATOR_ADDR = - 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720; + address public constant AGGREGATOR_ADDR = 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720; + address public constant TASK_GENERATOR_ADDR = 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720; // ERC20 and Strategy: we need to deploy this erc20, create a strategy for it, and whitelist this strategy in the strategymanager @@ -69,60 +72,32 @@ contract IncredibleSquaringDeployer is Script, Utils { IServiceManager public incredibleSquaringServiceManagerImplementation; IncredibleSquaringTaskManager public incredibleSquaringTaskManager; - IIncredibleSquaringTaskManager - public incredibleSquaringTaskManagerImplementation; + IIncredibleSquaringTaskManager public incredibleSquaringTaskManagerImplementation; function run() external { // Eigenlayer contracts - string memory eigenlayerDeployedContracts = readOutput( - "eigenlayer_deployment_output" - ); - IStrategyManager strategyManager = IStrategyManager( - stdJson.readAddress( - eigenlayerDeployedContracts, - ".addresses.strategyManager" - ) - ); - IDelegationManager delegationManager = IDelegationManager( - stdJson.readAddress( - eigenlayerDeployedContracts, - ".addresses.delegation" - ) - ); - ProxyAdmin eigenLayerProxyAdmin = ProxyAdmin( - stdJson.readAddress( - eigenlayerDeployedContracts, - ".addresses.eigenLayerProxyAdmin" - ) - ); - PauserRegistry eigenLayerPauserReg = PauserRegistry( - stdJson.readAddress( - eigenlayerDeployedContracts, - ".addresses.eigenLayerPauserReg" - ) - ); + string memory eigenlayerDeployedContracts = readOutput("eigenlayer_deployment_output"); + IStrategyManager strategyManager = + IStrategyManager(stdJson.readAddress(eigenlayerDeployedContracts, ".addresses.strategyManager")); + IDelegationManager delegationManager = + IDelegationManager(stdJson.readAddress(eigenlayerDeployedContracts, ".addresses.delegation")); + ProxyAdmin eigenLayerProxyAdmin = + ProxyAdmin(stdJson.readAddress(eigenlayerDeployedContracts, ".addresses.eigenLayerProxyAdmin")); + PauserRegistry eigenLayerPauserReg = + PauserRegistry(stdJson.readAddress(eigenlayerDeployedContracts, ".addresses.eigenLayerPauserReg")); StrategyBaseTVLLimits baseStrategyImplementation = StrategyBaseTVLLimits( - stdJson.readAddress( - eigenlayerDeployedContracts, - ".addresses.baseStrategyImplementation" - ) - ); + stdJson.readAddress(eigenlayerDeployedContracts, ".addresses.baseStrategyImplementation") + ); address credibleSquaringCommunityMultisig = msg.sender; address credibleSquaringPauser = msg.sender; vm.startBroadcast(); _deployErc20AndStrategyAndWhitelistStrategy( - eigenLayerProxyAdmin, - eigenLayerPauserReg, - baseStrategyImplementation, - strategyManager + eigenLayerProxyAdmin, eigenLayerPauserReg, baseStrategyImplementation, strategyManager ); _deployCredibleSquaringContracts( - delegationManager, - erc20MockStrategy, - credibleSquaringCommunityMultisig, - credibleSquaringPauser + delegationManager, erc20MockStrategy, credibleSquaringCommunityMultisig, credibleSquaringPauser ); vm.stopBroadcast(); } @@ -145,7 +120,7 @@ contract IncredibleSquaringDeployer is Script, Utils { StrategyBaseTVLLimits.initialize.selector, 1 ether, // maxPerDeposit 100 ether, // maxDeposits - IERC20(erc20Mock), + erc20Mock, eigenLayerPauserReg ) ) @@ -165,7 +140,7 @@ contract IncredibleSquaringDeployer is Script, Utils { // Adding this as a temporary fix to make the rest of the script work with a single strategy // since it was originally written to work with an array of strategies IStrategy[1] memory deployedStrategyArray = [strat]; - uint numStrategies = deployedStrategyArray.length; + uint256 numStrategies = deployedStrategyArray.length; // deploy proxy admin for ability to upgrade proxy contracts incredibleSquaringProxyAdmin = new ProxyAdmin(); @@ -175,10 +150,7 @@ contract IncredibleSquaringDeployer is Script, Utils { address[] memory pausers = new address[](2); pausers[0] = credibleSquaringPauser; pausers[1] = incredibleSquaringCommunityMultisig; - incredibleSquaringPauserReg = new PauserRegistry( - pausers, - incredibleSquaringCommunityMultisig - ); + incredibleSquaringPauserReg = new PauserRegistry(pausers, incredibleSquaringCommunityMultisig); } EmptyContract emptyContract = new EmptyContract(); @@ -190,90 +162,44 @@ contract IncredibleSquaringDeployer is Script, Utils { * not yet deployed, we give these proxies an empty contract as the initial implementation, to act as if they have no code. */ incredibleSquaringServiceManager = IncredibleSquaringServiceManager( - address( - new TransparentUpgradeableProxy( - address(emptyContract), - address(incredibleSquaringProxyAdmin), - "" - ) - ) + address(new TransparentUpgradeableProxy(address(emptyContract), address(incredibleSquaringProxyAdmin), "")) ); incredibleSquaringTaskManager = IncredibleSquaringTaskManager( - address( - new TransparentUpgradeableProxy( - address(emptyContract), - address(incredibleSquaringProxyAdmin), - "" - ) - ) + address(new TransparentUpgradeableProxy(address(emptyContract), address(incredibleSquaringProxyAdmin), "")) ); registryCoordinator = regcoord.RegistryCoordinator( - address( - new TransparentUpgradeableProxy( - address(emptyContract), - address(incredibleSquaringProxyAdmin), - "" - ) - ) + address(new TransparentUpgradeableProxy(address(emptyContract), address(incredibleSquaringProxyAdmin), "")) ); blsApkRegistry = IBLSApkRegistry( - address( - new TransparentUpgradeableProxy( - address(emptyContract), - address(incredibleSquaringProxyAdmin), - "" - ) - ) + address(new TransparentUpgradeableProxy(address(emptyContract), address(incredibleSquaringProxyAdmin), "")) ); indexRegistry = IIndexRegistry( - address( - new TransparentUpgradeableProxy( - address(emptyContract), - address(incredibleSquaringProxyAdmin), - "" - ) - ) + address(new TransparentUpgradeableProxy(address(emptyContract), address(incredibleSquaringProxyAdmin), "")) ); stakeRegistry = IStakeRegistry( - address( - new TransparentUpgradeableProxy( - address(emptyContract), - address(incredibleSquaringProxyAdmin), - "" - ) - ) + address(new TransparentUpgradeableProxy(address(emptyContract), address(incredibleSquaringProxyAdmin), "")) ); operatorStateRetriever = new OperatorStateRetriever(); // Second, deploy the *implementation* contracts, using the *proxy contracts* as inputs { - stakeRegistryImplementation = new StakeRegistry( - registryCoordinator, - delegationManager - ); + stakeRegistryImplementation = new StakeRegistry(registryCoordinator, delegationManager); incredibleSquaringProxyAdmin.upgrade( - TransparentUpgradeableProxy(payable(address(stakeRegistry))), - address(stakeRegistryImplementation) + TransparentUpgradeableProxy(payable(address(stakeRegistry))), address(stakeRegistryImplementation) ); - blsApkRegistryImplementation = new BLSApkRegistry( - registryCoordinator - ); + blsApkRegistryImplementation = new BLSApkRegistry(registryCoordinator); incredibleSquaringProxyAdmin.upgrade( - TransparentUpgradeableProxy(payable(address(blsApkRegistry))), - address(blsApkRegistryImplementation) + TransparentUpgradeableProxy(payable(address(blsApkRegistry))), address(blsApkRegistryImplementation) ); - indexRegistryImplementation = new IndexRegistry( - registryCoordinator - ); + indexRegistryImplementation = new IndexRegistry(registryCoordinator); incredibleSquaringProxyAdmin.upgrade( - TransparentUpgradeableProxy(payable(address(indexRegistry))), - address(indexRegistryImplementation) + TransparentUpgradeableProxy(payable(address(indexRegistry))), address(indexRegistryImplementation) ); } @@ -285,49 +211,38 @@ contract IncredibleSquaringDeployer is Script, Utils { ); { - uint numQuorums = 1; + uint256 numQuorums = 1; // for each quorum to setup, we need to define // QuorumOperatorSetParam, minimumStakeForQuorum, and strategyParams - regcoord.IRegistryCoordinator.OperatorSetParam[] - memory quorumsOperatorSetParams = new regcoord.IRegistryCoordinator.OperatorSetParam[]( - numQuorums - ); - for (uint i = 0; i < numQuorums; i++) { + regcoord.IRegistryCoordinator.OperatorSetParam[] memory quorumsOperatorSetParams = + new regcoord.IRegistryCoordinator.OperatorSetParam[](numQuorums); + for (uint256 i = 0; i < numQuorums; i++) { // hard code these for now - quorumsOperatorSetParams[i] = regcoord - .IRegistryCoordinator - .OperatorSetParam({ - maxOperatorCount: 10000, - kickBIPsOfOperatorStake: 15000, - kickBIPsOfTotalStake: 100 - }); + quorumsOperatorSetParams[i] = regcoord.IRegistryCoordinator.OperatorSetParam({ + maxOperatorCount: 10000, + kickBIPsOfOperatorStake: 15000, + kickBIPsOfTotalStake: 100 + }); } // set to 0 for every quorum uint96[] memory quorumsMinimumStake = new uint96[](numQuorums); - IStakeRegistry.StrategyParams[][] - memory quorumsStrategyParams = new IStakeRegistry.StrategyParams[][]( - numQuorums - ); - for (uint i = 0; i < numQuorums; i++) { - quorumsStrategyParams[i] = new IStakeRegistry.StrategyParams[]( - numStrategies - ); - for (uint j = 0; j < numStrategies; j++) { - quorumsStrategyParams[i][j] = IStakeRegistry - .StrategyParams({ - strategy: deployedStrategyArray[j], - // setting this to 1 ether since the divisor is also 1 ether - // therefore this allows an operator to register with even just 1 token - // see https://github.com/Layr-Labs/eigenlayer-middleware/blob/m2-mainnet/src/StakeRegistry.sol#L484 - // weight += uint96(sharesAmount * strategyAndMultiplier.multiplier / WEIGHTING_DIVISOR); - multiplier: 1 ether - }); + IStakeRegistry.StrategyParams[][] memory quorumsStrategyParams = + new IStakeRegistry.StrategyParams[][](numQuorums); + for (uint256 i = 0; i < numQuorums; i++) { + quorumsStrategyParams[i] = new IStakeRegistry.StrategyParams[](numStrategies); + for (uint256 j = 0; j < numStrategies; j++) { + quorumsStrategyParams[i][j] = IStakeRegistry.StrategyParams({ + strategy: deployedStrategyArray[j], + // setting this to 1 ether since the divisor is also 1 ether + // therefore this allows an operator to register with even just 1 token + // see https://github.com/Layr-Labs/eigenlayer-middleware/blob/m2-mainnet/src/StakeRegistry.sol#L484 + // weight += uint96(sharesAmount * strategyAndMultiplier.multiplier / WEIGHTING_DIVISOR); + multiplier: 1 ether + }); } } incredibleSquaringProxyAdmin.upgradeAndCall( - TransparentUpgradeableProxy( - payable(address(registryCoordinator)) - ), + TransparentUpgradeableProxy(payable(address(registryCoordinator))), address(registryCoordinatorImplementation), abi.encodeWithSelector( regcoord.RegistryCoordinator.initialize.selector, @@ -345,33 +260,23 @@ contract IncredibleSquaringDeployer is Script, Utils { } incredibleSquaringServiceManagerImplementation = new IncredibleSquaringServiceManager( - delegationManager, - registryCoordinator, - stakeRegistry, - incredibleSquaringTaskManager + delegationManager, registryCoordinator, stakeRegistry, incredibleSquaringTaskManager ); // Third, upgrade the proxy contracts to use the correct implementation contracts and initialize them. incredibleSquaringProxyAdmin.upgradeAndCall( - TransparentUpgradeableProxy( - payable(address(incredibleSquaringServiceManager)) - ), + TransparentUpgradeableProxy(payable(address(incredibleSquaringServiceManager))), address(incredibleSquaringServiceManagerImplementation), abi.encodeWithSelector( - incredibleSquaringServiceManager.initialize.selector, - incredibleSquaringCommunityMultisig + incredibleSquaringServiceManager.initialize.selector, incredibleSquaringCommunityMultisig ) ); - incredibleSquaringTaskManagerImplementation = new IncredibleSquaringTaskManager( - registryCoordinator, - TASK_RESPONSE_WINDOW_BLOCK - ); + incredibleSquaringTaskManagerImplementation = + new IncredibleSquaringTaskManager(registryCoordinator, TASK_RESPONSE_WINDOW_BLOCK); // Third, upgrade the proxy contracts to use the correct implementation contracts and initialize them. incredibleSquaringProxyAdmin.upgradeAndCall( - TransparentUpgradeableProxy( - payable(address(incredibleSquaringTaskManager)) - ), + TransparentUpgradeableProxy(payable(address(incredibleSquaringTaskManager))), address(incredibleSquaringTaskManagerImplementation), abi.encodeWithSelector( incredibleSquaringTaskManager.initialize.selector, @@ -386,58 +291,31 @@ contract IncredibleSquaringDeployer is Script, Utils { string memory parent_object = "parent object"; string memory deployed_addresses = "addresses"; + vm.serializeAddress(deployed_addresses, "erc20Mock", address(erc20Mock)); + vm.serializeAddress(deployed_addresses, "erc20MockStrategy", address(erc20MockStrategy)); vm.serializeAddress( - deployed_addresses, - "erc20Mock", - address(erc20Mock) - ); - vm.serializeAddress( - deployed_addresses, - "erc20MockStrategy", - address(erc20MockStrategy) - ); - vm.serializeAddress( - deployed_addresses, - "credibleSquaringServiceManager", - address(incredibleSquaringServiceManager) + deployed_addresses, "credibleSquaringServiceManager", address(incredibleSquaringServiceManager) ); vm.serializeAddress( deployed_addresses, "credibleSquaringServiceManagerImplementation", address(incredibleSquaringServiceManagerImplementation) ); - vm.serializeAddress( - deployed_addresses, - "credibleSquaringTaskManager", - address(incredibleSquaringTaskManager) - ); + vm.serializeAddress(deployed_addresses, "credibleSquaringTaskManager", address(incredibleSquaringTaskManager)); vm.serializeAddress( deployed_addresses, "credibleSquaringTaskManagerImplementation", address(incredibleSquaringTaskManagerImplementation) ); + vm.serializeAddress(deployed_addresses, "registryCoordinator", address(registryCoordinator)); vm.serializeAddress( - deployed_addresses, - "registryCoordinator", - address(registryCoordinator) - ); - vm.serializeAddress( - deployed_addresses, - "registryCoordinatorImplementation", - address(registryCoordinatorImplementation) - ); - string memory deployed_addresses_output = vm.serializeAddress( - deployed_addresses, - "operatorStateRetriever", - address(operatorStateRetriever) + deployed_addresses, "registryCoordinatorImplementation", address(registryCoordinatorImplementation) ); + string memory deployed_addresses_output = + vm.serializeAddress(deployed_addresses, "operatorStateRetriever", address(operatorStateRetriever)); // serialize all the data - string memory finalJson = vm.serializeString( - parent_object, - deployed_addresses, - deployed_addresses_output - ); + string memory finalJson = vm.serializeString(parent_object, deployed_addresses, deployed_addresses_output); writeOutput(finalJson, "credible_squaring_avs_deployment_output"); } diff --git a/contracts/script/utils/Utils.sol b/contracts/script/utils/Utils.sol index 19320d9..40cc6e3 100644 --- a/contracts/script/utils/Utils.sol +++ b/contracts/script/utils/Utils.sol @@ -10,15 +10,9 @@ import "forge-std/StdJson.sol"; contract Utils is Script { // Note that this fct will only work for the ERC20Mock that has a public mint function - function _mintTokens( - address strategyAddress, - address[] memory tos, - uint256[] memory amounts - ) internal { + function _mintTokens(address strategyAddress, address[] memory tos, uint256[] memory amounts) internal { for (uint256 i = 0; i < tos.length; i++) { - ERC20Mock underlyingToken = ERC20Mock( - address(StrategyBase(strategyAddress).underlyingToken()) - ); + ERC20Mock underlyingToken = ERC20Mock(address(StrategyBase(strategyAddress).underlyingToken())); underlyingToken.mint(tos[i], amounts[i]); } } @@ -32,9 +26,7 @@ contract Utils is Script { } } - function convertBoolToString( - bool input - ) public pure returns (string memory) { + function convertBoolToString(bool input) public pure returns (string memory) { if (input) { return "true"; } else { @@ -42,21 +34,16 @@ contract Utils is Script { } } - function convertOperatorStatusToString( - IRegistryCoordinator.OperatorStatus operatorStatus - ) public pure returns (string memory) { - if ( - operatorStatus == - IRegistryCoordinator.OperatorStatus.NEVER_REGISTERED - ) { + function convertOperatorStatusToString(IRegistryCoordinator.OperatorStatus operatorStatus) + public + pure + returns (string memory) + { + if (operatorStatus == IRegistryCoordinator.OperatorStatus.NEVER_REGISTERED) { return "NEVER_REGISTERED"; - } else if ( - operatorStatus == IRegistryCoordinator.OperatorStatus.REGISTERED - ) { + } else if (operatorStatus == IRegistryCoordinator.OperatorStatus.REGISTERED) { return "REGISTERED"; - } else if ( - operatorStatus == IRegistryCoordinator.OperatorStatus.DEREGISTERED - ) { + } else if (operatorStatus == IRegistryCoordinator.OperatorStatus.DEREGISTERED) { return "DEREGISTERED"; } else { return "UNKNOWN"; @@ -64,45 +51,24 @@ contract Utils is Script { } // Forge scripts best practice: https://book.getfoundry.sh/tutorials/best-practices#scripts - function readInput( - string memory inputFileName - ) internal view returns (string memory) { - string memory inputDir = string.concat( - vm.projectRoot(), - "/script/input/" - ); + function readInput(string memory inputFileName) internal view returns (string memory) { + string memory inputDir = string.concat(vm.projectRoot(), "/script/input/"); string memory chainDir = string.concat(vm.toString(block.chainid), "/"); string memory file = string.concat(inputFileName, ".json"); return vm.readFile(string.concat(inputDir, chainDir, file)); } - function readOutput( - string memory outputFileName - ) internal view returns (string memory) { - string memory inputDir = string.concat( - vm.projectRoot(), - "/script/output/" - ); + function readOutput(string memory outputFileName) internal view returns (string memory) { + string memory inputDir = string.concat(vm.projectRoot(), "/script/output/"); string memory chainDir = string.concat(vm.toString(block.chainid), "/"); string memory file = string.concat(outputFileName, ".json"); return vm.readFile(string.concat(inputDir, chainDir, file)); } - function writeOutput( - string memory outputJson, - string memory outputFileName - ) internal { - string memory outputDir = string.concat( - vm.projectRoot(), - "/script/output/" - ); + function writeOutput(string memory outputJson, string memory outputFileName) internal { + string memory outputDir = string.concat(vm.projectRoot(), "/script/output/"); string memory chainDir = string.concat(vm.toString(block.chainid), "/"); - string memory outputFilePath = string.concat( - outputDir, - chainDir, - outputFileName, - ".json" - ); + string memory outputFilePath = string.concat(outputDir, chainDir, outputFileName, ".json"); vm.writeJson(outputJson, outputFilePath); } } diff --git a/contracts/src/ERC20Mock.sol b/contracts/src/ERC20Mock.sol index de379fc..b1b3535 100644 --- a/contracts/src/ERC20Mock.sol +++ b/contracts/src/ERC20Mock.sol @@ -3,306 +3,16 @@ pragma solidity =0.8.12; -import "@openzeppelin/contracts/interfaces/IERC20.sol"; -import "@openzeppelin/contracts/utils/Context.sol"; - -/** - * @dev Implementation of the {IERC20} interface. - * - * This implementation is agnostic to the way tokens are created. This means - * that a supply mechanism has to be added in a derived contract using {_mint}. - * For a generic mechanism see {ERC20PresetMinterPauser}. - * - * TIP: For a detailed writeup see our guide - * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How - * to implement supply mechanisms]. - * - * The default value of {decimals} is 18. To change this, you should override - * this function so it returns a different value. - * - * We have followed general OpenZeppelin Contracts guidelines: functions revert - * instead returning `false` on failure. This behavior is nonetheless - * conventional and does not conflict with the expectations of ERC20 - * applications. - * - * Additionally, an {Approval} event is emitted on calls to {transferFrom}. - * This allows applications to reconstruct the allowance for all accounts just - * by listening to said events. Other implementations of the EIP may not emit - * these events, as it isn't required by the specification. - * - * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} - * functions have been added to mitigate the well-known issues around setting - * allowances. See {IERC20-approve}. - */ -contract ERC20Mock is Context, IERC20 { - mapping(address => uint256) private _balances; - - mapping(address => mapping(address => uint256)) private _allowances; - - uint256 private _totalSupply; - - /** - * @dev See {IERC20-totalSupply}. - */ - function totalSupply() public view virtual override returns (uint256) { - return _totalSupply; - } - - /** - * @dev See {IERC20-balanceOf}. - */ - function balanceOf( - address account - ) public view virtual override returns (uint256) { - return _balances[account]; - } +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +contract ERC20Mock is ERC20("Mock Token", "MCK") { function mint(address account, uint256 amount) public { _mint(account, amount); } - /** - * @dev See {IERC20-transfer}. - * - * Requirements: - * - * - `to` cannot be the zero address. - * - the caller must have a balance of at least `amount`. - */ - function transfer( - address to, - uint256 amount - ) public virtual override returns (bool) { - address owner = _msgSender(); - _transfer(owner, to, amount); + /// WARNING: Vulnerable, bypasses allowance check. Do not use in production! + function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { + super._transfer(from, to, amount); return true; } - - /** - * @dev See {IERC20-allowance}. - */ - function allowance( - address owner, - address spender - ) public view virtual override returns (uint256) { - return _allowances[owner][spender]; - } - - /** - * @dev See {IERC20-approve}. - * - * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on - * `transferFrom`. This is semantically equivalent to an infinite approval. - * - * Requirements: - * - * - `spender` cannot be the zero address. - */ - function approve( - address /*spender*/, - uint256 /*amount*/ - ) public virtual override returns (bool) { - return true; - } - - /** - * @dev See {IERC20-transferFrom}. - * - * Emits an {Approval} event indicating the updated allowance. This is not - * required by the EIP. See the note at the beginning of {ERC20}. - * - * NOTE: Does not update the allowance if the current allowance - * is the maximum `uint256`. - * - * Requirements: - * - * - `from` and `to` cannot be the zero address. - * - `from` must have a balance of at least `amount`. - * - the caller must have allowance for ``from``'s tokens of at least - * `amount`. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) public virtual override returns (bool) { - _transfer(from, to, amount); - return true; - } - - /** - * @dev Moves `amount` of tokens from `from` to `to`. - * - * This internal function is equivalent to {transfer}, and can be used to - * e.g. implement automatic token fees, slashing mechanisms, etc. - * - * Emits a {Transfer} event. - * - * Requirements: - * - * - `from` cannot be the zero address. - * - `to` cannot be the zero address. - * - `from` must have a balance of at least `amount`. - */ - function _transfer( - address from, - address to, - uint256 amount - ) internal virtual { - require(from != address(0), "ERC20: transfer from the zero address"); - require(to != address(0), "ERC20: transfer to the zero address"); - - _beforeTokenTransfer(from, to, amount); - - require( - _balances[from] >= amount, - "ERC20: transfer amount exceeds balance" - ); - unchecked { - _balances[from] = _balances[from] - amount; - // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by - // decrementing then incrementing. - _balances[to] += amount; - } - - emit Transfer(from, to, amount); - - _afterTokenTransfer(from, to, amount); - } - - /** @dev Creates `amount` tokens and assigns them to `account`, increasing - * the total supply. - * - * Emits a {Transfer} event with `from` set to the zero address. - * - * Requirements: - * - * - `account` cannot be the zero address. - */ - function _mint(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: mint to the zero address"); - - _totalSupply += amount; - unchecked { - // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. - _balances[account] += amount; - } - emit Transfer(address(0), account, amount); - } - - /** - * @dev Destroys `amount` tokens from `account`, reducing the - * total supply. - * - * Emits a {Transfer} event with `to` set to the zero address. - * - * Requirements: - * - * - `account` cannot be the zero address. - * - `account` must have at least `amount` tokens. - */ - function _burn(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: burn from the zero address"); - - _beforeTokenTransfer(account, address(0), amount); - - uint256 accountBalance = _balances[account]; - require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); - unchecked { - _balances[account] = accountBalance - amount; - // Overflow not possible: amount <= accountBalance <= totalSupply. - _totalSupply -= amount; - } - - emit Transfer(account, address(0), amount); - - _afterTokenTransfer(account, address(0), amount); - } - - /** - * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. - * - * This internal function is equivalent to `approve`, and can be used to - * e.g. set automatic allowances for certain subsystems, etc. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `owner` cannot be the zero address. - * - `spender` cannot be the zero address. - */ - function _approve( - address owner, - address spender, - uint256 amount - ) internal virtual { - require(owner != address(0), "ERC20: approve from the zero address"); - require(spender != address(0), "ERC20: approve to the zero address"); - - _allowances[owner][spender] = amount; - emit Approval(owner, spender, amount); - } - - /** - * @dev Updates `owner` s allowance for `spender` based on spent `amount`. - * - * Does not update the allowance amount in case of infinite allowance. - * Revert if not enough allowance is available. - * - * Might emit an {Approval} event. - */ - function _spendAllowance( - address owner, - address spender, - uint256 amount - ) internal virtual { - uint256 currentAllowance = allowance(owner, spender); - if (currentAllowance != type(uint256).max) { - require( - currentAllowance >= amount, - "ERC20: insufficient allowance" - ); - } - } - - /** - * @dev Hook that is called before any transfer of tokens. This includes - * minting and burning. - * - * Calling conditions: - * - * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens - * will be transferred to `to`. - * - when `from` is zero, `amount` tokens will be minted for `to`. - * - when `to` is zero, `amount` of ``from``'s tokens will be burned. - * - `from` and `to` are never both zero. - * - * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. - */ - function _beforeTokenTransfer( - address from, - address to, - uint256 amount - ) internal virtual {} - - /** - * @dev Hook that is called after any transfer of tokens. This includes - * minting and burning. - * - * Calling conditions: - * - * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens - * has been transferred to `to`. - * - when `from` is zero, `amount` tokens have been minted for `to`. - * - when `to` is zero, `amount` of ``from``'s tokens have been burned. - * - `from` and `to` are never both zero. - * - * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. - */ - function _afterTokenTransfer( - address from, - address to, - uint256 amount - ) internal virtual {} } diff --git a/contracts/src/IIncredibleSquaringTaskManager.sol b/contracts/src/IIncredibleSquaringTaskManager.sol index 6e6fcfc..8201b89 100644 --- a/contracts/src/IIncredibleSquaringTaskManager.sol +++ b/contracts/src/IIncredibleSquaringTaskManager.sol @@ -1,28 +1,19 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.9; -import "@eigenlayer-middleware/src/libraries/BN254.sol"; +import {BN254} from "@eigenlayer-middleware/src/libraries/BN254.sol"; interface IIncredibleSquaringTaskManager { // EVENTS event NewTaskCreated(uint32 indexed taskIndex, Task task); - event TaskResponded( - TaskResponse taskResponse, - TaskResponseMetadata taskResponseMetadata - ); + event TaskResponded(TaskResponse taskResponse, TaskResponseMetadata taskResponseMetadata); event TaskCompleted(uint32 indexed taskIndex); - event TaskChallengedSuccessfully( - uint32 indexed taskIndex, - address indexed challenger - ); + event TaskChallengedSuccessfully(uint32 indexed taskIndex, address indexed challenger); - event TaskChallengedUnsuccessfully( - uint32 indexed taskIndex, - address indexed challenger - ); + event TaskChallengedUnsuccessfully(uint32 indexed taskIndex, address indexed challenger); // STRUCTS struct Task { @@ -57,11 +48,8 @@ interface IIncredibleSquaringTaskManager { // FUNCTIONS // NOTE: this function creates new task. - function createNewTask( - uint256 numberToBeSquared, - uint32 quorumThresholdPercentage, - bytes calldata quorumNumbers - ) external; + function createNewTask(uint256 numberToBeSquared, uint32 quorumThresholdPercentage, bytes calldata quorumNumbers) + external; /// @notice Returns the current 'taskNumber' for the middleware function taskNumber() external view returns (uint32); diff --git a/contracts/src/IncredibleSquaringServiceManager.sol b/contracts/src/IncredibleSquaringServiceManager.sol index 26d5675..bd9fa78 100644 --- a/contracts/src/IncredibleSquaringServiceManager.sol +++ b/contracts/src/IncredibleSquaringServiceManager.sol @@ -1,9 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.9; -import "@eigenlayer/contracts/libraries/BytesLib.sol"; -import "./IIncredibleSquaringTaskManager.sol"; -import "@eigenlayer-middleware/src/ServiceManagerBase.sol"; +import {BytesLib} from "@eigenlayer/contracts/libraries/BytesLib.sol"; +import {IIncredibleSquaringTaskManager} from "./IIncredibleSquaringTaskManager.sol"; +import { + ServiceManagerBase, + IDelegationManager, + IRegistryCoordinator, + IStakeRegistry +} from "@eigenlayer-middleware/src/ServiceManagerBase.sol"; /** * @title Primary entrypoint for procuring services from IncredibleSquaring. @@ -12,8 +17,7 @@ import "@eigenlayer-middleware/src/ServiceManagerBase.sol"; contract IncredibleSquaringServiceManager is ServiceManagerBase { using BytesLib for bytes; - IIncredibleSquaringTaskManager - public immutable incredibleSquaringTaskManager; + IIncredibleSquaringTaskManager public immutable incredibleSquaringTaskManager; /// @notice when applied to a function, ensures that the function is only callable by the `registryCoordinator`. modifier onlyIncredibleSquaringTaskManager() { @@ -29,22 +33,14 @@ contract IncredibleSquaringServiceManager is ServiceManagerBase { IRegistryCoordinator _registryCoordinator, IStakeRegistry _stakeRegistry, IIncredibleSquaringTaskManager _incredibleSquaringTaskManager - ) - ServiceManagerBase( - _delegationManager, - _registryCoordinator, - _stakeRegistry - ) - { + ) ServiceManagerBase(_delegationManager, _registryCoordinator, _stakeRegistry) { incredibleSquaringTaskManager = _incredibleSquaringTaskManager; } /// @notice Called in the event of challenge resolution, in order to forward a call to the Slasher, which 'freezes' the `operator`. /// @dev The Slasher contract is under active development and its interface expected to change. /// We recommend writing slashing logic without integrating with the Slasher at this point in time. - function freezeOperator( - address operatorAddr - ) external onlyIncredibleSquaringTaskManager { + function freezeOperator(address operatorAddr) external onlyIncredibleSquaringTaskManager { // slasher.freezeOperator(operatorAddr); } } diff --git a/contracts/src/IncredibleSquaringTaskManager.sol b/contracts/src/IncredibleSquaringTaskManager.sol index d1762cf..e3e1ca8 100644 --- a/contracts/src/IncredibleSquaringTaskManager.sol +++ b/contracts/src/IncredibleSquaringTaskManager.sol @@ -59,19 +59,16 @@ contract IncredibleSquaringTaskManager is _; } - constructor( - IRegistryCoordinator _registryCoordinator, - uint32 _taskResponseWindowBlock - ) BLSSignatureChecker(_registryCoordinator) { + constructor(IRegistryCoordinator _registryCoordinator, uint32 _taskResponseWindowBlock) + BLSSignatureChecker(_registryCoordinator) + { TASK_RESPONSE_WINDOW_BLOCK = _taskResponseWindowBlock; } - function initialize( - IPauserRegistry _pauserRegistry, - address initialOwner, - address _aggregator, - address _generator - ) public initializer { + function initialize(IPauserRegistry _pauserRegistry, address initialOwner, address _aggregator, address _generator) + public + initializer + { _initializePauser(_pauserRegistry, UNPAUSE_ALL); _transferOwnership(initialOwner); aggregator = _aggregator; @@ -80,11 +77,10 @@ contract IncredibleSquaringTaskManager is /* FUNCTIONS */ // NOTE: this function creates new task, assigns it a taskId - function createNewTask( - uint256 numberToBeSquared, - uint32 quorumThresholdPercentage, - bytes calldata quorumNumbers - ) external onlyTaskGenerator { + function createNewTask(uint256 numberToBeSquared, uint32 quorumThresholdPercentage, bytes calldata quorumNumbers) + external + onlyTaskGenerator + { // create a new task struct Task memory newTask; newTask.numberToBeSquared = numberToBeSquared; @@ -110,8 +106,7 @@ contract IncredibleSquaringTaskManager is // check that the task is valid, hasn't been responsed yet, and is being responsed in time require( - keccak256(abi.encode(task)) == - allTaskHashes[taskResponse.referenceTaskIndex], + keccak256(abi.encode(task)) == allTaskHashes[taskResponse.referenceTaskIndex], "supplied task does not match the one recorded in the contract" ); // some logical checks @@ -120,8 +115,7 @@ contract IncredibleSquaringTaskManager is "Aggregator has already responded to the task" ); require( - uint32(block.number) <= - taskCreatedBlock + TASK_RESPONSE_WINDOW_BLOCK, + uint32(block.number) <= taskCreatedBlock + TASK_RESPONSE_WINDOW_BLOCK, "Aggregator has responded to the task too late" ); @@ -130,37 +124,23 @@ contract IncredibleSquaringTaskManager is bytes32 message = keccak256(abi.encode(taskResponse)); // check the BLS signature - ( - QuorumStakeTotals memory quorumStakeTotals, - bytes32 hashOfNonSigners - ) = checkSignatures( - message, - quorumNumbers, - taskCreatedBlock, - nonSignerStakesAndSignature - ); + (QuorumStakeTotals memory quorumStakeTotals, bytes32 hashOfNonSigners) = + checkSignatures(message, quorumNumbers, taskCreatedBlock, nonSignerStakesAndSignature); // check that signatories own at least a threshold percentage of each quourm - for (uint i = 0; i < quorumNumbers.length; i++) { + for (uint256 i = 0; i < quorumNumbers.length; i++) { // we don't check that the quorumThresholdPercentages are not >100 because a greater value would trivially fail the check, implying // signed stake > total stake require( - quorumStakeTotals.signedStakeForQuorum[i] * - _THRESHOLD_DENOMINATOR >= - quorumStakeTotals.totalStakeForQuorum[i] * - uint8(quorumThresholdPercentage), + quorumStakeTotals.signedStakeForQuorum[i] * _THRESHOLD_DENOMINATOR + >= quorumStakeTotals.totalStakeForQuorum[i] * uint8(quorumThresholdPercentage), "Signatories do not own at least threshold percentage of a quorum" ); } - TaskResponseMetadata memory taskResponseMetadata = TaskResponseMetadata( - uint32(block.number), - hashOfNonSigners - ); + TaskResponseMetadata memory taskResponseMetadata = TaskResponseMetadata(uint32(block.number), hashOfNonSigners); // updating the storage with task responsea - allTaskResponses[taskResponse.referenceTaskIndex] = keccak256( - abi.encode(taskResponse, taskResponseMetadata) - ); + allTaskResponses[taskResponse.referenceTaskIndex] = keccak256(abi.encode(taskResponse, taskResponseMetadata)); // emitting event emit TaskResponded(taskResponse, taskResponseMetadata); @@ -182,13 +162,9 @@ contract IncredibleSquaringTaskManager is uint32 referenceTaskIndex = taskResponse.referenceTaskIndex; uint256 numberToBeSquared = task.numberToBeSquared; // some logical checks + require(allTaskResponses[referenceTaskIndex] != bytes32(0), "Task hasn't been responded to yet"); require( - allTaskResponses[referenceTaskIndex] != bytes32(0), - "Task hasn't been responded to yet" - ); - require( - allTaskResponses[referenceTaskIndex] == - keccak256(abi.encode(taskResponse, taskResponseMetadata)), + allTaskResponses[referenceTaskIndex] == keccak256(abi.encode(taskResponse, taskResponseMetadata)), "Task response does not match the one recorded in the contract" ); require( @@ -197,16 +173,13 @@ contract IncredibleSquaringTaskManager is ); require( - uint32(block.number) <= - taskResponseMetadata.taskResponsedBlock + - TASK_CHALLENGE_WINDOW_BLOCK, + uint32(block.number) <= taskResponseMetadata.taskResponsedBlock + TASK_CHALLENGE_WINDOW_BLOCK, "The challenge period for this task has already expired." ); // logic for checking whether challenge is valid or not uint256 actualSquaredOutput = numberToBeSquared * numberToBeSquared; - bool isResponseCorrect = (actualSquaredOutput == - taskResponse.numberSquared); + bool isResponseCorrect = (actualSquaredOutput == taskResponse.numberSquared); // if response was correct, no slashing happens so we return if (isResponseCorrect == true) { @@ -215,13 +188,9 @@ contract IncredibleSquaringTaskManager is } // get the list of hash of pubkeys of operators who weren't part of the task response submitted by the aggregator - bytes32[] memory hashesOfPubkeysOfNonSigningOperators = new bytes32[]( - pubkeysOfNonSigningOperators.length - ); - for (uint i = 0; i < pubkeysOfNonSigningOperators.length; i++) { - hashesOfPubkeysOfNonSigningOperators[ - i - ] = pubkeysOfNonSigningOperators[i].hashG1Point(); + bytes32[] memory hashesOfPubkeysOfNonSigningOperators = new bytes32[](pubkeysOfNonSigningOperators.length); + for (uint256 i = 0; i < pubkeysOfNonSigningOperators.length; i++) { + hashesOfPubkeysOfNonSigningOperators[i] = pubkeysOfNonSigningOperators[i].hashG1Point(); } // verify whether the pubkeys of "claimed" non-signers supplied by challenger are actually non-signers as recorded before @@ -229,25 +198,18 @@ contract IncredibleSquaringTaskManager is // currently inlined, as the MiddlewareUtils.computeSignatoryRecordHash function was removed from BLSSignatureChecker // in this PR: https://github.com/Layr-Labs/eigenlayer-contracts/commit/c836178bf57adaedff37262dff1def18310f3dce#diff-8ab29af002b60fc80e3d6564e37419017c804ae4e788f4c5ff468ce2249b4386L155-L158 // TODO(samlaf): contracts team will add this function back in the BLSSignatureChecker, which we should use to prevent potential bugs from code duplication - bytes32 signatoryRecordHash = keccak256( - abi.encodePacked( - task.taskCreatedBlock, - hashesOfPubkeysOfNonSigningOperators - ) - ); + bytes32 signatoryRecordHash = + keccak256(abi.encodePacked(task.taskCreatedBlock, hashesOfPubkeysOfNonSigningOperators)); require( signatoryRecordHash == taskResponseMetadata.hashOfNonSigners, "The pubkeys of non-signing operators supplied by the challenger are not correct." ); // get the address of operators who didn't sign - address[] memory addresssOfNonSigningOperators = new address[]( - pubkeysOfNonSigningOperators.length - ); - for (uint i = 0; i < pubkeysOfNonSigningOperators.length; i++) { - addresssOfNonSigningOperators[i] = BLSApkRegistry( - address(blsApkRegistry) - ).pubkeyHashToOperator(hashesOfPubkeysOfNonSigningOperators[i]); + address[] memory addresssOfNonSigningOperators = new address[](pubkeysOfNonSigningOperators.length); + for (uint256 i = 0; i < pubkeysOfNonSigningOperators.length; i++) { + addresssOfNonSigningOperators[i] = + BLSApkRegistry(address(blsApkRegistry)).pubkeyHashToOperator(hashesOfPubkeysOfNonSigningOperators[i]); } // @dev the below code is commented out for the upcoming M2 release diff --git a/contracts/test/CredibleSquaringTaskManager.t.sol b/contracts/test/CredibleSquaringTaskManager.t.sol index 2022adf..1c7be0e 100644 --- a/contracts/test/CredibleSquaringTaskManager.t.sol +++ b/contracts/test/CredibleSquaringTaskManager.t.sol @@ -13,17 +13,14 @@ contract IncredibleSquaringTaskManagerTest is BLSMockAVSDeployer { IncredibleSquaringTaskManager tmImplementation; uint32 public constant TASK_RESPONSE_WINDOW_BLOCK = 30; - address aggregator = - address(uint160(uint256(keccak256(abi.encodePacked("aggregator"))))); - address generator = - address(uint160(uint256(keccak256(abi.encodePacked("generator"))))); + address aggregator = address(uint160(uint256(keccak256(abi.encodePacked("aggregator"))))); + address generator = address(uint160(uint256(keccak256(abi.encodePacked("generator"))))); function setUp() public { _setUpBLSMockAVSDeployer(); tmImplementation = new IncredibleSquaringTaskManager( - incsqsm.IRegistryCoordinator(address(registryCoordinator)), - TASK_RESPONSE_WINDOW_BLOCK + incsqsm.IRegistryCoordinator(address(registryCoordinator)), TASK_RESPONSE_WINDOW_BLOCK ); // Third, upgrade the proxy contracts to use the correct implementation contracts and initialize them. @@ -33,11 +30,7 @@ contract IncredibleSquaringTaskManagerTest is BLSMockAVSDeployer { address(tmImplementation), address(proxyAdmin), abi.encodeWithSelector( - tm.initialize.selector, - pauserRegistry, - registryCoordinatorOwner, - aggregator, - generator + tm.initialize.selector, pauserRegistry, registryCoordinatorOwner, aggregator, generator ) ) )