diff --git a/scripts/ethcommands.ts b/scripts/ethcommands.ts index 9f3a8858..a7a0720d 100644 --- a/scripts/ethcommands.ts +++ b/scripts/ethcommands.ts @@ -140,6 +140,41 @@ async function deployERC20Contract(deployerWallet: Wallet, decimals: number): Pr return token.address; } +async function deployFeeTokenPricerContract(deployerWallet: Wallet, exchangeRate: BigNumber): Promise { + //// Bytecode below is generated from this simple FeeTokenPricer contract + + // pragma solidity ^0.8.16; + + // interface IFeeTokenPricer { + // /** + // * @notice Get the number of child chain's fee tokens per 1 parent chain's native token. Exchange rate must be + // * denominated in 18 decimals. + // * @dev For example, parent chain's native token is ETH, fee token is DAI. If price of 1ETH = 2000DAI, then function should return 2000*1e18. + // * If fee token is USDC instead and price of 1ETH = 2000USDC, function should still return 2000*1e18, no matter that USDC uses 6 decimals. + // */ + // function getExchangeRate() external returns (uint256); + // } + + // contract ConstantFeeTokenPricer is IFeeTokenPricer { + // uint256 immutable public constExchangeRate; + // constructor(uint256 _constExchangeRate) { + // constExchangeRate = _constExchangeRate; + // } + + // function getExchangeRate() external view returns (uint256) { + // return constExchangeRate; + // } + // } + + const feeTokenPricerBytecode = "0x60a0604052348015600e575f80fd5b506040516101c63803806101c68339818101604052810190602e9190606d565b8060808181525050506093565b5f80fd5b5f819050919050565b604f81603f565b81146058575f80fd5b50565b5f815190506067816048565b92915050565b5f60208284031215607f57607e603b565b5b5f608a84828501605b565b91505092915050565b6080516101166100b05f395f8181606a0152608f01526101165ff3fe6080604052348015600e575f80fd5b50600436106030575f3560e01c8063b8910a29146034578063e6aa216c14604e575b5f80fd5b603a6068565b6040516045919060c9565b60405180910390f35b6054608c565b604051605f919060c9565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b5f819050919050565b60c38160b3565b82525050565b5f60208201905060da5f83018460bc565b9291505056fea2646970667358221220ee17f22614d853ccf8b3f854137f68f06ff92f9f71ba8b811d78b1313eead0c564736f6c634300081a0033"; + const abi = ["constructor(uint256 exchangeRate)"]; + const feeTokenPricerFactory = new ContractFactory(abi, feeTokenPricerBytecode, deployerWallet); + const feeTokenPricer = await feeTokenPricerFactory.deploy(exchangeRate); + await feeTokenPricer.deployTransaction.wait(); + + return feeTokenPricer.address; +} + async function deployWETHContract(deployerWallet: Wallet): Promise { const wethFactory = new ContractFactory(TestWETH9.abi, TestWETH9.bytecode, deployerWallet); const weth = await wethFactory.deploy("Wrapped Ether", "WETH"); @@ -382,6 +417,29 @@ export const createERC20Command = { }, }; +export const createFeeTokenPricerCommand = { + command: "create-fee-token-pricer", + describe: "creates Constant Fee Token Pricer on L2", + builder: { + deployer: { + string: true, + describe: "account (see general help)" + }, + }, + handler: async (argv: any) => { + console.log("create-fee-token-pricer"); + + argv.provider = new ethers.providers.WebSocketProvider(argv.l2url); + const deployerWallet = new Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes(argv.deployer)), + argv.provider + ); + const feeTokenPricerAddress = await deployFeeTokenPricerContract(deployerWallet, BigNumber.from("15000000000000000000")); + console.log("Contract deployed at address:", feeTokenPricerAddress); + + argv.provider.destroy(); + }, +}; // Will revert if the keyset is already valid. async function setValidKeyset(argv: any, upgradeExecutorAddr: string, sequencerInboxAddr: string, keyset: string){ const innerIface = new ethers.utils.Interface(["function setValidKeyset(bytes)"]) diff --git a/scripts/index.ts b/scripts/index.ts index a95c16fb..80253b59 100644 --- a/scripts/index.ts +++ b/scripts/index.ts @@ -23,6 +23,7 @@ import { setValidKeysetCommand, waitForSyncCommand, transferL3ChainOwnershipCommand, + createFeeTokenPricerCommand, } from "./ethcommands"; async function main() { @@ -41,6 +42,7 @@ async function main() { .command(bridgeToL3Command) .command(bridgeNativeTokenToL3Command) .command(createERC20Command) + .command(createFeeTokenPricerCommand) .command(createWETHCommand) .command(transferERC20Command) .command(sendL1Command) diff --git a/test-node.bash b/test-node.bash index 788acc68..643a82fe 100755 --- a/test-node.bash +++ b/test-node.bash @@ -52,6 +52,7 @@ consensusclient=false boldupgrade=false redundantsequencers=0 l3_custom_fee_token=false +l3_custom_fee_token_pricer=false l3_token_bridge=false l3_custom_fee_token_decimals=18 batchposters=1 @@ -226,6 +227,14 @@ while [[ $# -gt 0 ]]; do l3_custom_fee_token=true shift ;; + --l3-fee-token-pricer) + if ! $l3_custom_fee_token; then + echo "Error: --l3-fee-token-pricer requires --l3-fee-token to be provided." + exit 1 + fi + l3_custom_fee_token_pricer=true + shift + ;; --l3-fee-token-decimals) if ! $l3_custom_fee_token; then echo "Error: --l3-fee-token-decimals requires --l3-fee-token to be provided." @@ -583,6 +592,11 @@ if $force_init; then docker compose run scripts transfer-erc20 --token $nativeTokenAddress --amount 10000 --from user_fee_token_deployer --to l3owner docker compose run scripts transfer-erc20 --token $nativeTokenAddress --amount 10000 --from user_fee_token_deployer --to user_token_bridge_deployer EXTRA_L3_DEPLOY_FLAG="-e FEE_TOKEN_ADDRESS=$nativeTokenAddress" + if $l3_custom_fee_token_pricer; then + echo == Deploying custom fee token pricer + feeTokenPricerAddress=`docker compose run scripts create-fee-token-pricer --deployer user_fee_token_deployer | tail -n 1 | awk '{ print $NF }'` + EXTRA_L3_DEPLOY_FLAG="$EXTRA_L3_DEPLOY_FLAG -e FEE_TOKEN_PRICER_ADDRESS=$feeTokenPricerAddress" + fi fi echo == Deploying L3