diff --git a/.changeset/seven-carpets-tell.md b/.changeset/seven-carpets-tell.md new file mode 100644 index 000000000000..9be51c0a6974 --- /dev/null +++ b/.changeset/seven-carpets-tell.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/contracts': patch +--- + +Introduces the congestion price oracle contract diff --git a/packages/contracts/contracts/optimistic-ethereum/OVM/predeploys/OVM_GasPriceOracle.sol b/packages/contracts/contracts/optimistic-ethereum/OVM/predeploys/OVM_GasPriceOracle.sol new file mode 100644 index 000000000000..03cc96a860b0 --- /dev/null +++ b/packages/contracts/contracts/optimistic-ethereum/OVM/predeploys/OVM_GasPriceOracle.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity >0.5.0 <0.8.0; + +/* External Imports */ +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; + +/** + * @title OVM_GasPriceOracle + * @dev This contract exposes the current l2 gas price, a measure of how congested the network + * currently is. This measure is used by the Sequencer to determine what fee to charge for + * transactions. When the system is more congested, the l2 gas price will increase and fees + * will also increase as a result. + * + * Compiler used: optimistic-solc + * Runtime target: OVM + */ +contract OVM_GasPriceOracle is Ownable { + + /************* + * Variables * + *************/ + + // Current l2 gas price + uint256 public gasPrice; + + /*************** + * Constructor * + ***************/ + + /** + * @param _owner Address that will initially own this contract. + */ + constructor( + address _owner, + uint256 _initialGasPrice + ) + Ownable() + { + setGasPrice(_initialGasPrice); + transferOwnership(_owner); + } + + + /******************** + * Public Functions * + ********************/ + + /** + * Allows the owner to modify the l2 gas price. + * @param _gasPrice New l2 gas price. + */ + function setGasPrice( + uint256 _gasPrice + ) + public + onlyOwner + { + gasPrice = _gasPrice; + } +} diff --git a/packages/contracts/deploy-l2/000-OVM_GasPriceOracle.deploy.ts b/packages/contracts/deploy-l2/000-OVM_GasPriceOracle.deploy.ts new file mode 100644 index 000000000000..96eb8fd1b175 --- /dev/null +++ b/packages/contracts/deploy-l2/000-OVM_GasPriceOracle.deploy.ts @@ -0,0 +1,31 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { getContractDefinition } from '../src' + +const deployFn: DeployFunction = async (hre: any) => { + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + + const gasPriceOracle = getContractDefinition('OVM_GasPriceOracle', true) + + const gasOracleOwner = (hre as any).deployConfig.ovmSequencerAddress + const initialGasPrice = (hre as any).deployConfig.initialGasPriceOracleGasPrice + + if (!gasOracleOwner || !initialGasPrice) { + throw new Error('initialGasPrice & ovmSequencerAddress required to deploy gas price oracle') + } + + await deploy('OVM_GasPriceOracle', { + contract: gasPriceOracle, + from: deployer, + args: [gasOracleOwner, initialGasPrice], + log: true, + }); +} + +deployFn.tags = ['OVM_GasPriceOracle'] + +export default deployFn diff --git a/packages/contracts/deployments/README.md b/packages/contracts/deployments/README.md index 133f6ba27b34..a6d5b7156e9b 100644 --- a/packages/contracts/deployments/README.md +++ b/packages/contracts/deployments/README.md @@ -1,6 +1,15 @@ # Optimism Regenesis Deployments ## LAYER 2 +## OPTIMISTIC-KOVAN + +Network : __optimistic-kovan (chain id: 69)__ + +|Contract|Address| +|--|--| +|OVM_GasPriceOracle|[0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76](https://kovan-optimistic.etherscan.io/address/0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76)| +--- + ### Chain IDs: - Mainnet: 10 - Kovan: 69 diff --git a/packages/contracts/deployments/optimistic-kovan/.chainId b/packages/contracts/deployments/optimistic-kovan/.chainId new file mode 100644 index 000000000000..8c0474e3239f --- /dev/null +++ b/packages/contracts/deployments/optimistic-kovan/.chainId @@ -0,0 +1 @@ +69 \ No newline at end of file diff --git a/packages/contracts/deployments/optimistic-kovan/OVM_GasPriceOracle.json b/packages/contracts/deployments/optimistic-kovan/OVM_GasPriceOracle.json new file mode 100644 index 000000000000..3ad5351c0abc --- /dev/null +++ b/packages/contracts/deployments/optimistic-kovan/OVM_GasPriceOracle.json @@ -0,0 +1,164 @@ +{ + "address": "0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_initialGasPrice", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "gasPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_gasPrice", + "type": "uint256" + } + ], + "name": "setGasPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xed5fd0757566bc0bc1f3f7d701e31199835d6fe7b1e74353ad502983f2f5e744", + "receipt": { + "to": null, + "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", + "contractAddress": "0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76", + "transactionIndex": 0, + "gasUsed": "1732518", + "logsBloom": "0x00000000000000000000000000000000000000000000000000840000000000000000000000000000000000100000000000000000000000140000000000000000000000000100000000000008000000000001000010000000000000000000000400000000020000000000000000008800000000000000000000400010000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000010000000000000000000000000000000000000000000000008002000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x310208064b53df696581d48cee7439d3e94acac8c31a519e5d07e7cc542c920c", + "transactionHash": "0xed5fd0757566bc0bc1f3f7d701e31199835d6fe7b1e74353ad502983f2f5e744", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 336546, + "transactionHash": "0xed5fd0757566bc0bc1f3f7d701e31199835d6fe7b1e74353ad502983f2f5e744", + "address": "0x4200000000000000000000000000000000000006", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x00000000000000000000000018394b52d3cb931dfa76f63251919d051953413d", + "0x0000000000000000000000004200000000000000000000000000000000000005" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": 0, + "blockHash": "0x310208064b53df696581d48cee7439d3e94acac8c31a519e5d07e7cc542c920c" + }, + { + "transactionIndex": 0, + "blockNumber": 336546, + "transactionHash": "0xed5fd0757566bc0bc1f3f7d701e31199835d6fe7b1e74353ad502983f2f5e744", + "address": "0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000018394b52d3cb931dfa76f63251919d051953413d" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x310208064b53df696581d48cee7439d3e94acac8c31a519e5d07e7cc542c920c" + }, + { + "transactionIndex": 0, + "blockNumber": 336546, + "transactionHash": "0xed5fd0757566bc0bc1f3f7d701e31199835d6fe7b1e74353ad502983f2f5e744", + "address": "0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x00000000000000000000000018394b52d3cb931dfa76f63251919d051953413d", + "0x00000000000000000000000018394b52d3cb931dfa76f63251919d051953413d" + ], + "data": "0x", + "logIndex": 2, + "blockHash": "0x310208064b53df696581d48cee7439d3e94acac8c31a519e5d07e7cc542c920c" + } + ], + "blockNumber": 336546, + "cumulativeGasUsed": "1732518", + "status": 1, + "byzantium": true + }, + "args": [ + "0x18394B52d3Cb931dfA76F63251919D051953413d", + 1000000 + ], + "bytecode": "0x60806040523480156200001c5760008062000019620002ea565b50505b5060405162000a7338038062000a73833981810160405260408110156200004d576000806200004a620002ea565b50505b81019080805192919060200180519250600091506200006d9050620000ec565b90508060006001816200007f62000357565b816001600160a01b0302191690836001600160a01b0316021790620000a3620003b9565b5050506001600160a01b038116600060008051602062000a5383398151915260405160405180910390a350620000d981620000fe565b620000e48262000184565b50506200044f565b60005a620000f962000408565b905090565b62000108620000ec565b6001600160a01b03166200011b620002c7565b6001600160a01b031614620001705760405162461bcd60e51b8152602060048201819052602482015260008051602062000a338339815191526044820152606401604051809103906200016d620002ea565b50505b808060016200017e620003b9565b50505050565b6200018e620000ec565b6001600160a01b0316620001a1620002c7565b6001600160a01b031614620001f65760405162461bcd60e51b8152602060048201819052602482015260008051602062000a33833981519152604482015260640160405180910390620001f3620002ea565b50505b6001600160a01b038116620002485760405162461bcd60e51b815260040180806020018281038252602681526020018062000a0d602691396040019150506040518091039062000245620002ea565b50505b806001600160a01b03166000806200025f62000357565b906101000a90046001600160a01b03166001600160a01b031660008051602062000a5383398151915260405160405180910390a3806000600181620002a362000357565b816001600160a01b0302191690836001600160a01b03160217906200017e620003b9565b60008080620002d562000357565b906101000a90046001600160a01b0316905090565b632a2a7adb598160e01b8152600481016020815285602082015260005b868110156200032457808601518282016040015260200162000307565b506020828760640184336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b505050565b6303daa959598160e01b8152836004820152602081602483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051935060005b6040811015620003b4576000828201526020016200039b565b505050565b6322bd64c0598160e01b8152836004820152846024820152600081604483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b6000815260206200039b565b6373509064598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b805160008252935060206200039b565b6105ae806200045f6000396000f3fe60806040523480156100195760008061001661042d565b50505b50600436106100605760003560e01c8063715018a61461006e5780638da5cb5b14610078578063bf1fe4201461009c578063f2fde38b146100c2578063fe173b97146100f1575b60008061006b61042d565b50505b61007661010b565b005b61008061020d565b6040516001600160a01b03909116815260200160405180910390f35b610076600480360360208110156100bb576000806100b861042d565b50505b503561022e565b610076600480360360208110156100e1576000806100de61042d565b50505b50356001600160a01b03166102bc565b6100f9610410565b60405190815260200160405180910390f35b61011361041d565b6001600160a01b031661012461020d565b6001600160a01b0316146101875760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016040518091039061018461042d565b50505b60008080610193610498565b906101000a90046001600160a01b03166001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000806001816101e6610498565b816001600160a01b0302191690836001600160a01b03160217906102086104f3565b505050565b60008080610219610498565b906101000a90046001600160a01b0316905090565b61023661041d565b6001600160a01b031661024761020d565b6001600160a01b0316146102aa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401604051809103906102a761042d565b50505b808060016102b66104f3565b50505050565b6102c461041d565b6001600160a01b03166102d561020d565b6001600160a01b0316146103385760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016040518091039061033561042d565b50505b6001600160a01b0381166103865760405162461bcd60e51b8152600401808060200182810382526026815260200180610588602691396040019150506040518091039061038361042d565b50505b806001600160a01b031660008061039b610498565b906101000a90046001600160a01b03166001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a38060006001816103ee610498565b816001600160a01b0302191690836001600160a01b03160217906102b66104f3565b600161041a610498565b81565b60005a610428610541565b905090565b632a2a7adb598160e01b8152600481016020815285602082015260005b8681101561046557808601518282016040015260200161044a565b506020828760640184336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b505050565b6303daa959598160e01b8152836004820152602081602483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051935060005b6040811015610208576000828201526020016104dc565b6322bd64c0598160e01b8152836004820152846024820152600081604483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b6000815260206104dc565b6373509064598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b805160008252935060206104dc56fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65728be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "deployedBytecode": "0x60806040523480156100195760008061001661042d565b50505b50600436106100605760003560e01c8063715018a61461006e5780638da5cb5b14610078578063bf1fe4201461009c578063f2fde38b146100c2578063fe173b97146100f1575b60008061006b61042d565b50505b61007661010b565b005b61008061020d565b6040516001600160a01b03909116815260200160405180910390f35b610076600480360360208110156100bb576000806100b861042d565b50505b503561022e565b610076600480360360208110156100e1576000806100de61042d565b50505b50356001600160a01b03166102bc565b6100f9610410565b60405190815260200160405180910390f35b61011361041d565b6001600160a01b031661012461020d565b6001600160a01b0316146101875760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016040518091039061018461042d565b50505b60008080610193610498565b906101000a90046001600160a01b03166001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000806001816101e6610498565b816001600160a01b0302191690836001600160a01b03160217906102086104f3565b505050565b60008080610219610498565b906101000a90046001600160a01b0316905090565b61023661041d565b6001600160a01b031661024761020d565b6001600160a01b0316146102aa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401604051809103906102a761042d565b50505b808060016102b66104f3565b50505050565b6102c461041d565b6001600160a01b03166102d561020d565b6001600160a01b0316146103385760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016040518091039061033561042d565b50505b6001600160a01b0381166103865760405162461bcd60e51b8152600401808060200182810382526026815260200180610588602691396040019150506040518091039061038361042d565b50505b806001600160a01b031660008061039b610498565b906101000a90046001600160a01b03166001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a38060006001816103ee610498565b816001600160a01b0302191690836001600160a01b03160217906102b66104f3565b600161041a610498565b81565b60005a610428610541565b905090565b632a2a7adb598160e01b8152600481016020815285602082015260005b8681101561046557808601518282016040015260200161044a565b506020828760640184336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b505050565b6303daa959598160e01b8152836004820152602081602483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051935060005b6040811015610208576000828201526020016104dc565b6322bd64c0598160e01b8152836004820152846024820152600081604483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b6000815260206104dc565b6373509064598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b805160008252935060206104dc56fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373" +} \ No newline at end of file diff --git a/packages/contracts/tasks/deploy.ts b/packages/contracts/tasks/deploy.ts index 35d2e041b692..8c3a793b062b 100644 --- a/packages/contracts/tasks/deploy.ts +++ b/packages/contracts/tasks/deploy.ts @@ -99,6 +99,12 @@ task('deploy') undefined, types.string ) + .addOptionalParam( + 'initialGasPriceOracleGasPrice', + 'The initial execution price for the gas price oracle.', + undefined, + types.int + ) .setAction(async (args, hre: any, runSuper) => { // Necessary because hardhat doesn't let us attach non-optional parameters to existing tasks. const validateAddressArg = (argName: string) => { diff --git a/packages/contracts/test/contracts/OVM/precompiles/OVM_GasPriceOracle.spec.ts b/packages/contracts/test/contracts/OVM/precompiles/OVM_GasPriceOracle.spec.ts new file mode 100644 index 000000000000..ead0baebf899 --- /dev/null +++ b/packages/contracts/test/contracts/OVM/precompiles/OVM_GasPriceOracle.spec.ts @@ -0,0 +1,80 @@ +import { expect } from '../../../setup' + +/* External Imports */ +import { ethers } from 'hardhat' +import { ContractFactory, Contract, Signer } from 'ethers' + +describe('OVM_GasPriceOracle', () => { + const initialGasPrice = 0 + let signer1: Signer + let signer2: Signer + before(async () => { + ;[signer1, signer2] = await ethers.getSigners() + }) + + let Factory__OVM_GasPriceOracle: ContractFactory + before(async () => { + Factory__OVM_GasPriceOracle = await ethers.getContractFactory( + 'OVM_GasPriceOracle' + ) + }) + + let OVM_GasPriceOracle: Contract + beforeEach(async () => { + OVM_GasPriceOracle = await Factory__OVM_GasPriceOracle.deploy( + await signer1.getAddress(), + initialGasPrice + ) + }) + + describe('owner', () => { + it('should have an owner', async () => { + expect(await OVM_GasPriceOracle.owner()).to.equal( + await signer1.getAddress() + ) + }) + }) + + describe('setGasPrice', () => { + it('should revert if called by someone other than the owner', async () => { + await expect(OVM_GasPriceOracle.connect(signer2).setGasPrice(1234)).to.be + .reverted + }) + + it('should succeed if called by the owner and is equal to `0`', async () => { + await expect(OVM_GasPriceOracle.connect(signer1).setGasPrice(0)).to.not.be + .reverted + }) + }) + + describe('get gasPrice', () => { + it('should return zero at first', async () => { + expect(await OVM_GasPriceOracle.gasPrice()).to.equal(initialGasPrice) + }) + + it('should change when setGasPrice is called', async () => { + const gasPrice = 1234 + + await OVM_GasPriceOracle.connect(signer1).setGasPrice(gasPrice) + + expect(await OVM_GasPriceOracle.gasPrice()).to.equal(gasPrice) + }) + + it('is the 1st storage slot', async () => { + const gasPrice = 1234 + const slot = 1 + + // set the price + await OVM_GasPriceOracle.connect(signer1).setGasPrice(gasPrice) + + // get the storage slot value + const priceAtSlot = await signer1.provider.getStorageAt( + OVM_GasPriceOracle.address, + slot + ) + expect(await OVM_GasPriceOracle.gasPrice()).to.equal( + ethers.BigNumber.from(priceAtSlot) + ) + }) + }) +})