diff --git a/contracts/RealityModule.sol b/contracts/RealityModule.sol index 4c13bc9..2f81cc7 100644 --- a/contracts/RealityModule.sol +++ b/contracts/RealityModule.sol @@ -24,13 +24,20 @@ abstract contract RealityModule is Module { bytes32 indexed questionId, string indexed proposalId ); - + event ProposalExecuted(string proposalId, bytes32 txHash, uint256 txIndex); event RealityModuleSetup( address indexed initiator, address indexed owner, address indexed avatar, address target ); + event OracleSet(RealitioV3 oracle); + event SetQuestionTimeout(uint32 questionTimeout); + event SetQuestionCooldown(uint32 questionCooldown); + event SetAnswerExpiration(uint32 answerExpiration); + event SetArbitrator(address indexed questionArbitrator); + event SetMinimumBond(uint256 minimumBond); + event SetTemplate(uint256 templateId); RealitioV3 public oracle; uint256 public template; @@ -114,35 +121,43 @@ abstract contract RealityModule is Module { __Ownable_init(); require(_avatar != address(0), "Avatar can not be zero address"); require(_target != address(0), "Target can not be zero address"); - require(timeout > 0, "Timeout has to be greater 0"); - require( - expiration == 0 || expiration - cooldown >= 60, - "There need to be at least 60s between end of cooldown and expiration" - ); - avatar = _avatar; - target = _target; - oracle = _oracle; - answerExpiration = expiration; - questionTimeout = timeout; - questionCooldown = cooldown; - questionArbitrator = arbitrator; - minimumBond = bond; - template = templateId; + setAvatar(_avatar); + setTarget(_target); + setOracle(_oracle); + setAnswerExpiration(expiration); + setQuestionTimeout(timeout); + setQuestionCooldown(cooldown); + setArbitrator(arbitrator); + setMinimumBond(bond); + setTemplate(templateId); transferOwnership(_owner); emit RealityModuleSetup(msg.sender, _owner, avatar, target); } - /// @notice This can only be called by the owner + /// @dev Sets the `oracle` address + /// @param _oracle Address to be used as the oracle for this module + /// @notice This can only be called by the `owner` + function setOracle(RealitioV3 _oracle) public onlyOwner { + oracle = _oracle; + emit OracleSet(_oracle); + } + + /// @dev Sets the question timeout + /// @param timeout Timeout, in seconds, between when an answer is set and when it is final + /// @notice This can only be called by the `owner` + /// @notice Timeout must be greater than `0` function setQuestionTimeout(uint32 timeout) public onlyOwner { require(timeout > 0, "Timeout has to be greater 0"); + require(timeout < 365 days, "timeout must be less than 365 days"); questionTimeout = timeout; + emit SetQuestionTimeout(timeout); } - /// @dev Sets the cooldown before an answer is usable. - /// @param cooldown Cooldown in seconds that should be required after a oracle provided answer - /// @notice This can only be called by the owner + /// @dev Sets the cooldown before an answer is usable + /// @param cooldown Cooldown, in seconds, that should be required after a oracle provided answer + /// @notice This can only be called by the `owner` /// @notice There need to be at least 60 seconds between end of cooldown and expiration function setQuestionCooldown(uint32 cooldown) public onlyOwner { uint32 expiration = answerExpiration; @@ -151,47 +166,52 @@ abstract contract RealityModule is Module { "There need to be at least 60s between end of cooldown and expiration" ); questionCooldown = cooldown; + emit SetQuestionCooldown(cooldown); } - /// @dev Sets the duration for which a positive answer is valid. - /// @param expiration Duration that a positive answer of the oracle is valid in seconds (or 0 if valid forever) + /// @dev Sets the duration for which a positive answer is valid + /// @param expiration Duration that a positive answer of the oracle is valid, in seconds (or 0 if valid forever) /// @notice A proposal with an expired answer is the same as a proposal that has been marked invalid /// @notice There need to be at least 60 seconds between end of cooldown and expiration - /// @notice This can only be called by the owner + /// @notice This can only be called by the `owner` function setAnswerExpiration(uint32 expiration) public onlyOwner { require( expiration == 0 || expiration - questionCooldown >= 60, "There need to be at least 60s between end of cooldown and expiration" ); answerExpiration = expiration; + emit SetAnswerExpiration(expiration); } - /// @dev Sets the question arbitrator that will be used for future questions. + /// @dev Sets the question arbitrator that will be used for future questions /// @param arbitrator Address of the arbitrator - /// @notice This can only be called by the owner + /// @notice This can only be called by the `owner` function setArbitrator(address arbitrator) public onlyOwner { questionArbitrator = arbitrator; + emit SetArbitrator(arbitrator); } - /// @dev Sets the minimum bond that is required for an answer to be accepted. + /// @dev Sets the minimum bond that is required for an answer to be accepted /// @param bond Minimum bond that is required for an answer to be accepted - /// @notice This can only be called by the owner + /// @notice This can only be called by the `owner` function setMinimumBond(uint256 bond) public onlyOwner { minimumBond = bond; + emit SetMinimumBond(bond); } - /// @dev Sets the template that should be used for future questions. + /// @dev Sets the template that should be used for future questions /// @param templateId ID of the template that should be used for proposal questions /// @notice Check https://github.com/realitio/realitio-dapp#structuring-and-fetching-information for more information - /// @notice This can only be called by the owner + /// @notice This can only be called by the `owner` function setTemplate(uint256 templateId) public onlyOwner { template = templateId; + emit SetTemplate(templateId); } /// @dev Function to add a proposal that should be considered for execution /// @param proposalId Id that should identify the proposal uniquely /// @param txHashes EIP-712 hashes of the transactions that should be executed - /// @notice The nonce used for the question by this function is always 0 + /// @notice The nonce used for the question by this function is always `0` function addProposal(string memory proposalId, bytes32[] memory txHashes) public { @@ -296,7 +316,7 @@ abstract contract RealityModule is Module { /// @param value Wei value of the transaction that should be executed /// @param data Data of the transaction that should be executed /// @param operation Operation (Call or Delegatecall) of the transaction that should be executed - /// @notice The txIndex used by this function is always 0 + /// @notice The txIndex used by this function is always `0` function executeProposal( string memory proposalId, bytes32[] memory txHashes, @@ -394,6 +414,7 @@ abstract contract RealityModule is Module { executedProposalTransactions[questionHash][txHash] = true; // Execute the transaction via the target. require(exec(to, value, data, operation), "Module transaction failed"); + emit ProposalExecuted(proposalId, txHash, txIndex); } /// @dev Build the question by combining the proposalId and the hex string of the hash of the txHashes diff --git a/hardhat.config.ts b/hardhat.config.ts index 462af9e..7ce3e3f 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -6,6 +6,7 @@ import dotenv from "dotenv"; import type { HttpNetworkUserConfig } from "hardhat/types"; import yargs from "yargs"; import "./src/tasks/deployDeterministicDeploymentHelper"; +import "hardhat-contract-sizer"; const argv = yargs .option("network", { @@ -17,7 +18,8 @@ const argv = yargs // Load environment variables. dotenv.config(); -const { INFURA_KEY, MNEMONIC, ETHERSCAN_API_KEY, PK } = process.env; +const { INFURA_KEY, MNEMONIC, ETHERSCAN_API_KEY, PK, ALCHEMY_KEY } = + process.env; import "./src/tasks/setup"; import "./src/tasks/proposals"; @@ -59,13 +61,17 @@ export default { ...sharedNetworkConfig, url: `https://goerli.infura.io/v3/${INFURA_KEY}`, }, + arbitrum: { + ...sharedNetworkConfig, + url: `https://arb-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`, + }, xdai: { ...sharedNetworkConfig, url: "https://xdai.poanetwork.dev", }, matic: { ...sharedNetworkConfig, - url: "https://rpc-mainnet.maticvigil.com", + url: "https://polygon-rpc.com", }, bsc: { ...sharedNetworkConfig, diff --git a/package.json b/package.json index c6646b3..dc5b86a 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "lint:ts": "eslint --max-warnings 0 .", "fmt:sol": "prettier 'contracts/**/*.sol' -w", "prepack": "yarn build", - "prepare": "husky install" + "prepare": "husky install", + "size": "hardhat size-contracts" }, "repository": { "type": "git" @@ -58,6 +59,7 @@ "argv": "^0.0.2", "dotenv": "^8.0.0", "ethers": "^5.0.19", + "hardhat-contract-sizer": "^2.6.1", "solc": "0.8.1", "yargs": "^16.1.1" }, diff --git a/yarn.lock b/yarn.lock index a5bac78..69866a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30,6 +30,11 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@ensdomains/ens@^0.4.4": version "0.4.5" resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" @@ -2552,6 +2557,15 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-table3@^0.6.0: + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + cli-width@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" @@ -4822,6 +4836,14 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" +hardhat-contract-sizer@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/hardhat-contract-sizer/-/hardhat-contract-sizer-2.6.1.tgz#2b0046a55fa1ec96f19fdab7fde372377401c874" + integrity sha512-b8wS7DBvyo22kmVwpzstAQTdDCThpl/ySBqZh5ga9Yxjf61/uTL12TEg5nl7lDeWy73ntEUzxMwY6XxbQEc2wA== + dependencies: + chalk "^4.0.0" + cli-table3 "^0.6.0" + hardhat-deploy@^0.7.0-beta.38: version "0.7.11" resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.7.11.tgz#93f79dfbb529eeda24ac963e23a19064d536be2f"