From 39464542bfcd2c481f40d0ba90ed201797e95f3f Mon Sep 17 00:00:00 2001 From: DefiCake Date: Sat, 27 Apr 2024 23:47:10 +0200 Subject: [PATCH 01/28] feat: add testnet deploy scripts --- .../deploy/testnet/001.chain_state.ts | 39 +++++++++++++++ .../testnet/002.fuel_message_portal_v3.ts | 48 +++++++++++++++++++ .../deploy/testnet/003.erc20_gateway_v2.ts | 40 ++++++++++++++++ .../deploy/testnet/004.token.ts | 22 +++++++++ .../testnet/005.register_block_committer.ts | 28 +++++++++++ packages/solidity-contracts/hardhat.config.ts | 11 +++++ 6 files changed, 188 insertions(+) create mode 100644 packages/solidity-contracts/deploy/testnet/001.chain_state.ts create mode 100644 packages/solidity-contracts/deploy/testnet/002.fuel_message_portal_v3.ts create mode 100644 packages/solidity-contracts/deploy/testnet/003.erc20_gateway_v2.ts create mode 100644 packages/solidity-contracts/deploy/testnet/004.token.ts create mode 100644 packages/solidity-contracts/deploy/testnet/005.register_block_committer.ts diff --git a/packages/solidity-contracts/deploy/testnet/001.chain_state.ts b/packages/solidity-contracts/deploy/testnet/001.chain_state.ts new file mode 100644 index 00000000..65c1e9b7 --- /dev/null +++ b/packages/solidity-contracts/deploy/testnet/001.chain_state.ts @@ -0,0 +1,39 @@ +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; + +import { FuelChainState__factory as FuelChainState } from '../../typechain'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { + ethers, + upgrades: { deployProxy, erc1967 }, + deployments: { save, execute }, + } = hre; + const [deployer] = await ethers.getSigners(); + + const contract = await deployProxy(new FuelChainState(deployer), [], { + initializer: 'initialize', + }); + await contract.waitForDeployment(); + const address = await contract.getAddress(); + const implementation = await erc1967.getImplementationAddress(address); + + console.log('Deployed FuelChainState at', address); + await save('FuelChainState', { + address, + abi: [...FuelChainState.abi], + implementation, + }); + + await execute( + 'FuelChainState', + { log: true, from: deployer.address }, + 'pause' + ); + + return true; +}; + +func.tags = ['state', 'chain-state', 'chain_state', 'FuelChainState']; +func.id = 'chain_state'; +export default func; diff --git a/packages/solidity-contracts/deploy/testnet/002.fuel_message_portal_v3.ts b/packages/solidity-contracts/deploy/testnet/002.fuel_message_portal_v3.ts new file mode 100644 index 00000000..5ca0d404 --- /dev/null +++ b/packages/solidity-contracts/deploy/testnet/002.fuel_message_portal_v3.ts @@ -0,0 +1,48 @@ +import { MaxUint256 } from 'ethers'; +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; + +import { FuelMessagePortalV3__factory as FuelMessagePortal } from '../../typechain'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { + ethers, + upgrades: { deployProxy, erc1967 }, + deployments: { get, save, execute }, + } = hre; + const [deployer] = await ethers.getSigners(); + + const { address: fuelChainState } = await get('FuelChainState'); + + const contract = await deployProxy( + new FuelMessagePortal(deployer), + [fuelChainState], + { + initializer: 'initialize', + constructorArgs: [MaxUint256], + } + ); + await contract.waitForDeployment(); + + const address = await contract.getAddress(); + const implementation = await erc1967.getImplementationAddress(address); + + console.log('Deployed FuelMessagePortal at', address); + await save('FuelMessagePortal', { + address, + abi: [...FuelMessagePortal.abi], + implementation, + }); + + await execute( + 'FuelMessagePortal', + { log: true, from: deployer.address }, + 'pause' + ); + + return true; +}; + +func.tags = ['portal', 'message_portal', 'FuelMessagePortal']; +func.id = 'fuel_message_portal'; +export default func; diff --git a/packages/solidity-contracts/deploy/testnet/003.erc20_gateway_v2.ts b/packages/solidity-contracts/deploy/testnet/003.erc20_gateway_v2.ts new file mode 100644 index 00000000..c0307da2 --- /dev/null +++ b/packages/solidity-contracts/deploy/testnet/003.erc20_gateway_v2.ts @@ -0,0 +1,40 @@ +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; + +import { FuelERC20GatewayV2__factory as FuelERC20GatewayV2 } from '../../typechain'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { + ethers, + upgrades: { deployProxy, erc1967 }, + deployments: { get, save }, + } = hre; + const [deployer] = await ethers.getSigners(); + + const fuelMessagePortal = await get('FuelMessagePortal'); + + const contract = await deployProxy( + new FuelERC20GatewayV2(deployer), + [fuelMessagePortal.address], + { + initializer: 'initialize', + } + ); + await contract.waitForDeployment(); + + const address = await contract.getAddress(); + const implementation = await erc1967.getImplementationAddress(address); + + console.log('Deployed FuelERC20GatewayV2 at', address); + await save('FuelERC20GatewayV2', { + address, + abi: [], + implementation, + }); + + return true; +}; + +func.tags = ['erc20', 'erc20_gateway', 'FuelERC20GatewayV2']; +func.id = 'fuel_erc20_gateway_v2'; +export default func; diff --git a/packages/solidity-contracts/deploy/testnet/004.token.ts b/packages/solidity-contracts/deploy/testnet/004.token.ts new file mode 100644 index 00000000..2812266a --- /dev/null +++ b/packages/solidity-contracts/deploy/testnet/004.token.ts @@ -0,0 +1,22 @@ +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; + +/** + * @description Deployed for testing purposes + */ +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { + ethers, + deployments: { deploy }, + } = hre; + + const [deployer] = await ethers.getSigners(); + + await deploy('Token', { from: deployer.address, log: true }); + + return true; +}; + +func.tags = ['token']; +func.id = 'token'; +export default func; diff --git a/packages/solidity-contracts/deploy/testnet/005.register_block_committer.ts b/packages/solidity-contracts/deploy/testnet/005.register_block_committer.ts new file mode 100644 index 00000000..3f9dab71 --- /dev/null +++ b/packages/solidity-contracts/deploy/testnet/005.register_block_committer.ts @@ -0,0 +1,28 @@ +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; + +import { FuelChainState__factory } from '../../typechain'; + +const COMMITTER_ADDRESS = '0x6B956CcB32582E0e88136ff895BA77Dc52a68620'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { ethers, deployments } = hre; + const [deployer] = await ethers.getSigners(); + + const { address } = await deployments.get('FuelChainState'); + + const fuelChainState = FuelChainState__factory.connect(address, deployer); + const COMMITTER_ROLE = await fuelChainState.COMMITTER_ROLE(); + + await fuelChainState + .grantRole(COMMITTER_ROLE, COMMITTER_ADDRESS) + .then((tx) => tx.wait()); + + console.log('Granted role COMMITTER_ROLE to', COMMITTER_ADDRESS); + + return true; +}; + +func.tags = ['portal', 'message_portal', 'FuelMessagePortal']; +func.id = 'fuel_message_portal'; +export default func; diff --git a/packages/solidity-contracts/hardhat.config.ts b/packages/solidity-contracts/hardhat.config.ts index 9f18ace5..5889da36 100644 --- a/packages/solidity-contracts/hardhat.config.ts +++ b/packages/solidity-contracts/hardhat.config.ts @@ -84,6 +84,17 @@ const config: HardhatUserConfig = { deploy: ['deploy/devnet'], chainId: 11155111, }, + testnet: { + url: RPC_URL, + accounts: CONTRACTS_DEPLOYER_KEY + ? [CONTRACTS_DEPLOYER_KEY] + : { + mnemonic: + 'test test test test test test test test test test test junk', + }, + deploy: ['deploy/devnet'], + chainId: 11155111, + }, }, typechain: { outDir: 'typechain', From f9c839e34f47728c5595a1de72f258ddb29c6c0b Mon Sep 17 00:00:00 2001 From: DefiCake Date: Sun, 28 Apr 2024 00:05:49 +0200 Subject: [PATCH 02/28] feat: update testnet deploy scripts --- ...erc20_gateway_v2.ts => 003.erc20_gateway_v4.ts} | 14 +++++++------- .../deploy/testnet/005.register_block_committer.ts | 4 ++-- packages/solidity-contracts/hardhat.config.ts | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) rename packages/solidity-contracts/deploy/testnet/{003.erc20_gateway_v2.ts => 003.erc20_gateway_v4.ts} (69%) diff --git a/packages/solidity-contracts/deploy/testnet/003.erc20_gateway_v2.ts b/packages/solidity-contracts/deploy/testnet/003.erc20_gateway_v4.ts similarity index 69% rename from packages/solidity-contracts/deploy/testnet/003.erc20_gateway_v2.ts rename to packages/solidity-contracts/deploy/testnet/003.erc20_gateway_v4.ts index c0307da2..8c0097f7 100644 --- a/packages/solidity-contracts/deploy/testnet/003.erc20_gateway_v2.ts +++ b/packages/solidity-contracts/deploy/testnet/003.erc20_gateway_v4.ts @@ -1,7 +1,7 @@ import type { HardhatRuntimeEnvironment } from 'hardhat/types'; import type { DeployFunction } from 'hardhat-deploy/dist/types'; -import { FuelERC20GatewayV2__factory as FuelERC20GatewayV2 } from '../../typechain'; +import { FuelERC20GatewayV4__factory as FuelERC20Gateway } from '../../typechain'; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { @@ -14,7 +14,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const fuelMessagePortal = await get('FuelMessagePortal'); const contract = await deployProxy( - new FuelERC20GatewayV2(deployer), + new FuelERC20Gateway(deployer), [fuelMessagePortal.address], { initializer: 'initialize', @@ -25,16 +25,16 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const address = await contract.getAddress(); const implementation = await erc1967.getImplementationAddress(address); - console.log('Deployed FuelERC20GatewayV2 at', address); - await save('FuelERC20GatewayV2', { + console.log('Deployed FuelERC20GatewayV4 at', address); + await save('FuelERC20GatewayV4', { address, - abi: [], + abi: [...FuelERC20Gateway.abi], implementation, }); return true; }; -func.tags = ['erc20', 'erc20_gateway', 'FuelERC20GatewayV2']; -func.id = 'fuel_erc20_gateway_v2'; +func.tags = ['erc20', 'erc20_gateway', 'FuelERC20GatewayV4']; +func.id = 'fuel_erc20_gateway_v4'; export default func; diff --git a/packages/solidity-contracts/deploy/testnet/005.register_block_committer.ts b/packages/solidity-contracts/deploy/testnet/005.register_block_committer.ts index 3f9dab71..638727be 100644 --- a/packages/solidity-contracts/deploy/testnet/005.register_block_committer.ts +++ b/packages/solidity-contracts/deploy/testnet/005.register_block_committer.ts @@ -23,6 +23,6 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { return true; }; -func.tags = ['portal', 'message_portal', 'FuelMessagePortal']; -func.id = 'fuel_message_portal'; +func.tags = ['register_committer']; +func.id = 'register_committer'; export default func; diff --git a/packages/solidity-contracts/hardhat.config.ts b/packages/solidity-contracts/hardhat.config.ts index 5889da36..29d6e9f0 100644 --- a/packages/solidity-contracts/hardhat.config.ts +++ b/packages/solidity-contracts/hardhat.config.ts @@ -92,7 +92,7 @@ const config: HardhatUserConfig = { mnemonic: 'test test test test test test test test test test test junk', }, - deploy: ['deploy/devnet'], + deploy: ['deploy/testnet'], chainId: 11155111, }, }, From c265e6198499204fc0bdb53a0ff0f62a1770f8d3 Mon Sep 17 00:00:00 2001 From: DefiCake Date: Sun, 28 Apr 2024 00:12:00 +0200 Subject: [PATCH 03/28] chore: deploy testnet contracts --- .../.openzeppelin/sepolia.json | 694 +++++++++++++ packages/solidity-contracts/DEPLOYMENTS.MD | 12 + .../deployments/testnet/.chainId | 1 + .../deployments/testnet/.migrations.json | 7 + .../deployments/testnet/FuelChainState.json | 528 ++++++++++ .../testnet/FuelERC20GatewayV4.json | 715 ++++++++++++++ .../testnet/FuelMessagePortal.json | 926 ++++++++++++++++++ .../deployments/testnet/Token.json | 475 +++++++++ .../31fce82f72204deb1c3e677ecb77fe87.json | 257 +++++ 9 files changed, 3615 insertions(+) create mode 100644 packages/solidity-contracts/deployments/testnet/.chainId create mode 100644 packages/solidity-contracts/deployments/testnet/.migrations.json create mode 100644 packages/solidity-contracts/deployments/testnet/FuelChainState.json create mode 100644 packages/solidity-contracts/deployments/testnet/FuelERC20GatewayV4.json create mode 100644 packages/solidity-contracts/deployments/testnet/FuelMessagePortal.json create mode 100644 packages/solidity-contracts/deployments/testnet/Token.json create mode 100644 packages/solidity-contracts/deployments/testnet/solcInputs/31fce82f72204deb1c3e677ecb77fe87.json diff --git a/packages/solidity-contracts/.openzeppelin/sepolia.json b/packages/solidity-contracts/.openzeppelin/sepolia.json index ad57e324..0c67ff61 100644 --- a/packages/solidity-contracts/.openzeppelin/sepolia.json +++ b/packages/solidity-contracts/.openzeppelin/sepolia.json @@ -100,6 +100,21 @@ "address": "0x83114982BDe057a8907F8a081225C7d301898aDd", "txHash": "0x94d778dc8284824f38d3aacd8172ab9a1880d686365ae3e26e8425e16d858184", "kind": "uups" + }, + { + "address": "0x8097500F4168240f4334589170d99fE8797b6fF8", + "txHash": "0xdce60bb12134eb3e916258b01d225c7372eef36a8dc8d1f8a0964124c5c5d940", + "kind": "uups" + }, + { + "address": "0x768f9459E3339A1F7d59CcF24C80Eb4A711a01FB", + "txHash": "0x6b50229f9e4f2f4f19a16fba5bed9f832a3220c99fbd391b01809c9fae432cb3", + "kind": "uups" + }, + { + "address": "0xbdf7256C718FCede6f0af19e86D4aBDdc4DC2Ff2", + "txHash": "0x5e93f7942b84271090b9a8e44a95e2f3532d517fc73591e78711a01fccd2eea2", + "kind": "uups" } ], "impls": { @@ -2395,6 +2410,685 @@ }, "namespaces": {} } + }, + "b9dd224724fdadbc3e6f85275cf599f9a927d1c7796afe9b719fdd477d97c132": { + "address": "0xba98eDC9AC0B6191180562bF68CE001B1D71C11D", + "txHash": "0x12a9d396c2a057c03d859a04a2cc362d2c34e494c11537b6606e0f86ad57197e", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_paused", + "offset": 0, + "slot": "51", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_roles", + "offset": 0, + "slot": "151", + "type": "t_mapping(t_bytes32,t_struct(RoleData)2324_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:57" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:260" + }, + { + "label": "__gap", + "offset": 0, + "slot": "201", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "251", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "_commitSlots", + "offset": 0, + "slot": "301", + "type": "t_array(t_struct(Commit)5995_storage)240_storage", + "contract": "FuelChainState", + "src": "contracts/fuelchain/FuelChainState.sol:59" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Commit)5995_storage)240_storage": { + "label": "struct Commit[240]", + "numberOfBytes": "15360" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)2324_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_struct(Commit)5995_storage": { + "label": "struct Commit", + "members": [ + { + "label": "blockHash", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "timestamp", + "type": "t_uint32", + "offset": 0, + "slot": "1" + }, + { + "label": "reserved1", + "type": "t_address", + "offset": 4, + "slot": "1" + }, + { + "label": "reserved2", + "type": "t_uint16", + "offset": 24, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(RoleData)2324_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "9f7f29d876a56513bbcabdcf5a014a04b46d76b4623ba104065748cac07a981d": { + "address": "0xC9C453fA30cd0c6A2f09Af5e1C32F839Ff7a3DD0", + "txHash": "0xbfdf6b815be5966e0f6679044533d307278e66ff35444c333bef4690d9708b62", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_paused", + "offset": 0, + "slot": "51", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_roles", + "offset": 0, + "slot": "151", + "type": "t_mapping(t_bytes32,t_struct(RoleData)2324_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:57" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:260" + }, + { + "label": "_status", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:88" + }, + { + "label": "__gap", + "offset": 0, + "slot": "251", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "301", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "_incomingMessageSender", + "offset": 0, + "slot": "351", + "type": "t_bytes32", + "contract": "FuelMessagePortal", + "src": "contracts/fuelchain/FuelMessagePortal.sol:96" + }, + { + "label": "_fuelChainState", + "offset": 0, + "slot": "352", + "type": "t_contract(FuelChainState)6232", + "contract": "FuelMessagePortal", + "src": "contracts/fuelchain/FuelMessagePortal.sol:99" + }, + { + "label": "_outgoingMessageNonce", + "offset": 0, + "slot": "353", + "type": "t_uint256", + "contract": "FuelMessagePortal", + "src": "contracts/fuelchain/FuelMessagePortal.sol:102" + }, + { + "label": "_incomingMessageSuccessful", + "offset": 0, + "slot": "354", + "type": "t_mapping(t_bytes32,t_bool)", + "contract": "FuelMessagePortal", + "src": "contracts/fuelchain/FuelMessagePortal.sol:105" + }, + { + "label": "__gap", + "offset": 0, + "slot": "355", + "type": "t_array(t_uint256)49_storage", + "contract": "FuelMessagePortal", + "src": "contracts/fuelchain/FuelMessagePortal.sol:333" + }, + { + "label": "totalDeposited", + "offset": 0, + "slot": "404", + "type": "t_uint256", + "contract": "FuelMessagePortalV2", + "src": "contracts/fuelchain/FuelMessagePortal/v2/FuelMessagePortalV2.sol:14" + }, + { + "label": "__gap", + "offset": 0, + "slot": "405", + "type": "t_array(t_uint256)49_storage", + "contract": "FuelMessagePortalV2", + "src": "contracts/fuelchain/FuelMessagePortal/v2/FuelMessagePortalV2.sol:107" + }, + { + "label": "withdrawalsPaused", + "offset": 0, + "slot": "454", + "type": "t_bool", + "contract": "FuelMessagePortalV3", + "src": "contracts/fuelchain/FuelMessagePortal/v3/FuelMessagePortalV3.sol:14" + }, + { + "label": "messageIsBlacklisted", + "offset": 0, + "slot": "455", + "type": "t_mapping(t_bytes32,t_bool)", + "contract": "FuelMessagePortalV3", + "src": "contracts/fuelchain/FuelMessagePortal/v3/FuelMessagePortalV3.sol:15" + }, + { + "label": "__gap", + "offset": 0, + "slot": "456", + "type": "t_array(t_uint256)49_storage", + "contract": "FuelMessagePortalV3", + "src": "contracts/fuelchain/FuelMessagePortal/v3/FuelMessagePortalV3.sol:101" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(FuelChainState)6232": { + "label": "contract FuelChainState", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)2324_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_struct(RoleData)2324_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "15314565a307c1731d15b7db60595091a0bc5515c75cc16f8b05b732010db281": { + "address": "0xdF018d3163FA9FC70FD6eD79D3E0E3770A034756", + "txHash": "0xdc3594bd692d249aa419041e54908a16af1a240ea96752cebeb5681a547b9a55", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "_fuelMessagePortal", + "offset": 2, + "slot": "0", + "type": "t_contract(FuelMessagePortal)6853", + "contract": "FuelMessagesEnabled", + "src": "contracts/messaging/FuelMessagesEnabled.sol:21" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)49_storage", + "contract": "FuelMessagesEnabledUpgradeable", + "src": "contracts/messaging/FuelMessagesEnabledUpgradeable.sol:31" + }, + { + "label": "__gap", + "offset": 0, + "slot": "50", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_paused", + "offset": 0, + "slot": "100", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "__gap", + "offset": 0, + "slot": "150", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_roles", + "offset": 0, + "slot": "200", + "type": "t_mapping(t_bytes32,t_struct(RoleData)2324_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:57" + }, + { + "label": "__gap", + "offset": 0, + "slot": "201", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:260" + }, + { + "label": "__gap", + "offset": 0, + "slot": "250", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "300", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "whitelistRequired", + "offset": 0, + "slot": "350", + "type": "t_bool", + "contract": "FuelERC20GatewayV4", + "src": "contracts/messaging/gateway/FuelERC20Gateway/FuelERC20GatewayV4.sol:63" + }, + { + "label": "assetIssuerId", + "offset": 0, + "slot": "351", + "type": "t_bytes32", + "contract": "FuelERC20GatewayV4", + "src": "contracts/messaging/gateway/FuelERC20Gateway/FuelERC20GatewayV4.sol:64" + }, + { + "label": "_deposits", + "offset": 0, + "slot": "352", + "type": "t_mapping(t_address,t_uint256)", + "contract": "FuelERC20GatewayV4", + "src": "contracts/messaging/gateway/FuelERC20Gateway/FuelERC20GatewayV4.sol:66" + }, + { + "label": "_depositLimits", + "offset": 0, + "slot": "353", + "type": "t_mapping(t_address,t_uint256)", + "contract": "FuelERC20GatewayV4", + "src": "contracts/messaging/gateway/FuelERC20Gateway/FuelERC20GatewayV4.sol:67" + }, + { + "label": "_decimalsCache", + "offset": 0, + "slot": "354", + "type": "t_mapping(t_address,t_uint256)", + "contract": "FuelERC20GatewayV4", + "src": "contracts/messaging/gateway/FuelERC20Gateway/FuelERC20GatewayV4.sol:68" + }, + { + "label": "_isBridge", + "offset": 0, + "slot": "355", + "type": "t_mapping(t_bytes32,t_bool)", + "contract": "FuelERC20GatewayV4", + "src": "contracts/messaging/gateway/FuelERC20Gateway/FuelERC20GatewayV4.sol:69" + }, + { + "label": "__gap", + "offset": 0, + "slot": "356", + "type": "t_array(t_uint256)49_storage", + "contract": "FuelERC20GatewayV4", + "src": "contracts/messaging/gateway/FuelERC20Gateway/FuelERC20GatewayV4.sol:333" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(FuelMessagePortal)6853": { + "label": "contract FuelMessagePortal", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)2324_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_struct(RoleData)2324_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/solidity-contracts/DEPLOYMENTS.MD b/packages/solidity-contracts/DEPLOYMENTS.MD index 505dafd5..a2aac4f9 100644 --- a/packages/solidity-contracts/DEPLOYMENTS.MD +++ b/packages/solidity-contracts/DEPLOYMENTS.MD @@ -25,4 +25,16 @@ FuelERC721GatewayV2 at 0xc17a3694B01238308Fd1140E2F13928ff6564f84 FuelChainState at 0x0880932521f0E3a90d56bC96fD49c0c98CFCf4A7 FuelMessagePortal at 0x01eb5b6122E1f65eaF4566093C2431aa0c0eaCd5 FuelERC20GatewayV2 at 0x83114982BDe057a8907F8a081225C7d301898aDd +``` + +## Testnet + +``` +FuelChainState at 0x8097500F4168240f4334589170d99fE8797b6fF8 + +FuelMessagePortal at 0x768f9459E3339A1F7d59CcF24C80Eb4A711a01FB + +FuelERC20GatewayV4 at 0xbdf7256C718FCede6f0af19e86D4aBDdc4DC2Ff2 + +Token deployed at0x25E869bc5FC45e2786B4B1bEace61287e071C60e ``` \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/.chainId b/packages/solidity-contracts/deployments/testnet/.chainId new file mode 100644 index 00000000..bd8d1cd4 --- /dev/null +++ b/packages/solidity-contracts/deployments/testnet/.chainId @@ -0,0 +1 @@ +11155111 \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/.migrations.json b/packages/solidity-contracts/deployments/testnet/.migrations.json new file mode 100644 index 00000000..de166f4d --- /dev/null +++ b/packages/solidity-contracts/deployments/testnet/.migrations.json @@ -0,0 +1,7 @@ +{ + "chain_state": 1714255660, + "fuel_message_portal": 1714255695, + "fuel_erc20_gateway_v4": 1714255717, + "token": 1714255743, + "register_committer": 1714255753 +} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/FuelChainState.json b/packages/solidity-contracts/deployments/testnet/FuelChainState.json new file mode 100644 index 00000000..6bd96bcf --- /dev/null +++ b/packages/solidity-contracts/deployments/testnet/FuelChainState.json @@ -0,0 +1,528 @@ +{ + "address": "0x8097500F4168240f4334589170d99fE8797b6fF8", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "UnknownBlock", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "commitHeight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "name": "CommitSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKS_PER_COMMIT_INTERVAL", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COMMITTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NUM_COMMIT_SLOTS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAUSER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TIME_TO_FINALIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "commitHeight", + "type": "uint256" + } + ], + "name": "blockHashAtCommit", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "commitHeight", + "type": "uint256" + } + ], + "name": "commit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "blockHeight", + "type": "uint256" + } + ], + "name": "finalized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "numDeployments": 1, + "implementation": "0xba98eDC9AC0B6191180562bF68CE001B1D71C11D" +} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/FuelERC20GatewayV4.json b/packages/solidity-contracts/deployments/testnet/FuelERC20GatewayV4.json new file mode 100644 index 00000000..70503ce7 --- /dev/null +++ b/packages/solidity-contracts/deployments/testnet/FuelERC20GatewayV4.json @@ -0,0 +1,715 @@ +{ + "address": "0xbdf7256C718FCede6f0af19e86D4aBDdc4DC2Ff2", + "abi": [ + { + "inputs": [], + "name": "BridgeFull", + "type": "error" + }, + { + "inputs": [], + "name": "CallerIsNotPortal", + "type": "error" + }, + { + "inputs": [], + "name": "CannotDepositZero", + "type": "error" + }, + { + "inputs": [], + "name": "CannotWithdrawZero", + "type": "error" + }, + { + "inputs": [], + "name": "GlobalDepositLimit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidMessageSender", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sender", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdrawal", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FUEL_ASSET_DECIMALS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAUSER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "assetIssuerId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "to", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "depositLimits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "to", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "depositWithData", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "l2BurntAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "finalizeWithdrawal", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "fuelMessagePortal", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract FuelMessagePortal", + "name": "fuelMessagePortal", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "requireWhitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rescueETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "sendMetadata", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "setAssetIssuerId", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "setGlobalDepositLimit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "tokensDeposited", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "whitelistRequired", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "numDeployments": 1, + "implementation": "0xdF018d3163FA9FC70FD6eD79D3E0E3770A034756" +} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/FuelMessagePortal.json b/packages/solidity-contracts/deployments/testnet/FuelMessagePortal.json new file mode 100644 index 00000000..afe6218a --- /dev/null +++ b/packages/solidity-contracts/deployments/testnet/FuelMessagePortal.json @@ -0,0 +1,926 @@ +{ + "address": "0x768f9459E3339A1F7d59CcF24C80Eb4A711a01FB", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_depositLimitGlobal", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyRelayed", + "type": "error" + }, + { + "inputs": [], + "name": "AmountPrecisionIncompatibility", + "type": "error" + }, + { + "inputs": [], + "name": "AmountTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "CurrentMessageSenderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "GlobalDepositLimit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBlockInHistoryProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidMessageInBlockProof", + "type": "error" + }, + { + "inputs": [], + "name": "MessageBlacklisted", + "type": "error" + }, + { + "inputs": [], + "name": "MessageDataTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "UnfinalizedBlock", + "type": "error" + }, + { + "inputs": [], + "name": "WithdrawalsPaused", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "messageId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "sender", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "amount", + "type": "uint64" + } + ], + "name": "MessageRelayed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sender", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "amount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "MessageSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_DECIMALS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FUEL_BASE_ASSET_DECIMALS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_MESSAGE_DATA_SIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAUSER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PRECISION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "messageId", + "type": "bytes32" + } + ], + "name": "addMessageToBlacklist", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + } + ], + "name": "depositETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "depositLimitGlobal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fuelBaseAssetDecimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "fuelChainStateContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNextOutgoingMessageNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "messageId", + "type": "bytes32" + } + ], + "name": "incomingMessageSuccessful", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract FuelChainState", + "name": "fuelChainState", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "messageIsBlacklisted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "messageSender", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pauseWithdrawals", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "sender", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "amount", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Message", + "name": "message", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "prevRoot", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "height", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "applicationHash", + "type": "bytes32" + } + ], + "internalType": "struct FuelBlockHeaderLite", + "name": "rootBlockHeader", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "prevRoot", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "height", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "daHeight", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "txCount", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "outputMessagesCount", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "txRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "outputMessagesRoot", + "type": "bytes32" + } + ], + "internalType": "struct FuelBlockHeader", + "name": "blockHeader", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "key", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct MerkleProof", + "name": "blockInHistoryProof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "key", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct MerkleProof", + "name": "messageInBlockProof", + "type": "tuple" + } + ], + "name": "relayMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "messageId", + "type": "bytes32" + } + ], + "name": "removeMessageFromBlacklist", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDeposited", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpauseWithdrawals", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawalsPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "numDeployments": 1, + "implementation": "0xC9C453fA30cd0c6A2f09Af5e1C32F839Ff7a3DD0" +} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/Token.json b/packages/solidity-contracts/deployments/testnet/Token.json new file mode 100644 index 00000000..d4dea8d9 --- /dev/null +++ b/packages/solidity-contracts/deployments/testnet/Token.json @@ -0,0 +1,475 @@ +{ + "address": "0x25E869bc5FC45e2786B4B1bEace61287e071C60e", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "_owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x310a12e685caa9ef3b4186ab13e9ad9745b5335c8d076b4cba6012fb53cef8c0", + "receipt": { + "to": null, + "from": "0xC0cBA65C478C90D779419799687f6DaF8F9F01b1", + "contractAddress": "0x25E869bc5FC45e2786B4B1bEace61287e071C60e", + "transactionIndex": 59, + "gasUsed": "817074", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x6be8cfd73c319afc4815911196414227f0a84a7beaa59930fb52ad7d9fc6c452", + "transactionHash": "0x310a12e685caa9ef3b4186ab13e9ad9745b5335c8d076b4cba6012fb53cef8c0", + "logs": [], + "blockNumber": 5791370, + "cumulativeGasUsed": "7119154", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "31fce82f72204deb1c3e677ecb77fe87", + "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"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.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"mint(address,uint256)\":{\"details\":\"Allows anyone to mint the token.\",\"params\":{\"amount\":\"The amount of the token to mint to the owner.\",\"owner\":\"The owner of the token.\"}},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"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`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Constructor.\"},\"mint(address,uint256)\":{\"notice\":\"This is a simple mint function.\"}},\"notice\":\"This token is for testing purposes.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/Token.sol\":\"Token\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xa92e4fa126feb6907daa0513ddd816b2eb91f30a808de54f63c17d0e162c3439\",\"license\":\"MIT\"},\"contracts/test/Token.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.9;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n/// @notice This token is for testing purposes.\\ncontract Token is ERC20 {\\n address public _owner;\\n\\n /// @notice Constructor.\\n constructor() ERC20(\\\"Token\\\", \\\"TKN\\\") {\\n _owner = msg.sender;\\n }\\n\\n /// @notice This is a simple mint function.\\n /// @param owner The owner of the token.\\n /// @param amount The amount of the token to mint to the owner.\\n /// @dev Allows anyone to mint the token.\\n function mint(address owner, uint256 amount) external {\\n _mint(owner, amount);\\n }\\n}\\n\",\"keccak256\":\"0xbf1a9c1cb145ebd98b1f6159fb8d617c284044ca5ab8f07678a209c411083797\",\"license\":\"UNLICENSED\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b50604051806040016040528060058152602001642a37b5b2b760d91b815250604051806040016040528060038152602001622a25a760e91b81525081600390805190602001906200006492919062000095565b5080516200007a90600490602084019062000095565b5050600580546001600160a01b031916331790555062000178565b828054620000a3906200013b565b90600052602060002090601f016020900481019282620000c7576000855562000112565b82601f10620000e257805160ff191683800117855562000112565b8280016001018555821562000112579182015b8281111562000112578251825591602001919060010190620000f5565b506200012092915062000124565b5090565b5b8082111562000120576000815560010162000125565b600181811c908216806200015057607f821691505b602082108114156200017257634e487b7160e01b600052602260045260246000fd5b50919050565b610c9780620001886000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c806340c10f191161008c578063a457c2d711610066578063a457c2d7146101bf578063a9059cbb146101d2578063b2bdfa7b146101e5578063dd62ed3e1461022a57600080fd5b806340c10f191461016c57806370a082311461018157806395d89b41146101b757600080fd5b806323b872dd116100bd57806323b872dd14610137578063313ce5671461014a578063395093511461015957600080fd5b806306fdde03146100e4578063095ea7b31461010257806318160ddd14610125575b600080fd5b6100ec610270565b6040516100f99190610a77565b60405180910390f35b610115610110366004610b13565b610302565b60405190151581526020016100f9565b6002545b6040519081526020016100f9565b610115610145366004610b3d565b61031a565b604051601281526020016100f9565b610115610167366004610b13565b61033e565b61017f61017a366004610b13565b61038a565b005b61012961018f366004610b79565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100ec610398565b6101156101cd366004610b13565b6103a7565b6101156101e0366004610b13565b61047d565b6005546102059073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f9565b610129610238366004610b9b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60606003805461027f90610bce565b80601f01602080910402602001604051908101604052809291908181526020018280546102ab90610bce565b80156102f85780601f106102cd576101008083540402835291602001916102f8565b820191906000526020600020905b8154815290600101906020018083116102db57829003601f168201915b5050505050905090565b60003361031081858561048b565b5060019392505050565b60003361032885828561063e565b610333858585610715565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906103109082908690610385908790610c22565b61048b565b6103948282610984565b5050565b60606004805461027f90610bce565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610333828686840361048b565b600033610310818585610715565b73ffffffffffffffffffffffffffffffffffffffff831661052d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff82166105d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461070f5781811015610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610467565b61070f848484840361048b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166107b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff821661085b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361070f565b73ffffffffffffffffffffffffffffffffffffffff8216610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610467565b8060026000828254610a139190610c22565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b81811015610aa457858101830151858201604001528201610a88565b81811115610ab6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b0e57600080fd5b919050565b60008060408385031215610b2657600080fd5b610b2f83610aea565b946020939093013593505050565b600080600060608486031215610b5257600080fd5b610b5b84610aea565b9250610b6960208501610aea565b9150604084013590509250925092565b600060208284031215610b8b57600080fd5b610b9482610aea565b9392505050565b60008060408385031215610bae57600080fd5b610bb783610aea565b9150610bc560208401610aea565b90509250929050565b600181811c90821680610be257607f821691505b60208210811415610c1c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008219821115610c5c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea26469706673582212208229be857565d410e6d53feda1bd4d1a3faa25a0f5741d49827aa48b07a9084e64736f6c63430008090033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100df5760003560e01c806340c10f191161008c578063a457c2d711610066578063a457c2d7146101bf578063a9059cbb146101d2578063b2bdfa7b146101e5578063dd62ed3e1461022a57600080fd5b806340c10f191461016c57806370a082311461018157806395d89b41146101b757600080fd5b806323b872dd116100bd57806323b872dd14610137578063313ce5671461014a578063395093511461015957600080fd5b806306fdde03146100e4578063095ea7b31461010257806318160ddd14610125575b600080fd5b6100ec610270565b6040516100f99190610a77565b60405180910390f35b610115610110366004610b13565b610302565b60405190151581526020016100f9565b6002545b6040519081526020016100f9565b610115610145366004610b3d565b61031a565b604051601281526020016100f9565b610115610167366004610b13565b61033e565b61017f61017a366004610b13565b61038a565b005b61012961018f366004610b79565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100ec610398565b6101156101cd366004610b13565b6103a7565b6101156101e0366004610b13565b61047d565b6005546102059073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f9565b610129610238366004610b9b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60606003805461027f90610bce565b80601f01602080910402602001604051908101604052809291908181526020018280546102ab90610bce565b80156102f85780601f106102cd576101008083540402835291602001916102f8565b820191906000526020600020905b8154815290600101906020018083116102db57829003601f168201915b5050505050905090565b60003361031081858561048b565b5060019392505050565b60003361032885828561063e565b610333858585610715565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906103109082908690610385908790610c22565b61048b565b6103948282610984565b5050565b60606004805461027f90610bce565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610333828686840361048b565b600033610310818585610715565b73ffffffffffffffffffffffffffffffffffffffff831661052d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff82166105d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461070f5781811015610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610467565b61070f848484840361048b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166107b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff821661085b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361070f565b73ffffffffffffffffffffffffffffffffffffffff8216610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610467565b8060026000828254610a139190610c22565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b81811015610aa457858101830151858201604001528201610a88565b81811115610ab6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b0e57600080fd5b919050565b60008060408385031215610b2657600080fd5b610b2f83610aea565b946020939093013593505050565b600080600060608486031215610b5257600080fd5b610b5b84610aea565b9250610b6960208501610aea565b9150604084013590509250925092565b600060208284031215610b8b57600080fd5b610b9482610aea565b9392505050565b60008060408385031215610bae57600080fd5b610bb783610aea565b9150610bc560208401610aea565b90509250929050565b600181811c90821680610be257607f821691505b60208210811415610c1c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008219821115610c5c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea26469706673582212208229be857565d410e6d53feda1bd4d1a3faa25a0f5741d49827aa48b07a9084e64736f6c63430008090033", + "devdoc": { + "kind": "dev", + "methods": { + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "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." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "mint(address,uint256)": { + "details": "Allows anyone to mint the token.", + "params": { + "amount": "The amount of the token to mint to the owner.", + "owner": "The owner of the token." + } + }, + "name()": { + "details": "Returns the name of the token." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "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`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "constructor": { + "notice": "Constructor." + }, + "mint(address,uint256)": { + "notice": "This is a simple mint function." + } + }, + "notice": "This token is for testing purposes.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 5990, + "contract": "contracts/test/Token.sol:Token", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 5996, + "contract": "contracts/test/Token.sol:Token", + "label": "_allowances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 5998, + "contract": "contracts/test/Token.sol:Token", + "label": "_totalSupply", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 6000, + "contract": "contracts/test/Token.sol:Token", + "label": "_name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 6002, + "contract": "contracts/test/Token.sol:Token", + "label": "_symbol", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + }, + { + "astId": 13868, + "contract": "contracts/test/Token.sol:Token", + "label": "_owner", + "offset": 0, + "slot": "5", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/solcInputs/31fce82f72204deb1c3e677ecb77fe87.json b/packages/solidity-contracts/deployments/testnet/solcInputs/31fce82f72204deb1c3e677ecb77fe87.json new file mode 100644 index 00000000..720f1936 --- /dev/null +++ b/packages/solidity-contracts/deployments/testnet/solcInputs/31fce82f72204deb1c3e677ecb77fe87.json @@ -0,0 +1,257 @@ +{ + "language": "Solidity", + "sources": { + "@fuel-contracts/merkle-sol/contracts/tree/binary/BinaryMerkleProof.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\n/// @notice Merkle Tree Node structure.\nstruct BinaryMerkleProof {\n bytes32[] proof;\n uint256 key;\n uint256 numLeaves;\n}\n" + }, + "@fuel-contracts/merkle-sol/contracts/tree/binary/BinaryMerkleTree.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\nimport {Node} from \"./Node.sol\";\nimport {nodeDigest, leafDigest, hashNode} from \"./TreeHasher.sol\";\nimport {hashLeaf} from \"./TreeHasher.sol\";\nimport {MerkleBranch} from \"./Branch.sol\";\nimport {BinaryMerkleProof} from \"./BinaryMerkleProof.sol\";\nimport {Constants} from \"../Constants.sol\";\nimport {pathLengthFromKey, getStartingBit} from \"../Utils.sol\";\nimport {getBitAtFromMSB} from \"../Utils.sol\";\nimport {verifyBinaryTree, verifyBinaryTreeDigest} from \"./BinaryMerkleTreeUtils.sol\";\nimport {computeBinaryTreeRoot} from \"./BinaryMerkleTreeUtils.sol\";\nimport {getPtrToNode, getNodeAtPtr} from \"./BinaryMerkleTreeUtils.sol\";\nimport {addBranch, sideNodesForRoot} from \"./BinaryMerkleTreeUtils.sol\";\n\n/// @title Binary Merkle Tree.\n/// @notice spec can be found at https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/cryptographicprimitives.md#binary-merkle-tree.\nlibrary BinaryMerkleTree {\n /// @notice Verify if element (key, data) exists in Merkle tree, given data, proof, and root.\n /// @param root: The root of the tree in which verify the given leaf\n /// @param data: The data of the leaf to verify\n /// @param key: The key of the leaf to verify.\n /// @param proof: Binary Merkle Proof for the leaf.\n /// @param numLeaves: The number of leaves in the tree\n /// @return : Whether the proof is valid\n /// @dev numLeaves is necessary to determine height of sub-tree containing the data to prove\n function verify(\n bytes32 root,\n bytes memory data,\n bytes32[] memory proof,\n uint256 key,\n uint256 numLeaves\n ) public pure returns (bool) {\n return verifyBinaryTree(root, data, proof, key, numLeaves);\n }\n\n /// @notice Verify if element (key, digest) exists in Merkle tree, given digest, proof, and root.\n /// @param root: The root of the tree in which verify the given leaf\n /// @param digest: The digest of the data of the leaf to verify\n /// @param key: The key of the leaf to verify.\n /// @param proof: Binary Merkle Proof for the leaf.\n /// @param numLeaves: The number of leaves in the tree\n /// @return : Whether the proof is valid\n /// @dev numLeaves is necessary to determine height of sub-tree containing the data to prove\n function verifyDigest(\n bytes32 root,\n bytes32 digest,\n bytes32[] memory proof,\n uint256 key,\n uint256 numLeaves\n ) public pure returns (bool) {\n return verifyBinaryTreeDigest(root, digest, proof, key, numLeaves);\n }\n\n /// @notice Computes Merkle tree root from leaves.\n /// @param data: list of leaves' data in ascending for leaves order.\n /// @return : The root of the tree\n function computeRoot(bytes[] memory data) public pure returns (bytes32) {\n return computeBinaryTreeRoot(data);\n }\n\n /// @notice Appends a new element by calculating new root, returns new root and if successful, pure function.\n /// @param numLeaves, number of leaves in the tree currently.\n /// @param data, The data of the leaf to append.\n /// @param proof, Binary Merkle Proof to use for the leaf.\n /// @return : The root of the new tree\n /// @return : Whether the proof is valid\n function append(\n uint256 numLeaves,\n bytes memory data,\n bytes32[] memory proof\n ) public pure returns (bytes32, bool) {\n bytes32 digest = leafDigest(data);\n\n // Since appended leaf is last leaf in tree by definition, its path consists only of set bits\n // (because all side nodes will be on its left)\n // Therefore, the number of steps in the proof should equal number of bits set in the key\n // E.g. If appending the 7th leaf, key = 0b110 => proofLength = 2.\n\n uint256 proofLength = 0;\n while (numLeaves > 0) {\n proofLength += numLeaves & 1;\n numLeaves = numLeaves >> 1;\n }\n\n if (proof.length != proofLength) {\n return (Constants.NULL, false);\n }\n\n // If proof length is correctly 0, tree is empty, and we are appending the first leaf\n if (proofLength == 0) {\n digest = leafDigest(data);\n }\n // Otherwise tree non-empty so we calculate nodes up to root\n else {\n for (uint256 i = 0; i < proofLength; ++i) {\n digest = nodeDigest(proof[i], digest);\n }\n }\n\n return (digest, true);\n }\n\n /// @notice Update a given leaf\n /// @param key: The key of the leaf to be added\n /// @param value: The data to update the leaf with\n /// @param sideNodes: The sideNodes from the leaf to the root\n /// @param numLeaves: The total number of leaves in the tree\n /// @return currentPtr : The pointer to the root of the tree\n function updateWithSideNodes(\n bytes32 key,\n bytes memory value,\n bytes32[] memory sideNodes,\n uint256 numLeaves\n ) public pure returns (bytes32 currentPtr) {\n Node memory currentNode = hashLeaf(value);\n currentPtr = getPtrToNode(currentNode);\n\n // If numleaves <= 1, then the root is just the leaf hash (or ZERO)\n if (numLeaves > 1) {\n uint256 startingBit = getStartingBit(numLeaves);\n uint256 pathLength = pathLengthFromKey(uint256(key), numLeaves);\n\n for (uint256 i = 0; i < pathLength; i += 1) {\n if (getBitAtFromMSB(key, startingBit + pathLength - 1 - i) == 1) {\n currentNode = hashNode(\n sideNodes[i],\n currentPtr,\n getNodeAtPtr(sideNodes[i]).digest,\n currentNode.digest\n );\n } else {\n currentNode = hashNode(\n currentPtr,\n sideNodes[i],\n currentNode.digest,\n getNodeAtPtr(sideNodes[i]).digest\n );\n }\n\n currentPtr = getPtrToNode(currentNode);\n }\n }\n }\n\n /// @notice Add an array of branches and update one of them\n /// @param branches: The array of branches to add\n /// @param root: The root of the tree\n /// @param key: The key of the leaf to be added\n /// @param value: The data to update the leaf with\n /// @param numLeaves: The total number of leaves in the tree\n /// @return newRoot : The new root of the tree\n function addBranchesAndUpdate(\n MerkleBranch[] memory branches,\n bytes32 root,\n bytes32 key,\n bytes memory value,\n uint256 numLeaves\n ) public pure returns (bytes32 newRoot) {\n bytes32 rootPtr = Constants.ZERO;\n for (uint256 i = 0; i < branches.length; i++) {\n rootPtr = addBranch(\n branches[i].key,\n branches[i].value,\n branches[i].proof,\n root,\n rootPtr,\n numLeaves\n );\n }\n\n bytes32[] memory sideNodes = sideNodesForRoot(key, rootPtr, numLeaves);\n bytes32 newRootPtr = updateWithSideNodes(key, value, sideNodes, numLeaves);\n\n return getNodeAtPtr(newRootPtr).digest;\n }\n\n /// @notice Derive the proof for a new appended leaf from the proof for the last appended leaf\n /// @param oldProof: The proof to the last appeneded leaf\n /// @param lastLeaf: The last leaf hash\n /// @param key: The key of the new leaf\n /// @return : The proof for the appending of the new leaf\n /// @dev This function assumes that oldProof has been verified in position (key - 1)\n function deriveAppendProofFromLastProof(\n bytes32[] memory oldProof,\n bytes32 lastLeaf,\n uint256 key\n ) public pure returns (bytes32[] memory) {\n // First prepend last leaf to its proof.\n bytes32[] memory newProofBasis = new bytes32[](oldProof.length + 1);\n newProofBasis[0] = leafDigest(abi.encodePacked(lastLeaf));\n for (uint256 i = 0; i < oldProof.length; i += 1) {\n newProofBasis[i + 1] = oldProof[i];\n }\n\n // If the new leaf is \"even\", this will already be the new proof\n if (key & 1 == 1) {\n return newProofBasis;\n }\n\n // Otherwise, get the expected length of the new proof (it's the last leaf by definition, so numLeaves = key + 1)\n // Assuming old proof was valid, this will always be shorter than the old proof.\n uint256 expectedProofLength = pathLengthFromKey(key, key + 1);\n\n bytes32[] memory newProof = new bytes32[](expectedProofLength);\n\n // \"Hash up\" through old proof until we have the correct first sidenode\n bytes32 firstSideNode = newProofBasis[0];\n uint256 hashedUpIndex = 0;\n while (hashedUpIndex < (newProofBasis.length - expectedProofLength)) {\n firstSideNode = nodeDigest(newProofBasis[hashedUpIndex + 1], firstSideNode);\n hashedUpIndex += 1;\n }\n\n // Set the calculated first side node as the first element in the proof\n newProof[0] = firstSideNode;\n\n // Then append the remaining (unchanged) sidenodes, if any\n for (uint256 j = 1; j < expectedProofLength; j += 1) {\n newProof[j] = newProofBasis[hashedUpIndex + j];\n }\n\n return newProof;\n }\n}\n" + }, + "@fuel-contracts/merkle-sol/contracts/tree/binary/BinaryMerkleTreeUtils.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\nimport {Node} from \"./Node.sol\";\nimport {nodeDigest, leafDigest} from \"./TreeHasher.sol\";\nimport {parseNode, isLeaf} from \"./TreeHasher.sol\";\nimport {BinaryMerkleProof} from \"./BinaryMerkleProof.sol\";\nimport {Constants} from \"../Constants.sol\";\nimport {pathLengthFromKey, getStartingBit} from \"../Utils.sol\";\nimport {getBitAtFromMSB, reverseSideNodes} from \"../Utils.sol\";\nimport {shrinkBytes32Array} from \"../Utils.sol\";\n\n/// @notice Get the pointer to a node in memory\n/// @param node: The node to get the pointer to\n/// @return ptr : The pointer to the node\n// solhint-disable-next-line func-visibility\nfunction getPtrToNode(Node memory node) pure returns (bytes32 ptr) {\n assembly {\n ptr := node\n }\n}\n\n/// @notice Get a node at a given pointer\n/// @param ptr: The pointer to the node\n/// @return node : The node\n// solhint-disable-next-line func-visibility\nfunction getNodeAtPtr(bytes32 ptr) pure returns (Node memory node) {\n assembly {\n node := ptr\n }\n}\n\n/// @notice Verify if element (key, data) exists in Merkle tree, given data, proof, and root.\n/// @param root: The root of the tree in which verify the given leaf\n/// @param data: The data of the leaf to verify\n/// @param key: The key of the leaf to verify.\n/// @param proof: Binary Merkle Proof for the leaf.\n/// @param numLeaves: The number of leaves in the tree\n/// @return : Whether the proof is valid\n/// @dev numLeaves is necessary to determine height of sub-tree containing the data to prove\n// solhint-disable-next-line func-visibility\nfunction verifyBinaryTree(\n bytes32 root,\n bytes memory data,\n bytes32[] memory proof,\n uint256 key,\n uint256 numLeaves\n) pure returns (bool) {\n // A sibling at height 1 is created by getting the hash of the data to prove.\n return verifyBinaryTreeDigest(root, leafDigest(data), proof, key, numLeaves);\n}\n\n/// @notice Verify if element (key, digest) exists in Merkle tree, given digest, proof, and root.\n/// @param root: The root of the tree in which verify the given leaf\n/// @param digest: The digest of the data of the leaf to verify\n/// @param key: The key of the leaf to verify.\n/// @param proof: Binary Merkle Proof for the leaf.\n/// @param numLeaves: The number of leaves in the tree\n/// @return : Whether the proof is valid\n/// @dev numLeaves is necessary to determine height of sub-tree containing the data to prove\n// solhint-disable-next-line func-visibility\nfunction verifyBinaryTreeDigest(\n bytes32 root,\n bytes32 digest,\n bytes32[] memory proof,\n uint256 key,\n uint256 numLeaves\n) pure returns (bool) {\n // Check proof is correct length for the key it is proving\n if (numLeaves <= 1) {\n if (proof.length != 0) {\n return false;\n }\n } else if (proof.length != pathLengthFromKey(key, numLeaves)) {\n return false;\n }\n\n // Check key is in tree\n if (key >= numLeaves) {\n return false;\n }\n\n // Null proof is only valid if numLeaves = 1\n // If so, just verify digest is root\n if (proof.length == 0) {\n if (numLeaves == 1) {\n return (root == digest);\n } else {\n return false;\n }\n }\n\n uint256 height = 1;\n uint256 stableEnd = key;\n\n // While the current subtree (of height 'height') is complete, determine\n // the position of the next sibling using the complete subtree algorithm.\n // 'stableEnd' tells us the ending index of the last full subtree. It gets\n // initialized to 'key' because the first full subtree was the\n // subtree of height 1, created above (and had an ending index of\n // 'key').\n\n while (true) {\n // Determine if the subtree is complete. This is accomplished by\n // rounding down the key to the nearest 1 << 'height', adding 1\n // << 'height', and comparing the result to the number of leaves in the\n // Merkle tree.\n\n uint256 subTreeStartIndex = (key / (1 << height)) * (1 << height);\n uint256 subTreeEndIndex = subTreeStartIndex + (1 << height) - 1;\n\n // If the Merkle tree does not have a leaf at index\n // 'subTreeEndIndex', then the subtree of the current height is not\n // a complete subtree.\n if (subTreeEndIndex >= numLeaves) {\n break;\n }\n stableEnd = subTreeEndIndex;\n\n // Determine if the key is in the first or the second half of\n // the subtree.\n if (proof.length <= height - 1) {\n return false;\n }\n if (key - subTreeStartIndex < (1 << (height - 1))) {\n digest = nodeDigest(digest, proof[height - 1]);\n } else {\n digest = nodeDigest(proof[height - 1], digest);\n }\n\n height += 1;\n }\n\n // Determine if the next hash belongs to an orphan that was elevated. This\n // is the case IFF 'stableEnd' (the last index of the largest full subtree)\n // is equal to the number of leaves in the Merkle tree.\n if (stableEnd != numLeaves - 1) {\n if (proof.length <= height - 1) {\n return false;\n }\n digest = nodeDigest(digest, proof[height - 1]);\n height += 1;\n }\n\n // All remaining elements in the proof set will belong to a left sibling\\\n // i.e proof sideNodes are hashed in \"from the left\"\n while (height - 1 < proof.length) {\n digest = nodeDigest(proof[height - 1], digest);\n height += 1;\n }\n\n return (digest == root);\n}\n\n/// @notice Computes Merkle tree root from leaves.\n/// @param data: list of leaves' data in ascending for leaves order.\n/// @return : The root of the tree\n// solhint-disable-next-line func-visibility\nfunction computeBinaryTreeRoot(bytes[] memory data) pure returns (bytes32) {\n if (data.length == 0) {\n return Constants.EMPTY;\n }\n bytes32[] memory nodes = new bytes32[](data.length);\n for (uint256 i = 0; i < data.length; ++i) {\n nodes[i] = leafDigest(data[i]);\n }\n uint256 size = (nodes.length + 1) >> 1;\n uint256 odd = nodes.length & 1;\n // pNodes are nodes in previous level.\n // We use pNodes to avoid damaging the input leaves.\n bytes32[] memory pNodes = nodes;\n while (true) {\n uint256 i = 0;\n for (; i < size - odd; ++i) {\n uint256 j = i << 1;\n nodes[i] = nodeDigest(pNodes[j], pNodes[j + 1]);\n }\n if (odd == 1) {\n nodes[i] = pNodes[i << 1];\n }\n if (size == 1) {\n break;\n }\n odd = (size & 1);\n size = (size + 1) >> 1;\n pNodes = nodes;\n }\n return nodes[0];\n}\n\n/// @notice Appends a new element by calculating new root, returns new root and if successful, pure function.\n/// @param numLeaves, number of leaves in the tree currently.\n/// @param data, The data of the leaf to append.\n/// @param proof, Binary Merkle Proof to use for the leaf.\n/// @return : The root of the new tree\n/// @return : Whether the proof is valid\n// solhint-disable-next-line func-visibility\nfunction appendBinaryTree(\n uint256 numLeaves,\n bytes memory data,\n bytes32[] memory proof\n) pure returns (bytes32, bool) {\n bytes32 digest = leafDigest(data);\n\n // Since appended leaf is last leaf in tree by definition, its path consists only of set bits\n // (because all side nodes will be on its left)\n // Therefore, the number of steps in the proof should equal number of bits set in the key\n // E.g. If appending the 7th leaf, key = 0b110 => proofLength = 2.\n\n uint256 proofLength = 0;\n while (numLeaves > 0) {\n proofLength += numLeaves & 1;\n numLeaves = numLeaves >> 1;\n }\n\n if (proof.length != proofLength) {\n return (Constants.NULL, false);\n }\n\n // If proof length is correctly 0, tree is empty, and we are appending the first leaf\n if (proofLength == 0) {\n digest = leafDigest(data);\n }\n // Otherwise tree non-empty so we calculate nodes up to root\n else {\n for (uint256 i = 0; i < proofLength; ++i) {\n digest = nodeDigest(proof[i], digest);\n }\n }\n\n return (digest, true);\n}\n\n/// @notice Adds a branch to the in-storage sparse representation of tree\n/// @dev We store the minimum subset of nodes necessary to calculate the root\n/// @param key: The key of the leaf\n/// @param value : The data of the leaf\n/// @param root : The root of the tree containing the added branch\n/// @param rootPtr : The pointer to the root node\n/// @param proof: The proof (assumed valid) of the leaf up to the root\n/// @param numLeaves: The total number of leaves in the tree\n/// @return : The pointer to the root node\n// solhint-disable-next-line func-visibility\nfunction addBranch(\n bytes32 key,\n bytes memory value,\n bytes32[] memory proof,\n bytes32 root,\n bytes32 rootPtr,\n uint256 numLeaves\n) pure returns (bytes32) {\n // Handle case where tree has only one leaf (so it is the root)\n if (numLeaves == 1) {\n Node memory rootNode = Node(root, Constants.NULL, Constants.NULL);\n rootPtr = getPtrToNode(rootNode);\n return rootPtr;\n }\n uint256 startingBit = getStartingBit(numLeaves);\n\n AddBranchVariables memory variables;\n\n bytes32[] memory sideNodePtrs = new bytes32[](proof.length);\n bytes32[] memory nodePtrs = new bytes32[](proof.length);\n\n // Set root\n // When adding the first branch, rootPtr will not be set yet, set it here.\n if (rootPtr == Constants.NULL) {\n // Set the new root\n Node memory rootNode = Node(root, Constants.NULL, Constants.NULL);\n rootPtr = getPtrToNode(rootNode);\n variables.parent = rootNode;\n }\n // On subsequent branches, we need to retrieve root\n else {\n variables.parent = getNodeAtPtr(rootPtr);\n }\n\n // Step backwards through proof (from root down to leaf), getting pointers to the nodes/sideNodes\n // If node is not yet added, set digest to NULL (we'll set it when we hash back up the branch)\n for (uint256 i = proof.length; i > 0; i -= 1) {\n uint256 j = i - 1;\n\n // Descend into left or right subtree depending on key\n // If leaf is in the right subtree:\n if (getBitAtFromMSB(key, startingBit + proof.length - i) == 1) {\n // Subtree is on the right, so sidenode is on the left.\n // Check to see if sidenode already exists. If not, create it. and associate with parent\n if (variables.parent.leftChildPtr == Constants.NULL) {\n variables.sideNode = Node(proof[j], Constants.NULL, Constants.NULL);\n variables.sideNodePtr = getPtrToNode(variables.sideNode);\n variables.parent.leftChildPtr = variables.sideNodePtr;\n } else {\n variables.sideNodePtr = variables.parent.leftChildPtr;\n }\n\n // Check to see if node already exists. If not, create it. and associate with parent\n // Its digest is initially null. We calculate and set it when we climb back up the tree\n if (variables.parent.rightChildPtr == Constants.NULL) {\n variables.node = Node(Constants.NULL, Constants.NULL, Constants.NULL);\n variables.nodePtr = getPtrToNode(variables.node);\n variables.parent.rightChildPtr = variables.nodePtr;\n } else {\n variables.nodePtr = variables.parent.rightChildPtr;\n variables.node = getNodeAtPtr(variables.nodePtr);\n }\n\n // Mirror image of preceding code block, for when leaf is in the left subtree\n // If subtree is on the left, sideNode is on the right\n } else {\n if (variables.parent.rightChildPtr == Constants.NULL) {\n variables.sideNode = Node(proof[j], Constants.NULL, Constants.NULL);\n variables.sideNodePtr = getPtrToNode(variables.sideNode);\n variables.parent.rightChildPtr = variables.sideNodePtr;\n } else {\n variables.sideNodePtr = variables.parent.rightChildPtr;\n }\n\n if (variables.parent.leftChildPtr == Constants.NULL) {\n variables.node = Node(Constants.NULL, Constants.NULL, Constants.NULL);\n variables.nodePtr = getPtrToNode(variables.node);\n variables.parent.leftChildPtr = variables.nodePtr;\n } else {\n variables.nodePtr = variables.parent.leftChildPtr;\n variables.node = getNodeAtPtr(variables.nodePtr);\n }\n }\n\n // Keep pointers to sideNode and node\n sideNodePtrs[j] = variables.sideNodePtr;\n nodePtrs[j] = variables.nodePtr;\n\n variables.parent = variables.node;\n }\n\n // Set leaf digest\n Node memory leaf = getNodeAtPtr(nodePtrs[0]);\n leaf.digest = leafDigest(value);\n\n if (proof.length == 0) {\n return rootPtr;\n }\n\n // Go back up the tree, setting the digests of nodes on the branch\n for (uint256 i = 1; i < nodePtrs.length; i += 1) {\n variables.node = getNodeAtPtr(nodePtrs[i]);\n variables.node.digest = nodeDigest(\n getNodeAtPtr(variables.node.leftChildPtr).digest,\n getNodeAtPtr(variables.node.rightChildPtr).digest\n );\n }\n\n return rootPtr;\n}\n\n/// @notice Get the sidenodes for a given leaf key up to the root\n/// @param key: The key for which to find the sidenodes\n/// @param rootPtr: The memory pointer to the root of the tree\n/// @param numLeaves : The total number of leaves in the tree\n/// @return The sidenodes up to the root.\n// solhint-disable-next-line func-visibility\nfunction sideNodesForRoot(\n bytes32 key,\n bytes32 rootPtr,\n uint256 numLeaves\n) pure returns (bytes32[] memory) {\n // Allocate a large enough array for the sidenodes (we'll shrink it later)\n bytes32[] memory sideNodes = new bytes32[](256);\n\n Node memory currentNode = getNodeAtPtr(rootPtr);\n\n // If the root is a placeholder, the tree is empty, so there are no sidenodes to return.\n // The leaf pointer is the root pointer\n if (currentNode.digest == Constants.ZERO) {\n bytes32[] memory emptySideNodes;\n return emptySideNodes;\n }\n\n // If the root is a leaf, the tree has only one leaf, so there are also no sidenodes to return.\n // The leaf pointer is the root pointer\n if (isLeaf(currentNode)) {\n bytes32[] memory emptySideNodes;\n return emptySideNodes;\n }\n\n // Tree has at least 2 leaves\n SideNodesFunctionVariables memory variables;\n\n variables.sideNodeCount = 0;\n\n uint256 startingBit = getStartingBit(numLeaves);\n uint256 pathLength = pathLengthFromKey(uint256(key), numLeaves);\n\n // Descend the tree from the root according to the key, collecting side nodes\n for (uint256 i = startingBit; i < startingBit + pathLength; i++) {\n (variables.leftNodePtr, variables.rightNodePtr) = parseNode(currentNode);\n // Bifurcate left or right depending on bit in key\n if (getBitAtFromMSB(key, i) == 1) {\n (variables.nodePtr, variables.sideNodePtr) = (\n variables.rightNodePtr,\n variables.leftNodePtr\n );\n } else {\n (variables.nodePtr, variables.sideNodePtr) = (\n variables.leftNodePtr,\n variables.rightNodePtr\n );\n }\n\n sideNodes[variables.sideNodeCount] = variables.sideNodePtr;\n variables.sideNodeCount += 1;\n\n currentNode = getNodeAtPtr(variables.nodePtr);\n }\n\n return reverseSideNodes(shrinkBytes32Array(sideNodes, variables.sideNodeCount));\n}\n\nstruct AddBranchVariables {\n bytes32 nodePtr;\n bytes32 sideNodePtr;\n Node node;\n Node parent;\n Node sideNode;\n}\n\n/// @notice A struct to hold variables of the sidenodes function in memory\n/// @dev Necessary to circumvent stack-too-deep errors caused by too many\n/// @dev variables on the stack.\nstruct SideNodesFunctionVariables {\n bytes32 leftNodePtr;\n bytes32 rightNodePtr;\n bytes32 nodePtr;\n bytes32 sideNodePtr;\n uint256 sideNodeCount;\n}\n" + }, + "@fuel-contracts/merkle-sol/contracts/tree/binary/Branch.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\nstruct MerkleBranch {\n bytes32[] proof;\n bytes32 key;\n bytes value;\n}\n" + }, + "@fuel-contracts/merkle-sol/contracts/tree/binary/Node.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\n/// @notice Merkle Tree Node structure.\nstruct Node {\n bytes32 digest;\n // Left child.\n bytes32 leftChildPtr;\n // Right child.\n bytes32 rightChildPtr;\n}\n" + }, + "@fuel-contracts/merkle-sol/contracts/tree/binary/TreeHasher.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\nimport {CryptographyLib} from \"../Cryptography.sol\";\nimport {Constants} from \"../Constants.sol\";\nimport {Node} from \"./Node.sol\";\n\n/// @notice hash some data\n/// @param data: The data to be hashed\n// solhint-disable-next-line func-visibility\nfunction hash(bytes memory data) pure returns (bytes32) {\n return CryptographyLib.hash(data);\n}\n\n/// @notice Calculate the digest of a node\n/// @param left : The left child\n/// @param right: The right child\n/// @return digest : The node digest\n// solhint-disable-next-line func-visibility\nfunction nodeDigest(bytes32 left, bytes32 right) pure returns (bytes32 digest) {\n digest = hash(abi.encodePacked(Constants.NODE_PREFIX, left, right));\n}\n\n/// @notice Calculate the digest of a leaf\n/// @param data : The data of the leaf\n/// @return digest : The leaf digest\n// solhint-disable-next-line func-visibility\nfunction leafDigest(bytes memory data) pure returns (bytes32 digest) {\n digest = hash(abi.encodePacked(Constants.LEAF_PREFIX, data));\n}\n\n/// @notice Hash a leaf node.\n/// @param data, raw data of the leaf.\n/// @return The leaf represented as a Node struct\n// solhint-disable-next-line func-visibility\nfunction hashLeaf(bytes memory data) pure returns (Node memory) {\n bytes32 digest = leafDigest(data);\n return Node(digest, Constants.NULL, Constants.NULL);\n}\n\n/// @notice Hash a node, which is not a leaf.\n/// @param left, left child hash.\n/// @param right, right child hash.\n/// @param leftPtr, the pointer to the left child\n/// @param rightPtr, the pointer to the right child\n/// @return : The new Node object\n// solhint-disable-next-line func-visibility\nfunction hashNode(\n bytes32 leftPtr,\n bytes32 rightPtr,\n bytes32 left,\n bytes32 right\n) pure returns (Node memory) {\n bytes32 digest = nodeDigest(left, right);\n return Node(digest, leftPtr, rightPtr);\n}\n\n/// @notice Parse a node's data into its left and right children\n/// @param node: The node to be parsed\n/// @return : Pointers to the left and right children\n// solhint-disable-next-line func-visibility\nfunction parseNode(Node memory node) pure returns (bytes32, bytes32) {\n return (node.leftChildPtr, node.rightChildPtr);\n}\n\n/// @notice See if node has children, otherwise it is a leaf\n/// @param node: The node to be parsed\n/// @return : Whether the node is a leaf.\n// solhint-disable-next-line func-visibility\nfunction isLeaf(Node memory node) pure returns (bool) {\n return (node.leftChildPtr == Constants.ZERO || node.rightChildPtr == Constants.ZERO);\n}\n" + }, + "@fuel-contracts/merkle-sol/contracts/tree/Constants.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\nlibrary Constants {\n ///////////////\n // Constants //\n ///////////////\n\n /// @dev Maximum tree height\n uint256 internal constant MAX_HEIGHT = 256;\n\n /// @dev Empty node hash\n bytes32 internal constant EMPTY = sha256(\"\");\n\n /// @dev Default value for sparse Merkle tree node\n bytes32 internal constant ZERO = bytes32(0);\n\n /// @dev The null pointer\n bytes32 internal constant NULL = bytes32(0);\n\n /// @dev The prefixes of leaves and nodes\n bytes1 internal constant LEAF_PREFIX = 0x00;\n bytes1 internal constant NODE_PREFIX = 0x01;\n}\n" + }, + "@fuel-contracts/merkle-sol/contracts/tree/Cryptography.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\n/// @notice This library abstracts the hashing function used for the merkle tree implementation\nlibrary CryptographyLib {\n /// @notice The hash method\n /// @param data The bytes input data.\n /// @return The returned hash result.\n function hash(bytes memory data) internal pure returns (bytes32) {\n return sha256(data);\n }\n}\n" + }, + "@fuel-contracts/merkle-sol/contracts/tree/Utils.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\nimport {Constants} from \"./Constants.sol\";\n\n/// @notice Calculate the starting bit of the path to a leaf\n/// @param numLeaves : The total number of leaves in the tree\n/// @return startingBit : The starting bit of the path\n// solhint-disable-next-line func-visibility\nfunction getStartingBit(uint256 numLeaves) pure returns (uint256 startingBit) {\n // Determine height of the left subtree. This is the maximum path length, so all paths start at this offset from the right-most bit\n startingBit = 0;\n while ((1 << startingBit) < numLeaves) {\n startingBit += 1;\n }\n return Constants.MAX_HEIGHT - startingBit;\n}\n\n/// @notice Calculate the length of the path to a leaf\n/// @param key: The key of the leaf\n/// @param numLeaves: The total number of leaves in the tree\n/// @return pathLength : The length of the path to the leaf\n/// @dev A precondition to this function is that `numLeaves > 1`, so that `(pathLength - 1)` does not cause an underflow when pathLength = 0.\n// solhint-disable-next-line func-visibility\nfunction pathLengthFromKey(uint256 key, uint256 numLeaves) pure returns (uint256 pathLength) {\n // Get the height of the left subtree. This is equal to the offset of the starting bit of the path\n pathLength = 256 - getStartingBit(numLeaves);\n\n // Determine the number of leaves in the left subtree\n uint256 numLeavesLeftSubTree = (1 << (pathLength - 1));\n\n // If leaf is in left subtree, path length is full height of left subtree\n if (key <= numLeavesLeftSubTree - 1) {\n return pathLength;\n }\n // Otherwise, if left sub tree has only one leaf, path has one additional step\n else if (numLeavesLeftSubTree == 1) {\n return 1;\n }\n // Otherwise, if right sub tree has only one leaf, path has one additional step\n else if (numLeaves - numLeavesLeftSubTree <= 1) {\n return 1;\n }\n // Otherwise, add 1 to height and recurse into right subtree\n else {\n return 1 + pathLengthFromKey(key - numLeavesLeftSubTree, numLeaves - numLeavesLeftSubTree);\n }\n}\n\n/// @notice Gets the bit at an offset from the most significant bit\n/// @param data: The data to check the bit\n/// @param position: The position of the bit to check\n// solhint-disable-next-line func-visibility\nfunction getBitAtFromMSB(bytes32 data, uint256 position) pure returns (uint256) {\n if (uint8(data[position / 8]) & (1 << (8 - 1 - (position % 8))) > 0) {\n return 1;\n } else {\n return 0;\n }\n}\n\n/// @notice Reverses an array\n/// @param sideNodes: The array of sidenodes to be reversed\n/// @return The reversed array\n// solhint-disable-next-line func-visibility\nfunction reverseSideNodes(bytes32[] memory sideNodes) pure returns (bytes32[] memory) {\n uint256 left = 0;\n uint256 right = sideNodes.length - 1;\n\n while (left < right) {\n (sideNodes[left], sideNodes[right]) = (sideNodes[right], sideNodes[left]);\n left = left + 1;\n right = right - 1;\n }\n return sideNodes;\n}\n\n/// @notice Counts the number of leading bits two bytes32 have in common\n/// @param data1: The first piece of data to compare\n/// @param data2: The second piece of data to compare\n/// @return The number of shared leading bits\n// solhint-disable-next-line func-visibility\nfunction countCommonPrefix(bytes32 data1, bytes32 data2) pure returns (uint256) {\n uint256 count = 0;\n\n for (uint256 i = 0; i < Constants.MAX_HEIGHT; i++) {\n if (getBitAtFromMSB(data1, i) == getBitAtFromMSB(data2, i)) {\n count += 1;\n } else {\n break;\n }\n }\n return count;\n}\n\n/// @notice Shrinks an over-allocated dynamic array of bytes32 to the correct size\n/// @param inputArray: The bytes32 array to be shrunk\n/// @param length: The length to shrink to\n/// @return finalArray : The full array of bytes32\n/// @dev Needed where an unknown number of elements are to be pushed to a dynamic array\n/// @dev We fist allocate a large-enough array, and then shrink once we're done populating it\n// solhint-disable-next-line func-visibility\nfunction shrinkBytes32Array(bytes32[] memory inputArray, uint256 length)\n pure\n returns (bytes32[] memory finalArray)\n{\n finalArray = new bytes32[](length);\n for (uint256 i = 0; i < length; i++) {\n finalArray[i] = inputArray[i];\n }\n return finalArray;\n}\n\n/// @notice compares a byte array to the (bytes32) default (ZERO) value\n/// @param value : The bytes to compare\n/// @dev No byte array comparison in solidity, so compare keccak hashes\n// solhint-disable-next-line func-visibility\nfunction isDefaultValue(bytes memory value) pure returns (bool) {\n return keccak256(value) == keccak256(abi.encodePacked(Constants.ZERO));\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../utils/StringsUpgradeable.sol\";\nimport \"../utils/introspection/ERC165Upgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n function __AccessControl_init() internal onlyInitializing {\n }\n\n function __AccessControl_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n StringsUpgradeable.toHexString(account),\n \" is missing role \",\n StringsUpgradeable.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControlUpgradeable {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822ProxiableUpgradeable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.8.3._\n */\ninterface IERC1967Upgradeable {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeaconUpgradeable {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeaconUpgradeable.sol\";\nimport \"../../interfaces/IERC1967Upgradeable.sol\";\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/StorageSlotUpgradeable.sol\";\nimport {Initializable} from \"../utils/Initializable.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n */\nabstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n function __ERC1967Upgrade_init() internal onlyInitializing {\n }\n\n function __ERC1967Upgrade_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(AddressUpgradeable.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n AddressUpgradeable.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(AddressUpgradeable.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);\n }\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../ERC1967/ERC1967UpgradeUpgradeable.sol\";\nimport {Initializable} from \"./Initializable.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n address private immutable __self = address(this);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n require(address(this) != __self, \"Function must be called through delegatecall\");\n require(_getImplementation() == __self, \"Function must be called through active proxy\");\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n _;\n }\n\n function __UUPSUpgradeable_init() internal onlyInitializing {\n }\n\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n return _IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeTo(address newImplementation) public virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data, true);\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal override onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721Upgradeable is IERC165Upgradeable {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165Upgradeable.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\n function __ERC165_init() internal onlyInitializing {\n }\n\n function __ERC165_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165Upgradeable).interfaceId;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary MathUpgradeable {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMathUpgradeable {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlotUpgradeable {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/MathUpgradeable.sol\";\nimport \"./math/SignedMathUpgradeable.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = MathUpgradeable.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMathUpgradeable.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, MathUpgradeable.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(address from, address to, uint256 amount) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/ERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n using Address for address;\n using Strings for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: address zero is not a valid owner\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _ownerOf(tokenId);\n require(owner != address(0), \"ERC721: invalid token ID\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n _requireMinted(tokenId);\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not token owner or approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n _requireMinted(tokenId);\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(address from, address to, uint256 tokenId) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n _safeTransfer(from, to, tokenId, data);\n }\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n */\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n return _owners[tokenId];\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _ownerOf(tokenId) != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n address owner = ERC721.ownerOf(tokenId);\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId, 1);\n\n // Check that tokenId was not minted by `_beforeTokenTransfer` hook\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n unchecked {\n // Will not overflow unless all 2**256 token ids are minted to the same owner.\n // Given that tokens are minted one by one, it is impossible in practice that\n // this ever happens. Might change if we allow batch minting.\n // The ERC fails to describe this case.\n _balances[to] += 1;\n }\n\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n\n _afterTokenTransfer(address(0), to, tokenId, 1);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n * This is an internal function that does not check if the sender is authorized to operate on the token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId, 1);\n\n // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\n owner = ERC721.ownerOf(tokenId);\n\n // Clear approvals\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // Cannot overflow, as that would require more tokens to be burned/transferred\n // out than the owner initially received through minting and transferring in.\n _balances[owner] -= 1;\n }\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n\n _afterTokenTransfer(owner, address(0), tokenId, 1);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(address from, address to, uint256 tokenId) internal virtual {\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId, 1);\n\n // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n\n // Clear approvals from the previous owner\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\n // `from`'s balance is the number of token held, which is at least one before the current\n // transfer.\n // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\n // all 2**256 token ids to be minted, which in practice is impossible.\n _balances[from] -= 1;\n _balances[to] += 1;\n }\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n _afterTokenTransfer(from, to, tokenId, 1);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits an {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\n return retval == IERC721Receiver.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\n * - When `from` is zero, the tokens will be minted for `to`.\n * - When `to` is zero, ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\n * - When `from` is zero, the tokens were minted for `to`.\n * - When `to` is zero, ``from``'s tokens were burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\n\n /**\n * @dev Unsafe write access to the balances, used by extensions that \"mint\" tokens using an {ownerOf} override.\n *\n * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant\n * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such\n * that `ownerOf(tokenId)` is `a`.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __unsafe_increaseBalance(address account, uint256 amount) internal {\n _balances[account] += amount;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "contracts/fuelchain/FuelChainState.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n// solhint-disable not-rely-on-time\npragma solidity 0.8.9;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {AccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {CryptographyLib} from \"../lib/Cryptography.sol\";\n\n/// @notice Structure for commits\nstruct Commit {\n bytes32 blockHash;\n uint32 timestamp;\n address reserved1;\n uint16 reserved2;\n}\n\n/// @notice The Fuel v2 chain state\ncontract FuelChainState is Initializable, PausableUpgradeable, AccessControlUpgradeable, UUPSUpgradeable {\n ///////////////\n // Constants //\n ///////////////\n\n /// @dev The commit proccess parameters\n //TODO: update these values once block time and commit frequency are finalized\n // days worth of commits\n // NUM_COMMIT_SLOTS an arbitrary number of commits to store before starting to overwrite\n uint256 public constant NUM_COMMIT_SLOTS = 240;\n // Number of blocks per commit interval\n // BLOCKS_PER_COMMIT_INTERVAL = (num of blocks per minute * target interval in minutes)\n uint256 public constant BLOCKS_PER_COMMIT_INTERVAL = 10800;\n // Time to fianlize in seconds\n // TIME_TO_FINALIZE = target interval in minutes * 60\n uint256 public constant TIME_TO_FINALIZE = 10800;\n\n /// @dev The admin related contract roles\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n bytes32 public constant COMMITTER_ROLE = keccak256(\"COMMITTER_ROLE\");\n\n ////////////\n // Events //\n ////////////\n\n /// @dev Emitted when a commit is first submitted\n event CommitSubmitted(uint256 indexed commitHeight, bytes32 blockHash);\n\n ////////////\n // Errors //\n ////////////\n\n error UnknownBlock();\n\n /////////////\n // Storage //\n /////////////\n\n /// @dev The commits buffer\n Commit[NUM_COMMIT_SLOTS] private _commitSlots;\n\n /////////////////////////////\n // Constructor/Initializer //\n /////////////////////////////\n\n /// @notice Constructor disables initialization for the implementation contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /// @notice Contract initializer to setup starting values\n function initialize() public initializer {\n __Pausable_init();\n __AccessControl_init();\n __UUPSUpgradeable_init();\n\n //grant initial roles\n _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _grantRole(PAUSER_ROLE, msg.sender);\n _grantRole(COMMITTER_ROLE, msg.sender);\n }\n\n /////////////////////\n // Admin Functions //\n /////////////////////\n\n /// @notice Pause block commitments\n function pause() external onlyRole(PAUSER_ROLE) {\n _pause();\n }\n\n /// @notice Unpause block commitments\n function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) {\n _unpause();\n }\n\n /// @notice Commits a block header.\n /// @dev Committing to the same commitHeight twice would have the effect of delaying\n /// finality, as the timestamp of the committed slot is taken from the ETH block\n /// timestamp. TODO: it might be reasonable to put a require here to disallow overwriting\n /// In the future we will want this to be challenge-able, and rewriting the slot\n /// could open for foul play during IVG\n /// @param blockHash The hash of a block\n /// @param commitHeight The height of the commit\n function commit(bytes32 blockHash, uint256 commitHeight) external whenNotPaused onlyRole(COMMITTER_ROLE) {\n uint256 slot = commitHeight % NUM_COMMIT_SLOTS;\n Commit storage commitSlot = _commitSlots[slot];\n commitSlot.blockHash = blockHash;\n commitSlot.timestamp = uint32(block.timestamp);\n\n emit CommitSubmitted(commitHeight, blockHash);\n }\n\n //////////////////////\n // Public Functions //\n //////////////////////\n\n /// @notice Checks if a given block is finalized\n /// @param blockHash The hash of the block to check\n /// @param blockHeight The height of the block to check\n /// @return true if the block is finalized\n function finalized(bytes32 blockHash, uint256 blockHeight) external view whenNotPaused returns (bool) {\n // TODO This division could be done offchain, or at least also could be assembly'ed to avoid non-zero division check\n uint256 commitHeight = blockHeight / BLOCKS_PER_COMMIT_INTERVAL;\n Commit storage commitSlot = _commitSlots[commitHeight % NUM_COMMIT_SLOTS];\n if (commitSlot.blockHash != blockHash) revert UnknownBlock();\n\n return block.timestamp >= uint256(commitSlot.timestamp) + TIME_TO_FINALIZE;\n }\n\n /// @notice Gets the block hash at the given commit height\n /// @param commitHeight The height of the commit\n /// @return hash of the block at the given commit height\n function blockHashAtCommit(uint256 commitHeight) external view returns (bytes32) {\n Commit storage commitSlot = _commitSlots[commitHeight % NUM_COMMIT_SLOTS];\n return commitSlot.blockHash;\n }\n\n ////////////////////////\n // Internal Functions //\n ////////////////////////\n\n /// @notice Executes a message in the given header\n // solhint-disable-next-line no-empty-blocks\n function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {\n //should revert if msg.sender is not authorized to upgrade the contract (currently only owner)\n }\n}\n" + }, + "contracts/fuelchain/FuelMessagePortal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {AccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {ReentrancyGuardUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport {verifyBinaryTree} from \"@fuel-contracts/merkle-sol/contracts/tree/binary/BinaryMerkleTree.sol\";\nimport {FuelChainState} from \"./FuelChainState.sol\";\nimport {FuelBlockHeader, FuelBlockHeaderLib} from \"./types/FuelBlockHeader.sol\";\nimport {FuelBlockHeaderLite, FuelBlockHeaderLiteLib} from \"./types/FuelBlockHeaderLite.sol\";\nimport {CryptographyLib} from \"../lib/Cryptography.sol\";\nimport {CommonPredicates} from \"../lib/CommonPredicates.sol\";\n\n/// @notice Structure for proving an element in a merkle tree\nstruct MerkleProof {\n uint256 key;\n bytes32[] proof;\n}\n\n/// @notice Structure containing all message details\nstruct Message {\n bytes32 sender;\n bytes32 recipient;\n bytes32 nonce;\n uint64 amount;\n bytes data;\n}\n\n/// @title FuelMessagePortal\n/// @notice The Fuel Message Portal contract sends messages to and from Fuel\n/// @custom:deprecation THIS CONTRACT IS DEPRECATED. CHECK FuelMessagePortalV3\ncontract FuelMessagePortal is\n Initializable,\n PausableUpgradeable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n UUPSUpgradeable\n{\n using FuelBlockHeaderLib for FuelBlockHeader;\n using FuelBlockHeaderLiteLib for FuelBlockHeaderLite;\n\n ////////////\n // Events //\n ////////////\n\n /// @dev Emitted when a message is sent from Ethereum to Fuel\n event MessageSent(\n bytes32 indexed sender,\n bytes32 indexed recipient,\n uint256 indexed nonce,\n uint64 amount,\n bytes data\n );\n\n /// @dev Emitted when a message is successfully relayed to Ethereum from Fuel\n event MessageRelayed(bytes32 indexed messageId, bytes32 indexed sender, bytes32 indexed recipient, uint64 amount);\n\n ////////////\n // Errors //\n ////////////\n\n error UnfinalizedBlock();\n error InvalidBlockInHistoryProof();\n error InvalidMessageInBlockProof();\n error CurrentMessageSenderNotSet();\n error MessageDataTooLarge();\n error AmountPrecisionIncompatibility();\n error AmountTooBig();\n error AlreadyRelayed();\n\n ///////////////\n // Constants //\n ///////////////\n\n /// @dev The admin related contract roles\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n /// @dev The number of decimals that the base Fuel asset uses\n uint256 public constant FUEL_BASE_ASSET_DECIMALS = 9;\n uint256 public constant ETH_DECIMALS = 18;\n uint256 public constant PRECISION = 10 ** (ETH_DECIMALS - FUEL_BASE_ASSET_DECIMALS);\n\n /// @dev The max message data size in bytes\n uint256 public constant MAX_MESSAGE_DATA_SIZE = 2 ** 16;\n\n /// @dev Non-zero null value to optimize gas costs\n bytes32 internal constant NULL_MESSAGE_SENDER = 0x000000000000000000000000000000000000000000000000000000000000dead;\n\n /////////////\n // Storage //\n /////////////\n\n /// @notice Current message sender for other contracts to reference\n bytes32 internal _incomingMessageSender;\n\n /// @notice The Fuel chain state contract\n FuelChainState internal _fuelChainState;\n\n /// @notice Nonce for the next message to be sent\n uint256 internal _outgoingMessageNonce;\n\n /// @notice Mapping of message hash to boolean success value\n mapping(bytes32 => bool) internal _incomingMessageSuccessful;\n\n /////////////////////////////\n // Constructor/Initializer //\n /////////////////////////////\n\n /// @notice Constructor disables initialization for the implementation contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /// @notice Contract initializer to setup starting values\n /// @param fuelChainState Chain state contract\n function initialize(FuelChainState fuelChainState) public initializer {\n __Pausable_init();\n __AccessControl_init();\n __ReentrancyGuard_init();\n __UUPSUpgradeable_init();\n\n //grant initial roles\n _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _grantRole(PAUSER_ROLE, msg.sender);\n\n //chain state contract\n _fuelChainState = fuelChainState;\n\n //outgoing message data\n _outgoingMessageNonce = 0;\n\n //incoming message data\n _incomingMessageSender = NULL_MESSAGE_SENDER;\n }\n\n /////////////////////\n // Admin Functions //\n /////////////////////\n\n /// @notice Pause outbound messages\n function pause() external virtual onlyRole(PAUSER_ROLE) {\n _pause();\n }\n\n /// @notice Unpause outbound messages\n function unpause() external virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n _unpause();\n }\n\n //////////////////////\n // Public Functions //\n //////////////////////\n\n /// @notice Gets the number of decimals used in the Fuel base asset\n /// @return decimals of the Fuel base asset\n function fuelBaseAssetDecimals() public pure virtual returns (uint8) {\n return uint8(FUEL_BASE_ASSET_DECIMALS);\n }\n\n /// @notice Gets the set Fuel chain state contract\n /// @return fuel chain state contract\n function fuelChainStateContract() public view virtual returns (address) {\n return address(_fuelChainState);\n }\n\n function getNextOutgoingMessageNonce() public view virtual returns (uint256) {\n return _outgoingMessageNonce;\n }\n\n ///////////////////////////////////////\n // Incoming Message Public Functions //\n ///////////////////////////////////////\n\n /// @notice Relays a message published on Fuel from a given block\n /// @param message The message to relay\n /// @param rootBlockHeader The root block for proving chain history\n /// @param blockHeader The block containing the message\n /// @param blockInHistoryProof Proof that the message block exists in the history of the root block\n /// @param messageInBlockProof Proof that message exists in block\n /// @dev Made payable to reduce gas costs\n function relayMessage(\n Message calldata message,\n FuelBlockHeaderLite calldata rootBlockHeader,\n FuelBlockHeader calldata blockHeader,\n MerkleProof calldata blockInHistoryProof,\n MerkleProof calldata messageInBlockProof\n ) external payable virtual whenNotPaused {\n //verify root block header\n if (!_fuelChainState.finalized(rootBlockHeader.computeConsensusHeaderHash(), rootBlockHeader.height)) {\n revert UnfinalizedBlock();\n }\n\n //verify block in history\n if (\n !verifyBinaryTree(\n rootBlockHeader.prevRoot,\n abi.encodePacked(blockHeader.computeConsensusHeaderHash()),\n blockInHistoryProof.proof,\n blockInHistoryProof.key,\n rootBlockHeader.height\n )\n ) revert InvalidBlockInHistoryProof();\n\n //verify message in block\n bytes32 messageId = CryptographyLib.hash(\n abi.encodePacked(message.sender, message.recipient, message.nonce, message.amount, message.data)\n );\n if (\n !verifyBinaryTree(\n blockHeader.outputMessagesRoot,\n abi.encodePacked(messageId),\n messageInBlockProof.proof,\n messageInBlockProof.key,\n blockHeader.outputMessagesCount\n )\n ) revert InvalidMessageInBlockProof();\n\n //execute message\n _executeMessage(messageId, message);\n }\n\n /// @notice Gets if the given message ID has been relayed successfully\n /// @param messageId Message ID\n /// @return true if message has been relayed successfully\n function incomingMessageSuccessful(bytes32 messageId) public view virtual returns (bool) {\n return _incomingMessageSuccessful[messageId];\n }\n\n /// @notice Used by message receiving contracts to get the address on Fuel that sent the message\n /// @return sender the address of the sender on Fuel\n function messageSender() external view virtual returns (bytes32) {\n if (_incomingMessageSender == NULL_MESSAGE_SENDER) revert CurrentMessageSenderNotSet();\n return _incomingMessageSender;\n }\n\n ///////////////////////////////////////\n // Outgoing Message Public Functions //\n ///////////////////////////////////////\n\n /// @notice Send a message to a recipient on Fuel\n /// @param recipient The target message receiver address or predicate root\n /// @param data The message data to be sent to the receiver\n function sendMessage(bytes32 recipient, bytes calldata data) external payable virtual whenNotPaused {\n _sendOutgoingMessage(recipient, data);\n }\n\n /// @notice Send only ETH to the given recipient\n /// @param recipient The target message receiver\n function depositETH(bytes32 recipient) external payable virtual whenNotPaused {\n _sendOutgoingMessage(recipient, new bytes(0));\n }\n\n ////////////////////////\n // Internal Functions //\n ////////////////////////\n\n /// @notice Performs all necessary logic to send a message to a target on Fuel\n /// @param recipient The message receiver address or predicate root\n /// @param data The message data to be sent to the receiver\n function _sendOutgoingMessage(bytes32 recipient, bytes memory data) internal virtual {\n bytes32 sender = bytes32(uint256(uint160(msg.sender)));\n unchecked {\n //make sure data size is not too large\n if (data.length >= MAX_MESSAGE_DATA_SIZE) revert MessageDataTooLarge();\n\n //make sure amount fits into the Fuel base asset decimal level\n uint256 precision = 10 ** (ETH_DECIMALS - FUEL_BASE_ASSET_DECIMALS);\n uint256 amount = msg.value / precision;\n if (msg.value > 0) {\n if (amount * PRECISION != msg.value) revert AmountPrecisionIncompatibility();\n if (amount > type(uint64).max) revert AmountTooBig();\n }\n\n //emit message for Fuel clients to pickup (messageID calculated offchain)\n uint256 nonce = _outgoingMessageNonce;\n emit MessageSent(sender, recipient, nonce, uint64(amount), data);\n\n // increment nonce for next message\n _outgoingMessageNonce = nonce + 1;\n }\n }\n\n /// @notice Executes a message in the given header\n /// @param messageId The id of message to execute\n /// @param message The message to execute\n function _executeMessage(bytes32 messageId, Message calldata message) internal virtual nonReentrant {\n if (_incomingMessageSuccessful[messageId]) revert AlreadyRelayed();\n\n //set message sender for receiving contract to reference\n _incomingMessageSender = message.sender;\n\n (bool success, bytes memory result) = address(uint160(uint256(message.recipient))).call{\n value: message.amount * (10 ** (ETH_DECIMALS - FUEL_BASE_ASSET_DECIMALS))\n }(message.data);\n\n if (!success) {\n // Look for revert reason and bubble it up if present\n if (result.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(result)\n revert(add(32, result), returndata_size)\n }\n }\n revert(\"Message relay failed\");\n }\n\n //unset message sender reference\n _incomingMessageSender = NULL_MESSAGE_SENDER;\n\n //keep track of successfully relayed messages\n _incomingMessageSuccessful[messageId] = true;\n\n //emit event for successful message relay\n emit MessageRelayed(messageId, message.sender, message.recipient, message.amount);\n }\n\n /// @notice Executes a message in the given header\n // solhint-disable-next-line no-empty-blocks\n function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {\n //should revert if msg.sender is not authorized to upgrade the contract (currently only admin)\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/fuelchain/FuelMessagePortal/IFuelMessagePortal.sol": { + "content": "// SPDX-License-Identifier: Apache 2.0\npragma solidity 0.8.9;\n\nimport {FuelMessagePortalV3} from \"./v3/FuelMessagePortalV3.sol\";\n\n/// @notice to be used by external tools, like the block producer\n/// @dev marked abstract to track all relevant current and future functions as development evolves\nabstract contract IFuelMessagePortal is FuelMessagePortalV3 {\n event Transaction(uint256 indexed nonce, uint64 max_gas, bytes canonically_serialized_tx);\n\n function sendTransaction(uint64 gas, bytes calldata serializedTx) external payable virtual;\n\n function getLastSeenBlock() external virtual returns (uint256);\n\n function getUsedGas() external virtual returns (uint64);\n}\n" + }, + "contracts/fuelchain/FuelMessagePortal/v2/FuelMessagePortalV2.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport \"../../FuelMessagePortal.sol\";\n\n/// @custom:oz-upgrades-unsafe-allow constructor state-variable-immutable\n/// @custom:deprecation THIS CONTRACT IS DEPRECATED. CHECK FuelMessagePortalV3\ncontract FuelMessagePortalV2 is FuelMessagePortal {\n error GlobalDepositLimit();\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 public immutable depositLimitGlobal;\n\n uint256 public totalDeposited;\n\n constructor(uint256 _depositLimitGlobal) {\n /// @custom:oz-upgrades-unsafe-allow state-variable-assignment\n depositLimitGlobal = _depositLimitGlobal;\n }\n\n ////////////////////////\n // Internal Functions //\n ////////////////////////\n\n /// @notice Performs all necessary logic to send a message to a target on Fuel\n /// @param recipient The message receiver address or predicate root\n /// @param data The message data to be sent to the receiver\n function _sendOutgoingMessage(bytes32 recipient, bytes memory data) internal virtual override {\n bytes32 sender = bytes32(uint256(uint160(msg.sender)));\n unchecked {\n //make sure data size is not too large\n if (data.length >= MAX_MESSAGE_DATA_SIZE) revert MessageDataTooLarge();\n\n // v2: increase global deposited ether\n uint256 globalDepositedAmount = totalDeposited += msg.value;\n if (globalDepositedAmount > depositLimitGlobal) {\n revert GlobalDepositLimit();\n }\n\n //make sure amount fits into the Fuel base asset decimal level\n uint256 amount = msg.value / PRECISION;\n if (msg.value > 0) {\n if (amount * PRECISION != msg.value) revert AmountPrecisionIncompatibility();\n if (amount > type(uint64).max) revert AmountTooBig();\n }\n\n //emit message for Fuel clients to pickup (messageID calculated offchain)\n uint256 nonce = _outgoingMessageNonce;\n emit MessageSent(sender, recipient, nonce, uint64(amount), data);\n\n // increment nonce for next message\n _outgoingMessageNonce = nonce + 1;\n }\n }\n\n /// @notice Executes a message in the given header\n /// @param messageId The id of message to execute\n /// @param message The message to execute\n function _executeMessage(bytes32 messageId, Message calldata message) internal virtual override nonReentrant {\n if (_incomingMessageSuccessful[messageId]) revert AlreadyRelayed();\n\n //set message sender for receiving contract to reference\n _incomingMessageSender = message.sender;\n\n // v2: update accounting if the message carries an amount\n bool success;\n bytes memory result;\n if (message.amount > 0) {\n uint256 withdrawnAmount = message.amount * PRECISION;\n\n // Underflow check enabled since the amount is coded in `message`\n totalDeposited -= withdrawnAmount;\n\n (success, result) = address(uint160(uint256(message.recipient))).call{value: withdrawnAmount}(message.data);\n } else {\n (success, result) = address(uint160(uint256(message.recipient))).call(message.data);\n }\n\n if (!success) {\n // Look for revert reason and bubble it up if present\n if (result.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(result)\n revert(add(32, result), returndata_size)\n }\n }\n revert(\"Message relay failed\");\n }\n\n //unset message sender reference\n _incomingMessageSender = NULL_MESSAGE_SENDER;\n\n //keep track of successfully relayed messages\n _incomingMessageSuccessful[messageId] = true;\n\n //emit event for successful message relay\n emit MessageRelayed(messageId, message.sender, message.recipient, message.amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/fuelchain/FuelMessagePortal/v3/FuelMessagePortalV3.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport \"../v2/FuelMessagePortalV2.sol\";\n\n/// @custom:oz-upgrades-unsafe-allow constructor state-variable-immutable\ncontract FuelMessagePortalV3 is FuelMessagePortalV2 {\n using FuelBlockHeaderLib for FuelBlockHeader;\n using FuelBlockHeaderLiteLib for FuelBlockHeaderLite;\n\n error MessageBlacklisted();\n error WithdrawalsPaused();\n\n bool public withdrawalsPaused;\n mapping(bytes32 => bool) public messageIsBlacklisted;\n\n constructor(uint256 _depositLimitGlobal) FuelMessagePortalV2(_depositLimitGlobal) {}\n\n function pauseWithdrawals() external payable onlyRole(PAUSER_ROLE) {\n withdrawalsPaused = true;\n }\n\n function unpauseWithdrawals() external payable onlyRole(DEFAULT_ADMIN_ROLE) {\n withdrawalsPaused = false;\n }\n\n function addMessageToBlacklist(bytes32 messageId) external payable onlyRole(PAUSER_ROLE) {\n messageIsBlacklisted[messageId] = true;\n }\n\n function removeMessageFromBlacklist(bytes32 messageId) external payable onlyRole(DEFAULT_ADMIN_ROLE) {\n messageIsBlacklisted[messageId] = false;\n }\n\n ///////////////////////////////////////\n // Incoming Message Public Functions //\n ///////////////////////////////////////\n\n /// @notice Relays a message published on Fuel from a given block\n /// @param message The message to relay\n /// @param rootBlockHeader The root block for proving chain history\n /// @param blockHeader The block containing the message\n /// @param blockInHistoryProof Proof that the message block exists in the history of the root block\n /// @param messageInBlockProof Proof that message exists in block\n /// @dev Made payable to reduce gas costs\n function relayMessage(\n Message calldata message,\n FuelBlockHeaderLite calldata rootBlockHeader,\n FuelBlockHeader calldata blockHeader,\n MerkleProof calldata blockInHistoryProof,\n MerkleProof calldata messageInBlockProof\n ) external payable virtual override whenNotPaused {\n if (withdrawalsPaused) {\n revert WithdrawalsPaused();\n }\n\n //verify root block header\n if (!_fuelChainState.finalized(rootBlockHeader.computeConsensusHeaderHash(), rootBlockHeader.height)) {\n revert UnfinalizedBlock();\n }\n\n //verify block in history\n if (\n !verifyBinaryTree(\n rootBlockHeader.prevRoot,\n abi.encodePacked(blockHeader.computeConsensusHeaderHash()),\n blockInHistoryProof.proof,\n blockInHistoryProof.key,\n rootBlockHeader.height\n )\n ) revert InvalidBlockInHistoryProof();\n\n //verify message in block\n bytes32 messageId = CryptographyLib.hash(\n abi.encodePacked(message.sender, message.recipient, message.nonce, message.amount, message.data)\n );\n\n if (messageIsBlacklisted[messageId]) {\n revert MessageBlacklisted();\n }\n\n if (\n !verifyBinaryTree(\n blockHeader.outputMessagesRoot,\n abi.encodePacked(messageId),\n messageInBlockProof.proof,\n messageInBlockProof.key,\n blockHeader.outputMessagesCount\n )\n ) revert InvalidMessageInBlockProof();\n\n //execute message\n _executeMessage(messageId, message);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/fuelchain/types/FuelBlockHeader.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {CryptographyLib} from \"../../lib/Cryptography.sol\";\n\n/// @title Fuel Chain Block Header\n/// @dev The Fuel chain block header structure\nstruct FuelBlockHeader {\n ///////////////\n // Consensus //\n ///////////////\n // Merkle root of all previous consensus header hashes (not including this block)\n bytes32 prevRoot;\n // Height of this block\n uint32 height;\n // Time this block was created, in TAI64 format\n uint64 timestamp;\n /////////////////\n // Application //\n /////////////////\n //Height of the data availability layer up to which (inclusive) input messages are processed\n uint64 daHeight;\n // Number of transactions in this block\n uint64 txCount;\n // Number of output messages in this block\n uint64 outputMessagesCount;\n // Merkle root of transactions in this block\n bytes32 txRoot;\n // Merkle root of output messages in this block\n bytes32 outputMessagesRoot;\n // Version of consensus parameters\n uint64 consensusParametersVersion;\n // Version of state transition bytecode\n uint64 stateTransitionBytecodeVersion;\n}\n\n/// @title Block Header Library\n/// @dev Provides useful functions for dealing with Fuel blocks\nlibrary FuelBlockHeaderLib {\n /////////////\n // Methods //\n /////////////\n\n /// @notice Serialize a block application header.\n /// @param header The block header structure.\n /// @return The serialized block application header.\n function serializeApplicationHeader(FuelBlockHeader memory header) internal pure returns (bytes memory) {\n return\n abi.encodePacked(\n header.daHeight,\n header.txCount,\n header.outputMessagesCount,\n header.txRoot,\n header.outputMessagesRoot,\n header.consensusParametersVersion,\n header.stateTransitionBytecodeVersion\n );\n }\n\n /// @notice Produce the block application header hash.\n /// @param header The block header structure.\n /// @return The block application header hash.\n function computeApplicationHeaderHash(FuelBlockHeader memory header) internal pure returns (bytes32) {\n return CryptographyLib.hash(serializeApplicationHeader(header));\n }\n\n /// @notice Serialize a block consensus header.\n /// @param header The block header structure.\n /// @return The serialized block consensus header.\n function serializeConsensusHeader(FuelBlockHeader memory header) internal pure returns (bytes memory) {\n return abi.encodePacked(header.prevRoot, header.height, header.timestamp, computeApplicationHeaderHash(header));\n }\n\n /// @notice Produce the block consensus header hash.\n /// @param header The block header structure.\n /// @return The block consensus header hash.\n function computeConsensusHeaderHash(FuelBlockHeader memory header) internal pure returns (bytes32) {\n return CryptographyLib.hash(serializeConsensusHeader(header));\n }\n}\n" + }, + "contracts/fuelchain/types/FuelBlockHeaderLite.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {CryptographyLib} from \"../../lib/Cryptography.sol\";\n\n/// @title Lightweight Fuel Chain Block Header\n/// @dev The Fuel chain block header structure with just a hash of the application header\nstruct FuelBlockHeaderLite {\n // Merkle root of all previous consensus header hashes (not including this block)\n bytes32 prevRoot;\n // Height of this block\n uint32 height;\n // Time this block was created, in TAI64 format\n uint64 timestamp;\n // Hash of serialized application header for this block\n bytes32 applicationHash;\n}\n\n/// @title Block Header Library\n/// @dev Provides useful functions for dealing with Fuel blocks\nlibrary FuelBlockHeaderLiteLib {\n /////////////\n // Methods //\n /////////////\n\n /// @notice Serialize a block consensus header.\n /// @param header The block header structure.\n /// @return The serialized block consensus header.\n function serializeConsensusHeader(FuelBlockHeaderLite memory header) internal pure returns (bytes memory) {\n return abi.encodePacked(header.prevRoot, (uint32)(header.height), header.timestamp, header.applicationHash);\n }\n\n /// @notice Produce the block consensus header hash.\n /// @param header The block header structure.\n /// @return The block consensus header hash.\n function computeConsensusHeaderHash(FuelBlockHeaderLite memory header) internal pure returns (bytes32) {\n return CryptographyLib.hash(serializeConsensusHeader(header));\n }\n}\n" + }, + "contracts/lib/CommonPredicates.sol": { + "content": "// SPDX-License-Identifier: Apache 2.0\n\npragma solidity 0.8.9;\n\n/// @notice Common predicates for Fuel inputs\nlibrary CommonPredicates {\n bytes32 public constant CONTRACT_MESSAGE_PREDICATE =\n 0xb12658c759d8bae2cdc523ebd7aa8637912f32b1763d242ad3618448057b79cd;\n}\n" + }, + "contracts/lib/Cryptography.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\n/// @notice This is the Fuel protocol cryptography library.\nlibrary CryptographyLib {\n /////////////\n // Methods //\n /////////////\n\n // secp256k1n / 2\n uint256 private constant MAX_SIGNATURE_S_VALUE = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0;\n\n /// @notice The primary hash method for Fuel.\n /// @param data The bytes input data.\n /// @return The returned hash result.\n function hash(bytes memory data) internal pure returns (bytes32) {\n return sha256(data);\n }\n\n function addressFromSignatureComponents(\n uint8 v,\n bytes32 r,\n bytes32 s,\n bytes32 message\n ) internal pure returns (address) {\n // reject high s values to prevent signature malleability\n // https://eips.ethereum.org/EIPS/eip-2\n require(uint256(s) <= MAX_SIGNATURE_S_VALUE, \"signature-invalid-s\");\n\n address signer = ecrecover(message, v, r, s);\n require(signer != address(0), \"signature-invalid\");\n\n return signer;\n }\n\n /// @notice Get the signing address from a signature and the signed data\n /// @param signature: The compact (64 byte) ECDSA signature\n /// @param message: The message which was signed over\n /// @return : The address of the signer, or address(0) in case of an error\n function addressFromSignature(bytes memory signature, bytes32 message) internal pure returns (address) {\n // ECDSA signatures must be 64 bytes (https://eips.ethereum.org/EIPS/eip-2098)\n require(signature.length == 64, \"signature-invalid-length\");\n\n // Signature is concatenation of r and v-s, both 32 bytes\n // https://github.com/celestiaorg/celestia-specs/blob/ec98170398dfc6394423ee79b00b71038879e211/src/specs/data_structures.md#signature\n bytes32 vs;\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n (r, vs) = abi.decode(signature, (bytes32, bytes32));\n\n // v is first bit of vs as uint8\n // yParity parameter is always either 0 or 1 (canonically the values used have been 27 and 28), so adjust accordingly\n v = 27 + uint8(uint256(vs) & (1 << 255) > 0 ? 1 : 0);\n\n // s is vs with first bit replaced by a 0\n s = bytes32((uint256(vs) << 1) >> 1);\n\n return addressFromSignatureComponents(v, r, s, message);\n }\n}\n" + }, + "contracts/messaging/FuelMessagesEnabled.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport {FuelMessagePortal} from \"../fuelchain/FuelMessagePortal.sol\";\n\n/// @title FuelMessagesEnabled\n/// @notice Helper contract for contracts sending and receiving messages from Fuel\nabstract contract FuelMessagesEnabled {\n ////////////\n // Errors //\n ////////////\n\n error CallerIsNotPortal();\n error InvalidMessageSender();\n\n /////////////\n // Storage //\n /////////////\n\n /// @notice FuelMessagePortal contract used to send and receive messages from Fuel\n FuelMessagePortal internal _fuelMessagePortal;\n\n ////////////////////////\n // Function Modifiers //\n ////////////////////////\n\n /// @notice Enforces that the modified function is only callable by the Fuel message portal\n modifier onlyFromPortal() {\n if (msg.sender != address(_fuelMessagePortal)) revert CallerIsNotPortal();\n _;\n }\n\n /// @notice Enforces that the modified function is only callable by the portal and a specific Fuel account\n /// @param fuelSender The only sender on Fuel which is authenticated to call this function\n modifier onlyFromFuelSender(bytes32 fuelSender) {\n if (msg.sender != address(_fuelMessagePortal)) revert CallerIsNotPortal();\n if (_fuelMessagePortal.messageSender() != fuelSender) revert InvalidMessageSender();\n _;\n }\n\n //////////////////////\n // Public Functions //\n //////////////////////\n\n /// @notice Gets the currently set message portal address\n /// @return fuelMessagePortal Fuel message portal address\n function fuelMessagePortal() public view returns (address) {\n return address(_fuelMessagePortal);\n }\n\n ////////////////////////\n // Internal Functions //\n ////////////////////////\n\n /// @notice Send a message to a recipient on Fuel\n /// @param recipient The message receiver address or predicate root\n /// @param data The message data to be sent to the receiver\n function sendMessage(bytes32 recipient, bytes memory data) internal {\n _fuelMessagePortal.sendMessage(recipient, data);\n }\n\n /// @notice Send a message to a recipient on Fuel\n /// @param recipient The message receiver address or predicate root\n /// @param amount The amount of ETH to send with message\n /// @param data The message data to be sent to the receiver\n function sendMessage(bytes32 recipient, uint256 amount, bytes memory data) internal {\n _fuelMessagePortal.sendMessage{value: amount}(recipient, data);\n }\n\n /// @notice Used by message receiving contracts to get the address on Fuel that sent the message\n function messageSender() internal view returns (bytes32) {\n return _fuelMessagePortal.messageSender();\n }\n}\n" + }, + "contracts/messaging/FuelMessagesEnabledUpgradeable.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {FuelMessagePortal} from \"../fuelchain/FuelMessagePortal.sol\";\nimport {FuelMessagesEnabled} from \"./FuelMessagesEnabled.sol\";\n\n/// @title FuelMessagesEnabledUpgradeable\n/// @notice Helper contract for contracts sending and receiving messages from Fuel\nabstract contract FuelMessagesEnabledUpgradeable is Initializable, FuelMessagesEnabled {\n /////////////////\n // Initializer //\n /////////////////\n\n /// @dev Initializes the contract\n // solhint-disable-next-line func-name-mixedcase\n function __FuelMessagesEnabled_init(FuelMessagePortal fuelMessagePortal) internal onlyInitializing {\n __FuelMessagesEnabled_init_unchained(fuelMessagePortal);\n }\n\n // solhint-disable-next-line func-name-mixedcase\n function __FuelMessagesEnabled_init_unchained(FuelMessagePortal fuelMessagePortal) internal onlyInitializing {\n _fuelMessagePortal = fuelMessagePortal;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/messaging/gateway/FuelBridgeBase/FuelBridgeBase.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nabstract contract FuelBridgeBase {\n /// @notice Finalizes the withdrawal process from the Fuel side gateway contract\n /// @param to Account to send withdrawn tokens to\n /// @param tokenAddress Address of the token being withdrawn from Fuel\n /// @param amount Amount of tokens to withdraw\n /// @param tokenId Discriminator for ERC721 / ERC1155 tokens. For ERC20, it must be 0\n /// @dev Made payable to reduce gas costs\n function finalizeWithdrawal(\n address to,\n address tokenAddress,\n uint256 amount,\n uint256 tokenId\n ) external payable virtual;\n}\n" + }, + "contracts/messaging/gateway/FuelBridgeBase/FuelBridgeBaseV2.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\n/// @custom:deprecation THIS CONTRACT IS DEPRECATED\nabstract contract FuelBridgeBaseV2 {\n error FuelContractIsNotBridge();\n\n event ReceiverRegistered(bytes32 indexed fuelContractId, address indexed tokenAddress);\n\n mapping(bytes32 => mapping(address => bool)) public isBridge;\n\n /// @notice Accepts a message from a fuel entity to acknowledge it can receive tokens\n /// @param tokenAddress The token address that the fuel entity can receive\n /// @dev Made payable to reduce gas costs\n /// @dev funcSig: aec97dc6 => registerAsReceiver(address)\n function registerAsReceiver(address tokenAddress) external payable virtual;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/messaging/gateway/FuelERC20Gateway/FuelERC20Gateway.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {AccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {FuelBridgeBase} from \"../FuelBridgeBase/FuelBridgeBase.sol\";\nimport {FuelMessagePortal, CommonPredicates} from \"../../../fuelchain/FuelMessagePortal.sol\";\nimport {FuelMessagesEnabledUpgradeable} from \"../../FuelMessagesEnabledUpgradeable.sol\";\n\n/// @title FuelERC20Gateway\n/// @notice The L1 side of the general ERC20 gateway with Fuel\n/// @dev This contract can be used as a template for future gateways to Fuel\n/// @custom:deprecation THIS CONTRACT IS DEPRECATED. CHECK FuelERC20GatewayV4\ncontract FuelERC20Gateway is\n Initializable,\n FuelBridgeBase,\n FuelMessagesEnabledUpgradeable,\n PausableUpgradeable,\n AccessControlUpgradeable,\n UUPSUpgradeable\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n ////////////\n // Events //\n ////////////\n\n /// @dev Emitted when tokens are deposited from Ethereum to Fuel\n event Deposit(bytes32 indexed sender, address indexed tokenAddress, bytes32 indexed fuelContractId, uint256 amount);\n\n /// @dev Emitted when tokens are withdrawn from Fuel to Ethereum\n event Withdrawal(\n bytes32 indexed recipient,\n address indexed tokenAddress,\n bytes32 indexed fuelContractId,\n uint256 amount\n );\n\n ///////////////\n // Constants //\n ///////////////\n\n /// @dev The admin related contract roles\n bytes1 public constant DEPOSIT_TO_CONTRACT = bytes1(keccak256(\"DEPOSIT_TO_CONTRACT\"));\n\n /// @dev The admin related contract roles\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n /////////////\n // Storage //\n /////////////\n\n /// @notice Maps ERC20 tokens to Fuel tokens to balance of the ERC20 tokens deposited\n mapping(address => mapping(bytes32 => uint256)) internal _deposits;\n\n /////////////////////////////\n // Constructor/Initializer //\n /////////////////////////////\n\n /// @notice Constructor disables initialization for the implementation contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /// @notice Contract initializer to setup starting values\n /// @param fuelMessagePortal The FuelMessagePortal contract\n function initialize(FuelMessagePortal fuelMessagePortal) public initializer {\n __FuelMessagesEnabled_init(fuelMessagePortal);\n __Pausable_init();\n __AccessControl_init();\n __UUPSUpgradeable_init();\n\n //grant initial roles\n _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _grantRole(PAUSER_ROLE, msg.sender);\n }\n\n /////////////////////\n // Admin Functions //\n /////////////////////\n\n /// @notice Pause ERC20 transfers\n function pause() external onlyRole(PAUSER_ROLE) {\n _pause();\n }\n\n /// @notice Unpause ERC20 transfers\n function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) {\n _unpause();\n }\n\n //////////////////////\n // Public Functions //\n //////////////////////\n\n /// @notice Gets the amount of tokens deposited to a corresponding token on Fuel\n /// @param tokenAddress ERC-20 token address\n /// @param fuelContractId ID of the corresponding token on Fuel\n /// @return amount of tokens deposited\n function tokensDeposited(address tokenAddress, bytes32 fuelContractId) public view virtual returns (uint256) {\n return _deposits[tokenAddress][fuelContractId];\n }\n\n /// @notice Deposits the given tokens to an account on Fuel\n /// @param to Fuel address to deposit tokens to\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param amount Amount of tokens to deposit\n /// @dev Made payable to reduce gas costs\n function deposit(\n bytes32 to,\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 amount\n ) external payable virtual whenNotPaused {\n bytes memory messageData = abi.encodePacked(\n fuelContractId,\n bytes32(uint256(uint160(tokenAddress))), // OFFSET_TOKEN_ADDRESS = 32\n bytes32(0), // OFFSET_TOKEN_ID = 64\n bytes32(uint256(uint160(msg.sender))), //from, OFFSET_FROM = 96\n to, // OFFSET_TO = 128\n amount // OFFSET_AMOUNT = 160\n );\n _deposit(tokenAddress, fuelContractId, amount, messageData);\n }\n\n /// @notice Deposits the given tokens to a contract on Fuel with optional data\n /// @param to Fuel account or contract to deposit tokens to\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param amount Amount of tokens to deposit\n /// @param data Optional data to send with the deposit\n /// @dev Made payable to reduce gas costs\n function depositWithData(\n bytes32 to,\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 amount,\n bytes calldata data\n ) external payable virtual whenNotPaused {\n bytes memory messageData = abi.encodePacked(\n fuelContractId,\n bytes32(uint256(uint160(tokenAddress))), // OFFSET_TOKEN_ADDRESS = 32\n bytes32(0), // OFFSET_TOKEN_ID = 64\n bytes32(uint256(uint160(msg.sender))), //from, OFFSET_FROM = 96\n to, // OFFSET_TO = 128\n amount, // OFFSET_AMOUNT = 160\n DEPOSIT_TO_CONTRACT, // OFFSET_ROLE = 161\n data\n );\n _deposit(tokenAddress, fuelContractId, amount, messageData);\n }\n\n /// @notice Finalizes the withdrawal process from the Fuel side gateway contract\n /// @param to Account to send withdrawn tokens to\n /// @param tokenAddress Address of the token being withdrawn from Fuel\n /// @param amount Amount of tokens to withdraw\n /// @param tokenId Discriminator for ERC721 / ERC1155 tokens. For ERC20, it must be 0\n /// @dev Made payable to reduce gas costs\n function finalizeWithdrawal(\n address to,\n address tokenAddress,\n uint256 amount,\n uint256 tokenId\n ) external payable virtual override whenNotPaused onlyFromPortal {\n require(amount > 0, \"Cannot withdraw zero\");\n require(tokenId == 0, \"Fungible tokens cannot have a tokenId\");\n bytes32 fuelContractId = messageSender();\n\n //reduce deposit balance and transfer tokens (math will underflow if amount is larger than allowed)\n _deposits[tokenAddress][fuelContractId] = _deposits[tokenAddress][fuelContractId] - amount;\n IERC20Upgradeable(tokenAddress).safeTransfer(to, amount);\n\n //emit event for successful token withdraw\n emit Withdrawal(bytes32(uint256(uint160(to))), tokenAddress, fuelContractId, amount);\n }\n\n /// @notice Allows the admin to rescue ETH sent to this contract by accident\n /// @dev Made payable to reduce gas costs\n function rescueETH() external payable virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n (bool success, ) = address(msg.sender).call{value: address(this).balance}(\"\");\n require(success);\n }\n\n ////////////////////////\n // Internal Functions //\n ////////////////////////\n\n /// @notice Deposits the given tokens to an account or contract on Fuel\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param amount Amount of tokens to deposit\n /// @param messageData The data of the message to send for deposit\n function _deposit(\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 amount,\n bytes memory messageData\n ) internal virtual {\n require(amount > 0, \"Cannot deposit zero\");\n\n //transfer tokens to this contract and update deposit balance\n IERC20Upgradeable(tokenAddress).safeTransferFrom(msg.sender, address(this), amount);\n _deposits[tokenAddress][fuelContractId] = _deposits[tokenAddress][fuelContractId] + amount;\n\n //send message to gateway on Fuel to finalize the deposit\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, messageData);\n\n //emit event for successful token deposit\n emit Deposit(bytes32(uint256(uint160(msg.sender))), tokenAddress, fuelContractId, amount);\n }\n\n /// @notice Executes a message in the given header\n // solhint-disable-next-line no-empty-blocks\n function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {\n //should revert if msg.sender is not authorized to upgrade the contract (currently only owner)\n }\n}\n" + }, + "contracts/messaging/gateway/FuelERC20Gateway/FuelERC20GatewayV2.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport \"./FuelERC20Gateway.sol\";\nimport \"../FuelBridgeBase/FuelBridgeBaseV2.sol\";\n\n/// @custom:deprecation THIS CONTRACT IS DEPRECATED. CHECK FuelERC20GatewayV4\ncontract FuelERC20GatewayV2 is FuelERC20Gateway, FuelBridgeBaseV2 {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n function registerAsReceiver(address tokenAddress) external payable virtual override onlyFromPortal {\n bytes32 sender = messageSender();\n\n isBridge[sender][tokenAddress] = true;\n\n emit ReceiverRegistered(sender, tokenAddress);\n }\n\n /// @notice Deposits the given tokens to an account or contract on Fuel\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param amount Amount of tokens to deposit\n /// @param messageData The data of the message to send for deposit\n function _deposit(\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 amount,\n bytes memory messageData\n ) internal virtual override {\n require(amount > 0, \"Cannot deposit zero\");\n if (!isBridge[fuelContractId][tokenAddress]) revert FuelContractIsNotBridge();\n\n //transfer tokens to this contract and update deposit balance\n IERC20Upgradeable(tokenAddress).safeTransferFrom(msg.sender, address(this), amount);\n _deposits[tokenAddress][fuelContractId] = _deposits[tokenAddress][fuelContractId] + amount;\n\n //send message to gateway on Fuel to finalize the deposit\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, messageData);\n\n //emit event for successful token deposit\n emit Deposit(bytes32(uint256(uint160(msg.sender))), tokenAddress, fuelContractId, amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/messaging/gateway/FuelERC20Gateway/FuelERC20GatewayV3.sol": { + "content": "// SPDX-License-Identifier: Apache 2.0\npragma solidity ^0.8.0;\n\nimport \"./FuelERC20GatewayV2.sol\";\n\n/// @custom:deprecation THIS CONTRACT IS DEPRECATED. CHECK FuelERC20GatewayV4\ncontract FuelERC20GatewayV3 is FuelERC20GatewayV2 {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n error GlobalDepositLimit();\n error CannotDepositZero();\n error CannotWithdrawZero();\n error TokenIdNotAllowed();\n\n mapping(address => uint256) public depositLimitGlobal;\n mapping(address => uint256) public depositTotals;\n\n function setGlobalDepositLimit(address token, uint256 limit) external payable virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n depositLimitGlobal[token] = limit;\n }\n\n /// @notice Deposits the given tokens to an account or contract on Fuel\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param amount Amount of tokens to deposit\n /// @param messageData The data of the message to send for deposit\n function _deposit(\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 amount,\n bytes memory messageData\n ) internal virtual override {\n ////////////\n // Checks //\n ////////////\n if (amount == 0) revert CannotDepositZero();\n\n uint256 updatedDepositTotals = depositTotals[tokenAddress] + amount;\n if (updatedDepositTotals > depositLimitGlobal[tokenAddress]) revert GlobalDepositLimit();\n\n if (!isBridge[fuelContractId][tokenAddress]) revert FuelContractIsNotBridge();\n\n /////////////\n // Effects //\n /////////////\n _deposits[tokenAddress][fuelContractId] += amount;\n depositTotals[tokenAddress] = updatedDepositTotals;\n\n /////////////\n // Actions //\n /////////////\n //send message to gateway on Fuel to finalize the deposit\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, messageData);\n\n //transfer tokens to this contract and update deposit balance\n IERC20Upgradeable(tokenAddress).safeTransferFrom(msg.sender, address(this), amount);\n\n //emit event for successful token deposit\n emit Deposit(bytes32(uint256(uint160(msg.sender))), tokenAddress, fuelContractId, amount);\n }\n\n /// @notice Finalizes the withdrawal process from the Fuel side gateway contract\n /// @param to Account to send withdrawn tokens to\n /// @param tokenAddress Address of the token being withdrawn from Fuel\n /// @param amount Amount of tokens to withdraw\n /// @param tokenId Discriminator for ERC721 / ERC1155 tokens. For ERC20, it must be 0\n /// @dev Made payable to reduce gas costs\n function finalizeWithdrawal(\n address to,\n address tokenAddress,\n uint256 amount,\n uint256 tokenId\n ) external payable override whenNotPaused onlyFromPortal {\n ////////////\n // Checks //\n ////////////\n if (amount == 0) revert CannotWithdrawZero();\n if (tokenId > 0) revert TokenIdNotAllowed();\n\n /////////////\n // Effects //\n /////////////\n bytes32 fuelContractId = messageSender();\n\n //reduce deposit balance and transfer tokens (math will underflow if amount is larger than allowed)\n _deposits[tokenAddress][fuelContractId] -= amount;\n depositTotals[tokenAddress] -= amount;\n\n /////////////\n // Actions //\n /////////////\n IERC20Upgradeable(tokenAddress).safeTransfer(to, amount);\n\n //emit event for successful token withdraw\n emit Withdrawal(bytes32(uint256(uint160(to))), tokenAddress, fuelContractId, amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/messaging/gateway/FuelERC20Gateway/FuelERC20GatewayV4.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {AccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {CommonPredicates} from \"../../../lib/CommonPredicates.sol\";\nimport {FuelMessagePortal} from \"../../../fuelchain/FuelMessagePortal.sol\";\nimport {FuelBridgeBase} from \"../FuelBridgeBase/FuelBridgeBase.sol\";\nimport {FuelMessagesEnabledUpgradeable} from \"../../FuelMessagesEnabledUpgradeable.sol\";\n\n/// @title FuelERC20GatewayV4\n/// @notice The L1 side of the general ERC20 gateway with Fuel. Not backwards compatible with previous implementations\ncontract FuelERC20GatewayV4 is\n Initializable,\n FuelBridgeBase,\n FuelMessagesEnabledUpgradeable,\n PausableUpgradeable,\n AccessControlUpgradeable,\n UUPSUpgradeable\n{\n using SafeERC20Upgradeable for IERC20MetadataUpgradeable;\n\n ////////////\n // Types //\n ////////////\n error BridgeFull();\n error GlobalDepositLimit();\n error CannotDepositZero();\n error CannotWithdrawZero();\n error InvalidSender();\n error InvalidAmount();\n\n /// @dev Emitted when tokens are deposited from Ethereum to Fuel\n event Deposit(bytes32 indexed sender, address indexed tokenAddress, uint256 amount);\n\n /// @dev Emitted when tokens are withdrawn from Fuel to Ethereum\n event Withdrawal(bytes32 indexed recipient, address indexed tokenAddress, uint256 amount);\n\n enum MessageType {\n DEPOSIT_TO_ADDRESS,\n DEPOSIT_TO_CONTRACT,\n DEPOSIT_WITH_DATA,\n METADATA\n }\n\n ///////////////\n // Constants //\n ///////////////\n\n /// @dev The admin related contract roles\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n uint256 public constant FUEL_ASSET_DECIMALS = 9;\n uint256 constant NO_DECIMALS = type(uint256).max;\n\n /////////////\n // Storage //\n /////////////\n\n bool public whitelistRequired;\n bytes32 public assetIssuerId;\n\n mapping(address => uint256) internal _deposits;\n mapping(address => uint256) internal _depositLimits;\n mapping(address => uint256) internal _decimalsCache;\n mapping(bytes32 => bool) internal _isBridge;\n\n /// @notice Contract initializer to setup starting values\n /// @param fuelMessagePortal The FuelMessagePortal contract\n function initialize(FuelMessagePortal fuelMessagePortal) public initializer {\n __FuelMessagesEnabled_init(fuelMessagePortal);\n __Pausable_init();\n __AccessControl_init();\n __UUPSUpgradeable_init();\n\n //grant initial roles\n _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _grantRole(PAUSER_ROLE, msg.sender);\n }\n\n /////////////////////\n // Admin Functions //\n /////////////////////\n\n /// @notice Pause ERC20 transfers\n function pause() external onlyRole(PAUSER_ROLE) {\n _pause();\n }\n\n /// @notice Unpause ERC20 transfers\n function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) {\n _unpause();\n }\n\n /// @notice sets the entity on L2 that will mint the tokens\n function setAssetIssuerId(bytes32 id) external payable virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n assetIssuerId = id;\n }\n\n /// @notice if enabled, only deposits for tokens allowed through `setGlobalDepositLimit` will be allowed\n function requireWhitelist(bool value) external onlyRole(DEFAULT_ADMIN_ROLE) {\n whitelistRequired = value;\n }\n\n /// @notice see `requireWhitelist`\n /// @dev param `limit` must be down/up scaled according to _adjustDepositDecimals\n function setGlobalDepositLimit(address token, uint256 limit) external payable virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n _depositLimits[token] = limit;\n }\n\n /// @notice Allows the admin to rescue ETH sent to this contract by accident\n /// @dev Made payable to reduce gas costs\n function rescueETH() external payable virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n (bool success, ) = address(msg.sender).call{value: address(this).balance}(\"\");\n require(success);\n }\n\n //////////////////////\n // Public Functions //\n //////////////////////\n\n /// @notice Gets the amount of tokens deposited to a corresponding token on Fuel\n /// @param tokenAddress ERC-20 token address\n /// @return amount of tokens deposited\n function tokensDeposited(address tokenAddress) public view virtual returns (uint256) {\n return _deposits[tokenAddress];\n }\n\n /// @notice Gets the amount of tokens deposited to a corresponding token on Fuel\n /// @param tokenAddress ERC-20 token address\n /// @return amount of tokens deposited\n function depositLimits(address tokenAddress) public view virtual returns (uint256) {\n return _depositLimits[tokenAddress];\n }\n\n /// @notice Deposits the given tokens to an account on Fuel\n /// @param to Fuel address to deposit tokens to\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param amount Amount of tokens to deposit\n /// @dev Made payable to reduce gas costs\n function deposit(bytes32 to, address tokenAddress, uint256 amount) external payable virtual whenNotPaused {\n uint8 decimals = _getTokenDecimals(tokenAddress);\n uint256 l2MintedAmount = _adjustDepositDecimals(decimals, amount);\n\n bytes memory depositMessage = abi.encodePacked(\n assetIssuerId,\n uint256(MessageType.DEPOSIT_TO_ADDRESS),\n bytes32(uint256(uint160(tokenAddress))),\n uint256(0), // token_id = 0 for all erc20 deposits\n bytes32(uint256(uint160(msg.sender))),\n to,\n l2MintedAmount,\n uint256(decimals)\n );\n _deposit(tokenAddress, amount, l2MintedAmount, depositMessage);\n }\n\n /// @notice Deposits the given tokens to a contract on Fuel with optional data\n /// @param to Fuel account or contract to deposit tokens to\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param amount Amount of tokens to deposit\n /// @param data Optional data to send with the deposit\n /// @dev Made payable to reduce gas costs\n function depositWithData(\n bytes32 to,\n address tokenAddress,\n uint256 amount,\n bytes calldata data\n ) external payable virtual whenNotPaused {\n uint8 decimals = _getTokenDecimals(tokenAddress);\n uint256 l2MintedAmount = _adjustDepositDecimals(decimals, amount);\n\n bytes memory depositMessage = abi.encodePacked(\n assetIssuerId,\n uint256(data.length == 0 ? MessageType.DEPOSIT_TO_CONTRACT : MessageType.DEPOSIT_WITH_DATA),\n bytes32(uint256(uint160(tokenAddress))),\n uint256(0), // token_id = 0 for all erc20 deposits\n bytes32(uint256(uint160(msg.sender))),\n to,\n l2MintedAmount,\n uint256(decimals),\n data\n );\n _deposit(tokenAddress, amount, l2MintedAmount, depositMessage);\n }\n\n function sendMetadata(address tokenAddress) external payable virtual whenNotPaused {\n bytes memory metadataMessage = abi.encodePacked(\n assetIssuerId,\n uint256(MessageType.METADATA),\n abi.encode(\n tokenAddress,\n uint256(0), // token_id = 0 for all erc20 deposits\n IERC20MetadataUpgradeable(tokenAddress).symbol(),\n IERC20MetadataUpgradeable(tokenAddress).name()\n )\n );\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, metadataMessage);\n }\n\n /// @notice Finalizes the withdrawal process from the Fuel side gateway contract\n /// @param to Account to send withdrawn tokens to\n /// @param tokenAddress Address of the token being withdrawn from Fuel\n /// @param l2BurntAmount Amount of tokens to withdraw\n /// @dev Made payable to reduce gas costs\n function finalizeWithdrawal(\n address to,\n address tokenAddress,\n uint256 l2BurntAmount,\n uint256 /*tokenId*/\n ) external payable virtual override whenNotPaused onlyFromPortal {\n if (l2BurntAmount == 0) {\n revert CannotWithdrawZero();\n }\n\n if (messageSender() != assetIssuerId) {\n revert InvalidSender();\n }\n\n uint8 decimals = _getTokenDecimals(tokenAddress);\n uint256 amount = _adjustWithdrawalDecimals(decimals, l2BurntAmount);\n\n //reduce deposit balance and transfer tokens (math will underflow if amount is larger than allowed)\n _deposits[tokenAddress] = _deposits[tokenAddress] - l2BurntAmount;\n IERC20MetadataUpgradeable(tokenAddress).safeTransfer(to, amount);\n\n //emit event for successful token withdraw\n emit Withdrawal(bytes32(uint256(uint160(to))), tokenAddress, amount);\n }\n\n /// @notice Deposits the given tokens to an account or contract on Fuel\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param amount tokens that have been deposited\n /// @param l2MintedAmount tokens that will be minted on L2\n /// @param messageData The data of the message to send for deposit\n function _deposit(\n address tokenAddress,\n uint256 amount,\n uint256 l2MintedAmount,\n bytes memory messageData\n ) internal virtual {\n ////////////\n // Checks //\n ////////////\n if (l2MintedAmount == 0) revert CannotDepositZero();\n if (l2MintedAmount > uint256(type(uint64).max)) revert InvalidAmount();\n\n /////////////\n // Effects //\n /////////////\n uint256 updatedDeposits = _deposits[tokenAddress] + l2MintedAmount;\n if (updatedDeposits > type(uint64).max) revert BridgeFull();\n\n if (whitelistRequired && updatedDeposits > _depositLimits[tokenAddress]) {\n revert GlobalDepositLimit();\n }\n\n _deposits[tokenAddress] = updatedDeposits;\n\n /////////////\n // Actions //\n /////////////\n //send message to gateway on Fuel to finalize the deposit\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, messageData);\n\n //transfer tokens to this contract and update deposit balance\n IERC20MetadataUpgradeable(tokenAddress).safeTransferFrom(msg.sender, address(this), amount);\n\n //emit event for successful token deposit\n emit Deposit(bytes32(uint256(uint160(msg.sender))), tokenAddress, amount);\n }\n\n function _getTokenDecimals(address tokenAddress) internal virtual returns (uint8) {\n uint256 decimals = _decimalsCache[tokenAddress];\n\n if (decimals == 0) {\n try IERC20MetadataUpgradeable(tokenAddress).decimals() returns (uint8 returnedDecimals) {\n _decimalsCache[tokenAddress] = returnedDecimals == 0 ? NO_DECIMALS : returnedDecimals;\n return returnedDecimals;\n } catch {\n _decimalsCache[tokenAddress] = NO_DECIMALS;\n return 0;\n }\n }\n\n if (decimals == NO_DECIMALS) return 0;\n return uint8(decimals);\n }\n\n function _adjustDepositDecimals(uint8 tokenDecimals, uint256 amount) internal pure virtual returns (uint256) {\n if (tokenDecimals > FUEL_ASSET_DECIMALS) {\n unchecked {\n uint256 precision = 10 ** (tokenDecimals - FUEL_ASSET_DECIMALS);\n if (amount % precision != 0) {\n revert InvalidAmount();\n }\n return _divByNonZero(amount, precision);\n }\n }\n return amount;\n }\n\n function _adjustWithdrawalDecimals(uint8 tokenDecimals, uint256 amount) internal pure virtual returns (uint256) {\n if (tokenDecimals > FUEL_ASSET_DECIMALS) {\n uint256 precision = 10 ** (tokenDecimals - FUEL_ASSET_DECIMALS);\n return amount * precision;\n }\n\n return amount;\n }\n\n /// @dev gas efficient division. Must be used with care, `_div` must be non zero\n function _divByNonZero(uint256 _num, uint256 _div) internal pure returns (uint256 result) {\n assembly {\n result := div(_num, _div)\n }\n }\n\n /// @notice Executes a message in the given header\n // solhint-disable-next-line no-empty-blocks\n function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {\n //should revert if msg.sender is not authorized to upgrade the contract (currently only owner)\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/messaging/gateway/FuelERC721Gateway/FuelERC721Gateway.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {AccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {IERC721Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\";\nimport {FuelBridgeBase} from \"../FuelBridgeBase/FuelBridgeBase.sol\";\nimport {FuelMessagePortal, CommonPredicates} from \"../../../fuelchain/FuelMessagePortal.sol\";\nimport {FuelMessagesEnabledUpgradeable} from \"../../FuelMessagesEnabledUpgradeable.sol\";\n\n/// @title FuelERC721Gateway\n/// @notice The L1 side of the general ERC721 gateway with Fuel\n/// @dev This contract can be used as a template for future gateways to Fuel\n\n/// @custom:deprecation THIS CONTRACT IS DEPRECATED. CHECK FuelERC20GatewayV4\ncontract FuelERC721Gateway is\n Initializable,\n FuelBridgeBase,\n FuelMessagesEnabledUpgradeable,\n PausableUpgradeable,\n AccessControlUpgradeable,\n UUPSUpgradeable\n{\n ////////////\n // Events //\n ////////////\n\n /// @dev Emitted when tokens are deposited from Ethereum to Fuel\n event Deposit(\n bytes32 indexed sender,\n address indexed tokenAddress,\n bytes32 indexed fuelContractId,\n uint256 tokenId\n );\n\n /// @dev Emitted when tokens are withdrawn from Fuel to Ethereum\n event Withdrawal(\n bytes32 indexed recipient,\n address indexed tokenAddress,\n bytes32 indexed fuelContractId,\n uint256 tokenId\n );\n\n ///////////////\n // Constants //\n ///////////////\n\n /// @dev The admin related contract roles\n bytes1 public constant DEPOSIT_TO_CONTRACT = bytes1(keccak256(\"DEPOSIT_TO_CONTRACT\"));\n\n /// @dev The admin related contract roles\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n /////////////\n // Storage //\n /////////////\n\n /// @notice Maps ERC721 tokens to its fuel bridge counterpart\n mapping(address => mapping(uint256 => bytes32)) internal _deposits;\n\n /////////////////////////////\n // Constructor/Initializer //\n /////////////////////////////\n\n /// @notice Constructor disables initialization for the implementation contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /// @notice Contract initializer to setup starting values\n /// @param fuelMessagePortal The FuelMessagePortal contract\n function initialize(FuelMessagePortal fuelMessagePortal) public initializer {\n __FuelMessagesEnabled_init(fuelMessagePortal);\n __Pausable_init();\n __AccessControl_init();\n __UUPSUpgradeable_init();\n\n //grant initial roles\n _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _grantRole(PAUSER_ROLE, msg.sender);\n }\n\n /////////////////////\n // Admin Functions //\n /////////////////////\n\n /// @notice Pause ERC721 transfers\n function pause() external onlyRole(PAUSER_ROLE) {\n _pause();\n }\n\n /// @notice Unpause ERC721 transfers\n function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) {\n _unpause();\n }\n\n //////////////////////\n // Public Functions //\n //////////////////////\n\n /// @notice Gets the FuelContractId of an ERC-721 token\n /// @param tokenAddress ERC-721 token address\n /// @param tokenId tokenId\n /// @return fuelContractId ID of the Fuel contract\n function tokensDeposited(address tokenAddress, uint256 tokenId) public view returns (bytes32) {\n return _deposits[tokenAddress][tokenId];\n }\n\n /// @notice Deposits the given tokens to an account on Fuel\n /// @param to Fuel address to deposit tokens to\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param tokenId tokenId to deposit\n /// @dev Made payable to reduce gas costs\n function deposit(\n bytes32 to,\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 tokenId\n ) external payable whenNotPaused {\n bytes memory messageData = abi.encodePacked(\n fuelContractId,\n bytes32(uint256(uint160(tokenAddress))), // OFFSET_TOKEN_ADDRESS = 32\n tokenId,\n bytes32(uint256(uint160(msg.sender))), //from, OFFSET_FROM = 96\n to, // OFFSET_TO = 128\n uint256(1) // OFFSET_AMOUNT = 160\n );\n _deposit(tokenAddress, fuelContractId, tokenId, messageData);\n }\n\n /// @notice Deposits the given tokens to a contract on Fuel with optional data\n /// @param to Fuel account or contract to deposit tokens to\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param tokenId tokenId to deposit\n /// @param data Optional data to send with the deposit\n /// @dev Made payable to reduce gas costs\n function depositWithData(\n bytes32 to,\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 tokenId,\n bytes calldata data\n ) external payable whenNotPaused {\n bytes memory messageData = abi.encodePacked(\n fuelContractId,\n bytes32(uint256(uint160(tokenAddress))), // OFFSET_TOKEN_ADDRESS = 32\n tokenId, // OFFSET_TOKEN_ID = 64\n bytes32(uint256(uint160(msg.sender))), //from, OFFSET_FROM = 96\n to, // OFFSET_TO = 128\n uint256(1), // OFFSET_AMOUNT = 160\n DEPOSIT_TO_CONTRACT, // OFFSET_ROLE = 161\n data\n );\n _deposit(tokenAddress, fuelContractId, tokenId, messageData);\n }\n\n /// @notice Finalizes the withdrawal process from the Fuel side gateway contract\n /// @param to Account to send withdrawn tokens to\n /// @param tokenAddress Address of the token being withdrawn from Fuel\n /// @param tokenId Discriminator for ERC721 / ERC1155 tokens\n /// @dev Made payable to reduce gas costs.\n /// @dev Could remove the amount param to further reduce cost, but that implies changes in the Fuel contract\n function finalizeWithdrawal(\n address to,\n address tokenAddress,\n uint256 /*amount*/,\n uint256 tokenId\n ) external payable override whenNotPaused onlyFromPortal {\n bytes32 fuelContractId = messageSender();\n require(_deposits[tokenAddress][tokenId] == fuelContractId, \"Fuel bridge does not own this token\");\n\n delete _deposits[tokenAddress][tokenId];\n\n IERC721Upgradeable(tokenAddress).transferFrom(address(this), to, tokenId);\n //emit event for successful token withdraw\n emit Withdrawal(bytes32(uint256(uint160(to))), tokenAddress, fuelContractId, 1);\n }\n\n ////////////////////////\n // Internal Functions //\n ////////////////////////\n\n /// @notice Deposits the given tokens to an account or contract on Fuel\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param tokenId tokenId to deposit\n /// @param messageData The data of the message to send for deposit\n function _deposit(\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 tokenId,\n bytes memory messageData\n ) internal virtual {\n // TODO: this check might be unnecessary. If the token is conformant to ERC721\n // it should not be possible to deposit the same token again\n require(_deposits[tokenAddress][tokenId] == 0, \"tokenId is already owned by another fuel bridge\");\n _deposits[tokenAddress][tokenId] = fuelContractId;\n\n //send message to gateway on Fuel to finalize the deposit\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, messageData);\n\n IERC721Upgradeable(tokenAddress).transferFrom(msg.sender, address(this), tokenId);\n //emit event for successful token deposit\n emit Deposit(bytes32(uint256(uint160(msg.sender))), tokenAddress, fuelContractId, tokenId);\n }\n\n /// @notice Executes a message in the given header\n // solhint-disable-next-line no-empty-blocks\n function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {\n //should revert if msg.sender is not authorized to upgrade the contract (currently only owner)\n }\n}\n" + }, + "contracts/messaging/gateway/FuelERC721Gateway/FuelERC721GatewayV2.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport \"./FuelERC721Gateway.sol\";\nimport \"../FuelBridgeBase/FuelBridgeBaseV2.sol\";\n\n/// @custom:deprecation THIS CONTRACT IS DEPRECATED. CHECK FuelERC20GatewayV4\ncontract FuelERC721GatewayV2 is FuelERC721Gateway, FuelBridgeBaseV2 {\n function registerAsReceiver(address tokenAddress) external payable virtual override onlyFromPortal {\n bytes32 sender = messageSender();\n\n isBridge[sender][tokenAddress] = true;\n\n emit ReceiverRegistered(sender, tokenAddress);\n }\n\n /// @notice Deposits the given tokens to an account or contract on Fuel\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param tokenId tokenId to deposit\n /// @param messageData The data of the message to send for deposit\n function _deposit(\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 tokenId,\n bytes memory messageData\n ) internal virtual override {\n // TODO: this check might be unnecessary. If the token is conformant to ERC721\n // it should not be possible to deposit the same token again\n require(_deposits[tokenAddress][tokenId] == 0, \"tokenId is already owned by another fuel bridge\");\n if (!isBridge[fuelContractId][tokenAddress]) revert FuelContractIsNotBridge();\n\n _deposits[tokenAddress][tokenId] = fuelContractId;\n\n //send message to gateway on Fuel to finalize the deposit\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, messageData);\n\n IERC721Upgradeable(tokenAddress).transferFrom(msg.sender, address(this), tokenId);\n //emit event for successful token deposit\n emit Deposit(bytes32(uint256(uint160(msg.sender))), tokenAddress, fuelContractId, tokenId);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/test/CustomToken.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/// @notice This token is for testing purposes.\ncontract CustomToken is ERC20 {\n address public _owner;\n uint8 customDecimals;\n\n /// @notice Constructor.\n constructor(uint8 _decimals) ERC20(\"Token\", \"TKN\") {\n _owner = msg.sender;\n customDecimals = _decimals;\n }\n\n /// @notice This is a simple mint function.\n /// @param owner The owner of the token.\n /// @param amount The amount of the token to mint to the owner.\n /// @dev Allows anyone to mint the token.\n function mint(address owner, uint256 amount) external {\n _mint(owner, amount);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return customDecimals;\n }\n}\n" + }, + "contracts/test/FuelBlockHeaderTester.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport {FuelBlockHeader, FuelBlockHeaderLib} from \"../fuelchain/types/FuelBlockHeader.sol\";\nimport {FuelBlockHeaderLite, FuelBlockHeaderLiteLib} from \"../fuelchain/types/FuelBlockHeaderLite.sol\";\nimport {CryptographyLib} from \"../lib/Cryptography.sol\";\n\ncontract FuelBlockHeaderTester {\n using FuelBlockHeaderLib for FuelBlockHeader;\n using FuelBlockHeaderLiteLib for FuelBlockHeaderLite;\n\n /// @notice Serialize a block application header.\n /// @param header The block header structure.\n /// @return The serialized block application header.\n function _serializeApplicationHeader(FuelBlockHeader memory header) public pure returns (bytes memory) {\n return header.serializeApplicationHeader();\n }\n\n /// @notice Produce the block application header hash.\n /// @param header The block header structure.\n /// @return The block application header hash.\n function _computeApplicationHeaderHash(FuelBlockHeader memory header) public pure returns (bytes32) {\n return CryptographyLib.hash(header.serializeApplicationHeader());\n }\n\n /// @notice Serialize a block consensus header.\n /// @param header The block header structure.\n /// @return The serialized block consensus header.\n function _serializeConsensusHeader(FuelBlockHeader memory header) public pure returns (bytes memory) {\n return header.serializeConsensusHeader();\n }\n\n /// @notice Produce the block consensus header hash.\n /// @param header The block header structure.\n /// @return The block consensus header hash.\n function _computeConsensusHeaderHash(FuelBlockHeader memory header) public pure returns (bytes32) {\n return CryptographyLib.hash(header.serializeConsensusHeader());\n }\n}\n" + }, + "contracts/test/MessageTester.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {FuelMessagesEnabled} from \"../messaging/FuelMessagesEnabled.sol\";\nimport {FuelMessagePortal} from \"../fuelchain/FuelMessagePortal.sol\";\n\n/// @notice This contract allows for testing message receiving.\ncontract MessageTester is FuelMessagesEnabled {\n bytes32 internal constant TRUSTED_SENDER = 0xf40001353a6b162f0ff9d59cae46ed49355aa4c424e3f79f6d84352f85715576;\n\n /// @notice Storage to hold and test incoming data\n uint256 public data1;\n uint256 public data2;\n\n /// @notice Constructor.\n /// @param fuelMessagePortal The FuelMessagePortal contract\n constructor(FuelMessagePortal fuelMessagePortal) {\n _fuelMessagePortal = fuelMessagePortal;\n }\n\n /// @notice Message receiving function.\n /// @param d1 Test param 1\n /// @param d2 Test param 2\n function receiveMessage(uint256 d1, uint256 d2) external payable onlyFromFuelSender(TRUSTED_SENDER) {\n data1 = d1;\n data2 = d2;\n }\n\n /// @notice Send a message to a recipient on Fuel\n /// @param recipient The target message receiver\n /// @param data The message data to be sent to the receiver\n function attemptSendMessage(bytes32 recipient, bytes memory data) external {\n sendMessage(recipient, data);\n }\n\n /// @notice Send a message to a recipient on Fuel\n /// @param recipient The target message receiver\n /// @param amount The amount of ETH to send with message\n /// @param data The message data to be sent to the receiver\n function attemptSendMessageWithAmount(bytes32 recipient, uint256 amount, bytes memory data) external {\n sendMessage(recipient, amount, data);\n }\n\n /// @notice Gets the address of the trusted message sender.\n /// @return Address of the trusted message sender\n function getTrustedSender() external pure returns (bytes32) {\n return TRUSTED_SENDER;\n }\n\n /// @notice Default receive function\n // solhint-disable-next-line no-empty-blocks\n receive() external payable {\n // handle incoming eth\n }\n}\n" + }, + "contracts/test/MockCryptography.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {CryptographyLib} from \"../lib/Cryptography.sol\";\n\ncontract MockCryptography {\n function hash(bytes memory data) public pure returns (bytes32) {\n return CryptographyLib.hash(data);\n }\n\n function addressFromSignatureComponents(\n uint8 v,\n bytes32 r,\n bytes32 s,\n bytes32 message\n ) external pure returns (address) {\n return CryptographyLib.addressFromSignatureComponents(v, r, s, message);\n }\n\n function addressFromSignature(bytes memory signature, bytes32 message) external pure returns (address) {\n return CryptographyLib.addressFromSignature(signature, message);\n }\n}\n" + }, + "contracts/test/MockFuelMessagePortal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.9;\n\ncontract MockFuelMessagePortal {\n event SendMessageCalled(bytes32 indexed target, bytes data);\n\n bytes32 private _messageSender;\n\n function setMessageSender(bytes32 value) external {\n _messageSender = value;\n }\n\n function messageSender() external view returns (bytes32) {\n return _messageSender;\n }\n\n function sendMessage(bytes32 target, bytes calldata data) external {\n emit SendMessageCalled(target, data);\n }\n}\n" + }, + "contracts/test/NFT.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >=0.8.9;\n\nimport \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\n\ncontract NFT is ERC721 {\n constructor() ERC721(\"TestNFT\", \"TestNFT\") {}\n\n function mint(address to, uint tokenID) external {\n _mint(to, tokenID);\n }\n}\n" + }, + "contracts/test/NoDecimalsToken.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/// @notice This token is for testing purposes.\ncontract NoDecimalsToken is ERC20 {\n address public _owner;\n uint8 customDecimals;\n\n /// @notice Constructor.\n constructor(uint8 _decimals) ERC20(\"Token\", \"TKN\") {\n _owner = msg.sender;\n customDecimals = _decimals;\n }\n\n /// @notice This is a simple mint function.\n /// @param owner The owner of the token.\n /// @param amount The amount of the token to mint to the owner.\n /// @dev Allows anyone to mint the token.\n function mint(address owner, uint256 amount) external {\n _mint(owner, amount);\n }\n\n function decimals() public view virtual override returns (uint8) {\n revert(\"\");\n }\n}\n" + }, + "contracts/test/Token.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/// @notice This token is for testing purposes.\ncontract Token is ERC20 {\n address public _owner;\n\n /// @notice Constructor.\n constructor() ERC20(\"Token\", \"TKN\") {\n _owner = msg.sender;\n }\n\n /// @notice This is a simple mint function.\n /// @param owner The owner of the token.\n /// @param amount The amount of the token to mint to the owner.\n /// @dev Allows anyone to mint the token.\n function mint(address owner, uint256 amount) external {\n _mint(owner, amount);\n }\n}\n" + }, + "contracts/test/UpgradeableTester.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {FuelMessagesEnabledUpgradeable} from \"../messaging/FuelMessagesEnabledUpgradeable.sol\";\nimport {FuelMessagePortal} from \"../fuelchain/FuelMessagePortal.sol\";\n\n/// @notice This contract allows for testing message receiving.\ncontract UpgradeableTester is FuelMessagesEnabledUpgradeable {\n /// @notice Test the init function for FuelMessagesEnabledUpgradeable\n function testFuelMessagesEnabledInit(FuelMessagePortal fuelMessagePortal) external {\n __FuelMessagesEnabled_init(fuelMessagePortal);\n }\n\n /// @notice Test the init unchained function for FuelMessagesEnabledUpgradeable\n function testFuelMessagesEnabledInitUnchained(FuelMessagePortal fuelMessagePortal) external {\n __FuelMessagesEnabled_init_unchained(fuelMessagePortal);\n }\n}\n" + }, + "contracts/vendor/SafeCall.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\n/**\n * @title SafeCall\n * @notice Perform low level safe calls. See https://github.com/nomad-xyz/ExcessivelySafeCall\n */\nlibrary SafeCall {\n /**\n * @notice Perform a low level call without copying any returndata\n *\n * @param _target Address to call\n * @param _value Amount of value to pass to the call\n * @param _calldata Calldata to pass to the call\n */\n function call(address _target, uint256 _value, bytes memory _calldata) internal returns (bool) {\n bool _success;\n uint256 _gas = gasleft();\n assembly {\n _success := call(\n _gas,\n _target,\n _value,\n add(_calldata, 0x20), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "storageLayout", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file From bf5dd9e90220c9389a20d7b23e42d292435fffa3 Mon Sep 17 00:00:00 2001 From: DefiCake Date: Fri, 3 May 2024 12:14:11 +0200 Subject: [PATCH 04/28] chore: replace current devnet deployment with testnet deployment --- .../deploy/devnet/001.chain_state.ts | 10 +- .../devnet/002.fuel_message_portal_v3.ts | 10 +- .../deploy/devnet/003.erc20_gateway_v2.ts | 40 - .../003.erc20_gateway_v4.ts | 0 .../devnet/005.register_block_committer.ts | 6 +- .../deploy/testnet/001.chain_state.ts | 39 - .../testnet/002.fuel_message_portal_v3.ts | 48 - .../deploy/testnet/004.token.ts | 22 - .../testnet/005.register_block_committer.ts | 28 - .../deployments/devnet/.migrations.json | 11 +- .../deployments/devnet/FuelChainState.json | 530 +++++++++- .../devnet/FuelERC20GatewayV2.json | 6 - .../FuelERC20GatewayV4.json | 0 .../deployments/devnet/FuelMessagePortal.json | 928 +++++++++++++++++- .../deployments/devnet/Token.json | 40 +- .../31fce82f72204deb1c3e677ecb77fe87.json | 0 .../8d5c154a685aa57faf682293f07bfe18.json | 240 ----- .../deployments/testnet/.chainId | 1 - .../deployments/testnet/.migrations.json | 7 - .../deployments/testnet/FuelChainState.json | 528 ---------- .../testnet/FuelMessagePortal.json | 926 ----------------- .../deployments/testnet/Token.json | 475 --------- 22 files changed, 1495 insertions(+), 2400 deletions(-) delete mode 100644 packages/solidity-contracts/deploy/devnet/003.erc20_gateway_v2.ts rename packages/solidity-contracts/deploy/{testnet => devnet}/003.erc20_gateway_v4.ts (100%) delete mode 100644 packages/solidity-contracts/deploy/testnet/001.chain_state.ts delete mode 100644 packages/solidity-contracts/deploy/testnet/002.fuel_message_portal_v3.ts delete mode 100644 packages/solidity-contracts/deploy/testnet/004.token.ts delete mode 100644 packages/solidity-contracts/deploy/testnet/005.register_block_committer.ts delete mode 100644 packages/solidity-contracts/deployments/devnet/FuelERC20GatewayV2.json rename packages/solidity-contracts/deployments/{testnet => devnet}/FuelERC20GatewayV4.json (100%) rename packages/solidity-contracts/deployments/{testnet => devnet}/solcInputs/31fce82f72204deb1c3e677ecb77fe87.json (100%) delete mode 100644 packages/solidity-contracts/deployments/devnet/solcInputs/8d5c154a685aa57faf682293f07bfe18.json delete mode 100644 packages/solidity-contracts/deployments/testnet/.chainId delete mode 100644 packages/solidity-contracts/deployments/testnet/.migrations.json delete mode 100644 packages/solidity-contracts/deployments/testnet/FuelChainState.json delete mode 100644 packages/solidity-contracts/deployments/testnet/FuelMessagePortal.json delete mode 100644 packages/solidity-contracts/deployments/testnet/Token.json diff --git a/packages/solidity-contracts/deploy/devnet/001.chain_state.ts b/packages/solidity-contracts/deploy/devnet/001.chain_state.ts index 97aa46d8..65c1e9b7 100644 --- a/packages/solidity-contracts/deploy/devnet/001.chain_state.ts +++ b/packages/solidity-contracts/deploy/devnet/001.chain_state.ts @@ -7,7 +7,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { ethers, upgrades: { deployProxy, erc1967 }, - deployments: { save }, + deployments: { save, execute }, } = hre; const [deployer] = await ethers.getSigners(); @@ -21,10 +21,16 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { console.log('Deployed FuelChainState at', address); await save('FuelChainState', { address, - abi: [], + abi: [...FuelChainState.abi], implementation, }); + await execute( + 'FuelChainState', + { log: true, from: deployer.address }, + 'pause' + ); + return true; }; diff --git a/packages/solidity-contracts/deploy/devnet/002.fuel_message_portal_v3.ts b/packages/solidity-contracts/deploy/devnet/002.fuel_message_portal_v3.ts index 0e1fb987..5ca0d404 100644 --- a/packages/solidity-contracts/deploy/devnet/002.fuel_message_portal_v3.ts +++ b/packages/solidity-contracts/deploy/devnet/002.fuel_message_portal_v3.ts @@ -8,7 +8,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { ethers, upgrades: { deployProxy, erc1967 }, - deployments: { get, save }, + deployments: { get, save, execute }, } = hre; const [deployer] = await ethers.getSigners(); @@ -30,10 +30,16 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { console.log('Deployed FuelMessagePortal at', address); await save('FuelMessagePortal', { address, - abi: [], + abi: [...FuelMessagePortal.abi], implementation, }); + await execute( + 'FuelMessagePortal', + { log: true, from: deployer.address }, + 'pause' + ); + return true; }; diff --git a/packages/solidity-contracts/deploy/devnet/003.erc20_gateway_v2.ts b/packages/solidity-contracts/deploy/devnet/003.erc20_gateway_v2.ts deleted file mode 100644 index c0307da2..00000000 --- a/packages/solidity-contracts/deploy/devnet/003.erc20_gateway_v2.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { HardhatRuntimeEnvironment } from 'hardhat/types'; -import type { DeployFunction } from 'hardhat-deploy/dist/types'; - -import { FuelERC20GatewayV2__factory as FuelERC20GatewayV2 } from '../../typechain'; - -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { - ethers, - upgrades: { deployProxy, erc1967 }, - deployments: { get, save }, - } = hre; - const [deployer] = await ethers.getSigners(); - - const fuelMessagePortal = await get('FuelMessagePortal'); - - const contract = await deployProxy( - new FuelERC20GatewayV2(deployer), - [fuelMessagePortal.address], - { - initializer: 'initialize', - } - ); - await contract.waitForDeployment(); - - const address = await contract.getAddress(); - const implementation = await erc1967.getImplementationAddress(address); - - console.log('Deployed FuelERC20GatewayV2 at', address); - await save('FuelERC20GatewayV2', { - address, - abi: [], - implementation, - }); - - return true; -}; - -func.tags = ['erc20', 'erc20_gateway', 'FuelERC20GatewayV2']; -func.id = 'fuel_erc20_gateway_v2'; -export default func; diff --git a/packages/solidity-contracts/deploy/testnet/003.erc20_gateway_v4.ts b/packages/solidity-contracts/deploy/devnet/003.erc20_gateway_v4.ts similarity index 100% rename from packages/solidity-contracts/deploy/testnet/003.erc20_gateway_v4.ts rename to packages/solidity-contracts/deploy/devnet/003.erc20_gateway_v4.ts diff --git a/packages/solidity-contracts/deploy/devnet/005.register_block_committer.ts b/packages/solidity-contracts/deploy/devnet/005.register_block_committer.ts index c9d0a64e..0ca34c29 100644 --- a/packages/solidity-contracts/deploy/devnet/005.register_block_committer.ts +++ b/packages/solidity-contracts/deploy/devnet/005.register_block_committer.ts @@ -3,7 +3,7 @@ import type { DeployFunction } from 'hardhat-deploy/dist/types'; import { FuelChainState__factory } from '../../typechain'; -const COMMITTER_ADDRESS = '0xd12663Fc8Dad968946EF7c715742B5f3814b618a'; +const COMMITTER_ADDRESS = '0x2100240626d914AC448525B721D9C5b48b64F674'; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { ethers, deployments } = hre; @@ -23,6 +23,6 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { return true; }; -func.tags = ['portal', 'message_portal', 'FuelMessagePortal']; -func.id = 'fuel_message_portal'; +func.tags = ['register_committer']; +func.id = 'register_committer'; export default func; diff --git a/packages/solidity-contracts/deploy/testnet/001.chain_state.ts b/packages/solidity-contracts/deploy/testnet/001.chain_state.ts deleted file mode 100644 index 65c1e9b7..00000000 --- a/packages/solidity-contracts/deploy/testnet/001.chain_state.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { HardhatRuntimeEnvironment } from 'hardhat/types'; -import type { DeployFunction } from 'hardhat-deploy/dist/types'; - -import { FuelChainState__factory as FuelChainState } from '../../typechain'; - -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { - ethers, - upgrades: { deployProxy, erc1967 }, - deployments: { save, execute }, - } = hre; - const [deployer] = await ethers.getSigners(); - - const contract = await deployProxy(new FuelChainState(deployer), [], { - initializer: 'initialize', - }); - await contract.waitForDeployment(); - const address = await contract.getAddress(); - const implementation = await erc1967.getImplementationAddress(address); - - console.log('Deployed FuelChainState at', address); - await save('FuelChainState', { - address, - abi: [...FuelChainState.abi], - implementation, - }); - - await execute( - 'FuelChainState', - { log: true, from: deployer.address }, - 'pause' - ); - - return true; -}; - -func.tags = ['state', 'chain-state', 'chain_state', 'FuelChainState']; -func.id = 'chain_state'; -export default func; diff --git a/packages/solidity-contracts/deploy/testnet/002.fuel_message_portal_v3.ts b/packages/solidity-contracts/deploy/testnet/002.fuel_message_portal_v3.ts deleted file mode 100644 index 5ca0d404..00000000 --- a/packages/solidity-contracts/deploy/testnet/002.fuel_message_portal_v3.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { MaxUint256 } from 'ethers'; -import type { HardhatRuntimeEnvironment } from 'hardhat/types'; -import type { DeployFunction } from 'hardhat-deploy/dist/types'; - -import { FuelMessagePortalV3__factory as FuelMessagePortal } from '../../typechain'; - -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { - ethers, - upgrades: { deployProxy, erc1967 }, - deployments: { get, save, execute }, - } = hre; - const [deployer] = await ethers.getSigners(); - - const { address: fuelChainState } = await get('FuelChainState'); - - const contract = await deployProxy( - new FuelMessagePortal(deployer), - [fuelChainState], - { - initializer: 'initialize', - constructorArgs: [MaxUint256], - } - ); - await contract.waitForDeployment(); - - const address = await contract.getAddress(); - const implementation = await erc1967.getImplementationAddress(address); - - console.log('Deployed FuelMessagePortal at', address); - await save('FuelMessagePortal', { - address, - abi: [...FuelMessagePortal.abi], - implementation, - }); - - await execute( - 'FuelMessagePortal', - { log: true, from: deployer.address }, - 'pause' - ); - - return true; -}; - -func.tags = ['portal', 'message_portal', 'FuelMessagePortal']; -func.id = 'fuel_message_portal'; -export default func; diff --git a/packages/solidity-contracts/deploy/testnet/004.token.ts b/packages/solidity-contracts/deploy/testnet/004.token.ts deleted file mode 100644 index 2812266a..00000000 --- a/packages/solidity-contracts/deploy/testnet/004.token.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { HardhatRuntimeEnvironment } from 'hardhat/types'; -import type { DeployFunction } from 'hardhat-deploy/dist/types'; - -/** - * @description Deployed for testing purposes - */ -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { - ethers, - deployments: { deploy }, - } = hre; - - const [deployer] = await ethers.getSigners(); - - await deploy('Token', { from: deployer.address, log: true }); - - return true; -}; - -func.tags = ['token']; -func.id = 'token'; -export default func; diff --git a/packages/solidity-contracts/deploy/testnet/005.register_block_committer.ts b/packages/solidity-contracts/deploy/testnet/005.register_block_committer.ts deleted file mode 100644 index 638727be..00000000 --- a/packages/solidity-contracts/deploy/testnet/005.register_block_committer.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { HardhatRuntimeEnvironment } from 'hardhat/types'; -import type { DeployFunction } from 'hardhat-deploy/dist/types'; - -import { FuelChainState__factory } from '../../typechain'; - -const COMMITTER_ADDRESS = '0x6B956CcB32582E0e88136ff895BA77Dc52a68620'; - -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { ethers, deployments } = hre; - const [deployer] = await ethers.getSigners(); - - const { address } = await deployments.get('FuelChainState'); - - const fuelChainState = FuelChainState__factory.connect(address, deployer); - const COMMITTER_ROLE = await fuelChainState.COMMITTER_ROLE(); - - await fuelChainState - .grantRole(COMMITTER_ROLE, COMMITTER_ADDRESS) - .then((tx) => tx.wait()); - - console.log('Granted role COMMITTER_ROLE to', COMMITTER_ADDRESS); - - return true; -}; - -func.tags = ['register_committer']; -func.id = 'register_committer'; -export default func; diff --git a/packages/solidity-contracts/deployments/devnet/.migrations.json b/packages/solidity-contracts/deployments/devnet/.migrations.json index 7638926f..30a2d580 100644 --- a/packages/solidity-contracts/deployments/devnet/.migrations.json +++ b/packages/solidity-contracts/deployments/devnet/.migrations.json @@ -1,6 +1,7 @@ { - "chain_state": 1712146933, - "fuel_message_portal": 1712147077, - "fuel_erc20_gateway_v2": 1712147101, - "token": 1712147115 -} + "chain_state": 1714255660, + "fuel_message_portal": 1714255695, + "fuel_erc20_gateway_v4": 1714255717, + "token": 1714255743, + "register_committer": 1714731217 +} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/devnet/FuelChainState.json b/packages/solidity-contracts/deployments/devnet/FuelChainState.json index 490acafd..6bd96bcf 100644 --- a/packages/solidity-contracts/deployments/devnet/FuelChainState.json +++ b/packages/solidity-contracts/deployments/devnet/FuelChainState.json @@ -1,6 +1,528 @@ { - "address": "0x0880932521f0E3a90d56bC96fD49c0c98CFCf4A7", - "abi": [], + "address": "0x8097500F4168240f4334589170d99fE8797b6fF8", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "UnknownBlock", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "commitHeight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "name": "CommitSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKS_PER_COMMIT_INTERVAL", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COMMITTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NUM_COMMIT_SLOTS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAUSER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TIME_TO_FINALIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "commitHeight", + "type": "uint256" + } + ], + "name": "blockHashAtCommit", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "commitHeight", + "type": "uint256" + } + ], + "name": "commit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "blockHeight", + "type": "uint256" + } + ], + "name": "finalized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], "numDeployments": 1, - "implementation": "0x1eF82F91979B8bdbaF700801E66A8fA260e7CA01" -} + "implementation": "0xba98eDC9AC0B6191180562bF68CE001B1D71C11D" +} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/devnet/FuelERC20GatewayV2.json b/packages/solidity-contracts/deployments/devnet/FuelERC20GatewayV2.json deleted file mode 100644 index 90a12b28..00000000 --- a/packages/solidity-contracts/deployments/devnet/FuelERC20GatewayV2.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "address": "0x83114982BDe057a8907F8a081225C7d301898aDd", - "abi": [], - "numDeployments": 1, - "implementation": "0x04dAEee4C4253f861eAe84503d4a518b3475b696" -} diff --git a/packages/solidity-contracts/deployments/testnet/FuelERC20GatewayV4.json b/packages/solidity-contracts/deployments/devnet/FuelERC20GatewayV4.json similarity index 100% rename from packages/solidity-contracts/deployments/testnet/FuelERC20GatewayV4.json rename to packages/solidity-contracts/deployments/devnet/FuelERC20GatewayV4.json diff --git a/packages/solidity-contracts/deployments/devnet/FuelMessagePortal.json b/packages/solidity-contracts/deployments/devnet/FuelMessagePortal.json index d2b9720d..afe6218a 100644 --- a/packages/solidity-contracts/deployments/devnet/FuelMessagePortal.json +++ b/packages/solidity-contracts/deployments/devnet/FuelMessagePortal.json @@ -1,6 +1,926 @@ { - "address": "0x01eb5b6122E1f65eaF4566093C2431aa0c0eaCd5", - "abi": [], + "address": "0x768f9459E3339A1F7d59CcF24C80Eb4A711a01FB", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_depositLimitGlobal", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyRelayed", + "type": "error" + }, + { + "inputs": [], + "name": "AmountPrecisionIncompatibility", + "type": "error" + }, + { + "inputs": [], + "name": "AmountTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "CurrentMessageSenderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "GlobalDepositLimit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBlockInHistoryProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidMessageInBlockProof", + "type": "error" + }, + { + "inputs": [], + "name": "MessageBlacklisted", + "type": "error" + }, + { + "inputs": [], + "name": "MessageDataTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "UnfinalizedBlock", + "type": "error" + }, + { + "inputs": [], + "name": "WithdrawalsPaused", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "messageId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "sender", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "amount", + "type": "uint64" + } + ], + "name": "MessageRelayed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sender", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "amount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "MessageSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_DECIMALS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FUEL_BASE_ASSET_DECIMALS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_MESSAGE_DATA_SIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAUSER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PRECISION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "messageId", + "type": "bytes32" + } + ], + "name": "addMessageToBlacklist", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + } + ], + "name": "depositETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "depositLimitGlobal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fuelBaseAssetDecimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "fuelChainStateContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNextOutgoingMessageNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "messageId", + "type": "bytes32" + } + ], + "name": "incomingMessageSuccessful", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract FuelChainState", + "name": "fuelChainState", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "messageIsBlacklisted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "messageSender", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pauseWithdrawals", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "sender", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "amount", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Message", + "name": "message", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "prevRoot", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "height", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "applicationHash", + "type": "bytes32" + } + ], + "internalType": "struct FuelBlockHeaderLite", + "name": "rootBlockHeader", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "prevRoot", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "height", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "daHeight", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "txCount", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "outputMessagesCount", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "txRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "outputMessagesRoot", + "type": "bytes32" + } + ], + "internalType": "struct FuelBlockHeader", + "name": "blockHeader", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "key", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct MerkleProof", + "name": "blockInHistoryProof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "key", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct MerkleProof", + "name": "messageInBlockProof", + "type": "tuple" + } + ], + "name": "relayMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "messageId", + "type": "bytes32" + } + ], + "name": "removeMessageFromBlacklist", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDeposited", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpauseWithdrawals", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawalsPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], "numDeployments": 1, - "implementation": "0x800567f454c125A9Dd54D53c3a5A0277a601bf9a" -} + "implementation": "0xC9C453fA30cd0c6A2f09Af5e1C32F839Ff7a3DD0" +} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/devnet/Token.json b/packages/solidity-contracts/deployments/devnet/Token.json index e216b91d..d4dea8d9 100644 --- a/packages/solidity-contracts/deployments/devnet/Token.json +++ b/packages/solidity-contracts/deployments/devnet/Token.json @@ -1,5 +1,5 @@ { - "address": "0x9A741B492A67393879eEe525FD2E58A41e403C3c", + "address": "0x25E869bc5FC45e2786B4B1bEace61287e071C60e", "abi": [ { "inputs": [], @@ -308,28 +308,28 @@ "type": "function" } ], - "transactionHash": "0x67051acf961999474989b9969c726db5338d6e444133bfef7cd4bad5f5b96b8d", + "transactionHash": "0x310a12e685caa9ef3b4186ab13e9ad9745b5335c8d076b4cba6012fb53cef8c0", "receipt": { "to": null, "from": "0xC0cBA65C478C90D779419799687f6DaF8F9F01b1", - "contractAddress": "0x9A741B492A67393879eEe525FD2E58A41e403C3c", - "transactionIndex": 112, + "contractAddress": "0x25E869bc5FC45e2786B4B1bEace61287e071C60e", + "transactionIndex": 59, "gasUsed": "817074", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x308f72cfbb6bf2f990fbeb69a1cea8c95aef95f97fa5c17e5e1c92f8bb36644e", - "transactionHash": "0x67051acf961999474989b9969c726db5338d6e444133bfef7cd4bad5f5b96b8d", + "blockHash": "0x6be8cfd73c319afc4815911196414227f0a84a7beaa59930fb52ad7d9fc6c452", + "transactionHash": "0x310a12e685caa9ef3b4186ab13e9ad9745b5335c8d076b4cba6012fb53cef8c0", "logs": [], - "blockNumber": 5620507, - "cumulativeGasUsed": "11963386", + "blockNumber": 5791370, + "cumulativeGasUsed": "7119154", "status": 1, "byzantium": true }, "args": [], "numDeployments": 1, - "solcInputHash": "8d5c154a685aa57faf682293f07bfe18", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"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.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless this function is overridden; NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"mint(address,uint256)\":{\"details\":\"Allows anyone to mint the token.\",\"params\":{\"amount\":\"The amount of the token to mint to the owner.\",\"owner\":\"The owner of the token.\"}},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"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`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Constructor.\"},\"mint(address,uint256)\":{\"notice\":\"This is a simple mint function.\"}},\"notice\":\"This token is for testing purposes.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/Token.sol\":\"Token\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0x4ffc0547c02ad22925310c585c0f166f8759e2648a09e9b489100c42f15dd98d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/test/Token.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.9;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n/// @notice This token is for testing purposes.\\ncontract Token is ERC20 {\\n address public _owner;\\n\\n /// @notice Constructor.\\n constructor() ERC20(\\\"Token\\\", \\\"TKN\\\") {\\n _owner = msg.sender;\\n }\\n\\n /// @notice This is a simple mint function.\\n /// @param owner The owner of the token.\\n /// @param amount The amount of the token to mint to the owner.\\n /// @dev Allows anyone to mint the token.\\n function mint(address owner, uint256 amount) external {\\n _mint(owner, amount);\\n }\\n}\\n\",\"keccak256\":\"0xbf1a9c1cb145ebd98b1f6159fb8d617c284044ca5ab8f07678a209c411083797\",\"license\":\"UNLICENSED\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b50604051806040016040528060058152602001642a37b5b2b760d91b815250604051806040016040528060038152602001622a25a760e91b81525081600390805190602001906200006492919062000095565b5080516200007a90600490602084019062000095565b5050600580546001600160a01b031916331790555062000178565b828054620000a3906200013b565b90600052602060002090601f016020900481019282620000c7576000855562000112565b82601f10620000e257805160ff191683800117855562000112565b8280016001018555821562000112579182015b8281111562000112578251825591602001919060010190620000f5565b506200012092915062000124565b5090565b5b8082111562000120576000815560010162000125565b600181811c908216806200015057607f821691505b602082108114156200017257634e487b7160e01b600052602260045260246000fd5b50919050565b610c9780620001886000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c806340c10f191161008c578063a457c2d711610066578063a457c2d7146101bf578063a9059cbb146101d2578063b2bdfa7b146101e5578063dd62ed3e1461022a57600080fd5b806340c10f191461016c57806370a082311461018157806395d89b41146101b757600080fd5b806323b872dd116100bd57806323b872dd14610137578063313ce5671461014a578063395093511461015957600080fd5b806306fdde03146100e4578063095ea7b31461010257806318160ddd14610125575b600080fd5b6100ec610270565b6040516100f99190610a77565b60405180910390f35b610115610110366004610b13565b610302565b60405190151581526020016100f9565b6002545b6040519081526020016100f9565b610115610145366004610b3d565b61031a565b604051601281526020016100f9565b610115610167366004610b13565b61033e565b61017f61017a366004610b13565b61038a565b005b61012961018f366004610b79565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100ec610398565b6101156101cd366004610b13565b6103a7565b6101156101e0366004610b13565b61047d565b6005546102059073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f9565b610129610238366004610b9b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60606003805461027f90610bce565b80601f01602080910402602001604051908101604052809291908181526020018280546102ab90610bce565b80156102f85780601f106102cd576101008083540402835291602001916102f8565b820191906000526020600020905b8154815290600101906020018083116102db57829003601f168201915b5050505050905090565b60003361031081858561048b565b5060019392505050565b60003361032885828561063e565b610333858585610715565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906103109082908690610385908790610c22565b61048b565b6103948282610984565b5050565b60606004805461027f90610bce565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610333828686840361048b565b600033610310818585610715565b73ffffffffffffffffffffffffffffffffffffffff831661052d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff82166105d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461070f5781811015610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610467565b61070f848484840361048b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166107b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff821661085b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361070f565b73ffffffffffffffffffffffffffffffffffffffff8216610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610467565b8060026000828254610a139190610c22565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b81811015610aa457858101830151858201604001528201610a88565b81811115610ab6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b0e57600080fd5b919050565b60008060408385031215610b2657600080fd5b610b2f83610aea565b946020939093013593505050565b600080600060608486031215610b5257600080fd5b610b5b84610aea565b9250610b6960208501610aea565b9150604084013590509250925092565b600060208284031215610b8b57600080fd5b610b9482610aea565b9392505050565b60008060408385031215610bae57600080fd5b610bb783610aea565b9150610bc560208401610aea565b90509250929050565b600181811c90821680610be257607f821691505b60208210811415610c1c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008219821115610c5c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea2646970667358221220835193b41985393c389419292c1256a20caf1cc7f72c136c9ef6173a3c157ecd64736f6c63430008090033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100df5760003560e01c806340c10f191161008c578063a457c2d711610066578063a457c2d7146101bf578063a9059cbb146101d2578063b2bdfa7b146101e5578063dd62ed3e1461022a57600080fd5b806340c10f191461016c57806370a082311461018157806395d89b41146101b757600080fd5b806323b872dd116100bd57806323b872dd14610137578063313ce5671461014a578063395093511461015957600080fd5b806306fdde03146100e4578063095ea7b31461010257806318160ddd14610125575b600080fd5b6100ec610270565b6040516100f99190610a77565b60405180910390f35b610115610110366004610b13565b610302565b60405190151581526020016100f9565b6002545b6040519081526020016100f9565b610115610145366004610b3d565b61031a565b604051601281526020016100f9565b610115610167366004610b13565b61033e565b61017f61017a366004610b13565b61038a565b005b61012961018f366004610b79565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100ec610398565b6101156101cd366004610b13565b6103a7565b6101156101e0366004610b13565b61047d565b6005546102059073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f9565b610129610238366004610b9b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60606003805461027f90610bce565b80601f01602080910402602001604051908101604052809291908181526020018280546102ab90610bce565b80156102f85780601f106102cd576101008083540402835291602001916102f8565b820191906000526020600020905b8154815290600101906020018083116102db57829003601f168201915b5050505050905090565b60003361031081858561048b565b5060019392505050565b60003361032885828561063e565b610333858585610715565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906103109082908690610385908790610c22565b61048b565b6103948282610984565b5050565b60606004805461027f90610bce565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610333828686840361048b565b600033610310818585610715565b73ffffffffffffffffffffffffffffffffffffffff831661052d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff82166105d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461070f5781811015610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610467565b61070f848484840361048b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166107b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff821661085b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361070f565b73ffffffffffffffffffffffffffffffffffffffff8216610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610467565b8060026000828254610a139190610c22565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b81811015610aa457858101830151858201604001528201610a88565b81811115610ab6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b0e57600080fd5b919050565b60008060408385031215610b2657600080fd5b610b2f83610aea565b946020939093013593505050565b600080600060608486031215610b5257600080fd5b610b5b84610aea565b9250610b6960208501610aea565b9150604084013590509250925092565b600060208284031215610b8b57600080fd5b610b9482610aea565b9392505050565b60008060408385031215610bae57600080fd5b610bb783610aea565b9150610bc560208401610aea565b90509250929050565b600181811c90821680610be257607f821691505b60208210811415610c1c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008219821115610c5c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea2646970667358221220835193b41985393c389419292c1256a20caf1cc7f72c136c9ef6173a3c157ecd64736f6c63430008090033", + "solcInputHash": "31fce82f72204deb1c3e677ecb77fe87", + "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"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.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"mint(address,uint256)\":{\"details\":\"Allows anyone to mint the token.\",\"params\":{\"amount\":\"The amount of the token to mint to the owner.\",\"owner\":\"The owner of the token.\"}},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"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`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Constructor.\"},\"mint(address,uint256)\":{\"notice\":\"This is a simple mint function.\"}},\"notice\":\"This token is for testing purposes.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/Token.sol\":\"Token\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xa92e4fa126feb6907daa0513ddd816b2eb91f30a808de54f63c17d0e162c3439\",\"license\":\"MIT\"},\"contracts/test/Token.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.9;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n/// @notice This token is for testing purposes.\\ncontract Token is ERC20 {\\n address public _owner;\\n\\n /// @notice Constructor.\\n constructor() ERC20(\\\"Token\\\", \\\"TKN\\\") {\\n _owner = msg.sender;\\n }\\n\\n /// @notice This is a simple mint function.\\n /// @param owner The owner of the token.\\n /// @param amount The amount of the token to mint to the owner.\\n /// @dev Allows anyone to mint the token.\\n function mint(address owner, uint256 amount) external {\\n _mint(owner, amount);\\n }\\n}\\n\",\"keccak256\":\"0xbf1a9c1cb145ebd98b1f6159fb8d617c284044ca5ab8f07678a209c411083797\",\"license\":\"UNLICENSED\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b50604051806040016040528060058152602001642a37b5b2b760d91b815250604051806040016040528060038152602001622a25a760e91b81525081600390805190602001906200006492919062000095565b5080516200007a90600490602084019062000095565b5050600580546001600160a01b031916331790555062000178565b828054620000a3906200013b565b90600052602060002090601f016020900481019282620000c7576000855562000112565b82601f10620000e257805160ff191683800117855562000112565b8280016001018555821562000112579182015b8281111562000112578251825591602001919060010190620000f5565b506200012092915062000124565b5090565b5b8082111562000120576000815560010162000125565b600181811c908216806200015057607f821691505b602082108114156200017257634e487b7160e01b600052602260045260246000fd5b50919050565b610c9780620001886000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c806340c10f191161008c578063a457c2d711610066578063a457c2d7146101bf578063a9059cbb146101d2578063b2bdfa7b146101e5578063dd62ed3e1461022a57600080fd5b806340c10f191461016c57806370a082311461018157806395d89b41146101b757600080fd5b806323b872dd116100bd57806323b872dd14610137578063313ce5671461014a578063395093511461015957600080fd5b806306fdde03146100e4578063095ea7b31461010257806318160ddd14610125575b600080fd5b6100ec610270565b6040516100f99190610a77565b60405180910390f35b610115610110366004610b13565b610302565b60405190151581526020016100f9565b6002545b6040519081526020016100f9565b610115610145366004610b3d565b61031a565b604051601281526020016100f9565b610115610167366004610b13565b61033e565b61017f61017a366004610b13565b61038a565b005b61012961018f366004610b79565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100ec610398565b6101156101cd366004610b13565b6103a7565b6101156101e0366004610b13565b61047d565b6005546102059073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f9565b610129610238366004610b9b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60606003805461027f90610bce565b80601f01602080910402602001604051908101604052809291908181526020018280546102ab90610bce565b80156102f85780601f106102cd576101008083540402835291602001916102f8565b820191906000526020600020905b8154815290600101906020018083116102db57829003601f168201915b5050505050905090565b60003361031081858561048b565b5060019392505050565b60003361032885828561063e565b610333858585610715565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906103109082908690610385908790610c22565b61048b565b6103948282610984565b5050565b60606004805461027f90610bce565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610333828686840361048b565b600033610310818585610715565b73ffffffffffffffffffffffffffffffffffffffff831661052d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff82166105d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461070f5781811015610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610467565b61070f848484840361048b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166107b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff821661085b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361070f565b73ffffffffffffffffffffffffffffffffffffffff8216610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610467565b8060026000828254610a139190610c22565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b81811015610aa457858101830151858201604001528201610a88565b81811115610ab6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b0e57600080fd5b919050565b60008060408385031215610b2657600080fd5b610b2f83610aea565b946020939093013593505050565b600080600060608486031215610b5257600080fd5b610b5b84610aea565b9250610b6960208501610aea565b9150604084013590509250925092565b600060208284031215610b8b57600080fd5b610b9482610aea565b9392505050565b60008060408385031215610bae57600080fd5b610bb783610aea565b9150610bc560208401610aea565b90509250929050565b600181811c90821680610be257607f821691505b60208210811415610c1c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008219821115610c5c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea26469706673582212208229be857565d410e6d53feda1bd4d1a3faa25a0f5741d49827aa48b07a9084e64736f6c63430008090033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100df5760003560e01c806340c10f191161008c578063a457c2d711610066578063a457c2d7146101bf578063a9059cbb146101d2578063b2bdfa7b146101e5578063dd62ed3e1461022a57600080fd5b806340c10f191461016c57806370a082311461018157806395d89b41146101b757600080fd5b806323b872dd116100bd57806323b872dd14610137578063313ce5671461014a578063395093511461015957600080fd5b806306fdde03146100e4578063095ea7b31461010257806318160ddd14610125575b600080fd5b6100ec610270565b6040516100f99190610a77565b60405180910390f35b610115610110366004610b13565b610302565b60405190151581526020016100f9565b6002545b6040519081526020016100f9565b610115610145366004610b3d565b61031a565b604051601281526020016100f9565b610115610167366004610b13565b61033e565b61017f61017a366004610b13565b61038a565b005b61012961018f366004610b79565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100ec610398565b6101156101cd366004610b13565b6103a7565b6101156101e0366004610b13565b61047d565b6005546102059073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f9565b610129610238366004610b9b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60606003805461027f90610bce565b80601f01602080910402602001604051908101604052809291908181526020018280546102ab90610bce565b80156102f85780601f106102cd576101008083540402835291602001916102f8565b820191906000526020600020905b8154815290600101906020018083116102db57829003601f168201915b5050505050905090565b60003361031081858561048b565b5060019392505050565b60003361032885828561063e565b610333858585610715565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906103109082908690610385908790610c22565b61048b565b6103948282610984565b5050565b60606004805461027f90610bce565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610333828686840361048b565b600033610310818585610715565b73ffffffffffffffffffffffffffffffffffffffff831661052d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff82166105d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461070f5781811015610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610467565b61070f848484840361048b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166107b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff821661085b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361070f565b73ffffffffffffffffffffffffffffffffffffffff8216610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610467565b8060026000828254610a139190610c22565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b81811015610aa457858101830151858201604001528201610a88565b81811115610ab6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b0e57600080fd5b919050565b60008060408385031215610b2657600080fd5b610b2f83610aea565b946020939093013593505050565b600080600060608486031215610b5257600080fd5b610b5b84610aea565b9250610b6960208501610aea565b9150604084013590509250925092565b600060208284031215610b8b57600080fd5b610b9482610aea565b9392505050565b60008060408385031215610bae57600080fd5b610bb783610aea565b9150610bc560208401610aea565b90509250929050565b600181811c90821680610be257607f821691505b60208210811415610c1c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008219821115610c5c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea26469706673582212208229be857565d410e6d53feda1bd4d1a3faa25a0f5741d49827aa48b07a9084e64736f6c63430008090033", "devdoc": { "kind": "dev", "methods": { @@ -343,7 +343,7 @@ "details": "See {IERC20-balanceOf}." }, "decimals()": { - "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless this function is overridden; NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." }, "decreaseAllowance(address,uint256)": { "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." @@ -392,7 +392,7 @@ "storageLayout": { "storage": [ { - "astId": 5644, + "astId": 5990, "contract": "contracts/test/Token.sol:Token", "label": "_balances", "offset": 0, @@ -400,7 +400,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5650, + "astId": 5996, "contract": "contracts/test/Token.sol:Token", "label": "_allowances", "offset": 0, @@ -408,7 +408,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 5652, + "astId": 5998, "contract": "contracts/test/Token.sol:Token", "label": "_totalSupply", "offset": 0, @@ -416,7 +416,7 @@ "type": "t_uint256" }, { - "astId": 5654, + "astId": 6000, "contract": "contracts/test/Token.sol:Token", "label": "_name", "offset": 0, @@ -424,7 +424,7 @@ "type": "t_string_storage" }, { - "astId": 5656, + "astId": 6002, "contract": "contracts/test/Token.sol:Token", "label": "_symbol", "offset": 0, @@ -432,7 +432,7 @@ "type": "t_string_storage" }, { - "astId": 13038, + "astId": 13868, "contract": "contracts/test/Token.sol:Token", "label": "_owner", "offset": 0, @@ -472,4 +472,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/solcInputs/31fce82f72204deb1c3e677ecb77fe87.json b/packages/solidity-contracts/deployments/devnet/solcInputs/31fce82f72204deb1c3e677ecb77fe87.json similarity index 100% rename from packages/solidity-contracts/deployments/testnet/solcInputs/31fce82f72204deb1c3e677ecb77fe87.json rename to packages/solidity-contracts/deployments/devnet/solcInputs/31fce82f72204deb1c3e677ecb77fe87.json diff --git a/packages/solidity-contracts/deployments/devnet/solcInputs/8d5c154a685aa57faf682293f07bfe18.json b/packages/solidity-contracts/deployments/devnet/solcInputs/8d5c154a685aa57faf682293f07bfe18.json deleted file mode 100644 index 7c67003f..00000000 --- a/packages/solidity-contracts/deployments/devnet/solcInputs/8d5c154a685aa57faf682293f07bfe18.json +++ /dev/null @@ -1,240 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "@fuel-contracts/merkle-sol/contracts/tree/binary/BinaryMerkleProof.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\n/// @notice Merkle Tree Node structure.\nstruct BinaryMerkleProof {\n bytes32[] proof;\n uint256 key;\n uint256 numLeaves;\n}\n" - }, - "@fuel-contracts/merkle-sol/contracts/tree/binary/BinaryMerkleTree.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\nimport {Node} from \"./Node.sol\";\nimport {nodeDigest, leafDigest, hashNode} from \"./TreeHasher.sol\";\nimport {hashLeaf} from \"./TreeHasher.sol\";\nimport {MerkleBranch} from \"./Branch.sol\";\nimport {BinaryMerkleProof} from \"./BinaryMerkleProof.sol\";\nimport {Constants} from \"../Constants.sol\";\nimport {pathLengthFromKey, getStartingBit} from \"../Utils.sol\";\nimport {getBitAtFromMSB} from \"../Utils.sol\";\nimport {verifyBinaryTree, verifyBinaryTreeDigest} from \"./BinaryMerkleTreeUtils.sol\";\nimport {computeBinaryTreeRoot} from \"./BinaryMerkleTreeUtils.sol\";\nimport {getPtrToNode, getNodeAtPtr} from \"./BinaryMerkleTreeUtils.sol\";\nimport {addBranch, sideNodesForRoot} from \"./BinaryMerkleTreeUtils.sol\";\n\n/// @title Binary Merkle Tree.\n/// @notice spec can be found at https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/cryptographicprimitives.md#binary-merkle-tree.\nlibrary BinaryMerkleTree {\n /// @notice Verify if element (key, data) exists in Merkle tree, given data, proof, and root.\n /// @param root: The root of the tree in which verify the given leaf\n /// @param data: The data of the leaf to verify\n /// @param key: The key of the leaf to verify.\n /// @param proof: Binary Merkle Proof for the leaf.\n /// @param numLeaves: The number of leaves in the tree\n /// @return : Whether the proof is valid\n /// @dev numLeaves is necessary to determine height of sub-tree containing the data to prove\n function verify(\n bytes32 root,\n bytes memory data,\n bytes32[] memory proof,\n uint256 key,\n uint256 numLeaves\n ) public pure returns (bool) {\n return verifyBinaryTree(root, data, proof, key, numLeaves);\n }\n\n /// @notice Verify if element (key, digest) exists in Merkle tree, given digest, proof, and root.\n /// @param root: The root of the tree in which verify the given leaf\n /// @param digest: The digest of the data of the leaf to verify\n /// @param key: The key of the leaf to verify.\n /// @param proof: Binary Merkle Proof for the leaf.\n /// @param numLeaves: The number of leaves in the tree\n /// @return : Whether the proof is valid\n /// @dev numLeaves is necessary to determine height of sub-tree containing the data to prove\n function verifyDigest(\n bytes32 root,\n bytes32 digest,\n bytes32[] memory proof,\n uint256 key,\n uint256 numLeaves\n ) public pure returns (bool) {\n return verifyBinaryTreeDigest(root, digest, proof, key, numLeaves);\n }\n\n /// @notice Computes Merkle tree root from leaves.\n /// @param data: list of leaves' data in ascending for leaves order.\n /// @return : The root of the tree\n function computeRoot(bytes[] memory data) public pure returns (bytes32) {\n return computeBinaryTreeRoot(data);\n }\n\n /// @notice Appends a new element by calculating new root, returns new root and if successful, pure function.\n /// @param numLeaves, number of leaves in the tree currently.\n /// @param data, The data of the leaf to append.\n /// @param proof, Binary Merkle Proof to use for the leaf.\n /// @return : The root of the new tree\n /// @return : Whether the proof is valid\n function append(\n uint256 numLeaves,\n bytes memory data,\n bytes32[] memory proof\n ) public pure returns (bytes32, bool) {\n bytes32 digest = leafDigest(data);\n\n // Since appended leaf is last leaf in tree by definition, its path consists only of set bits\n // (because all side nodes will be on its left)\n // Therefore, the number of steps in the proof should equal number of bits set in the key\n // E.g. If appending the 7th leaf, key = 0b110 => proofLength = 2.\n\n uint256 proofLength = 0;\n while (numLeaves > 0) {\n proofLength += numLeaves & 1;\n numLeaves = numLeaves >> 1;\n }\n\n if (proof.length != proofLength) {\n return (Constants.NULL, false);\n }\n\n // If proof length is correctly 0, tree is empty, and we are appending the first leaf\n if (proofLength == 0) {\n digest = leafDigest(data);\n }\n // Otherwise tree non-empty so we calculate nodes up to root\n else {\n for (uint256 i = 0; i < proofLength; ++i) {\n digest = nodeDigest(proof[i], digest);\n }\n }\n\n return (digest, true);\n }\n\n /// @notice Update a given leaf\n /// @param key: The key of the leaf to be added\n /// @param value: The data to update the leaf with\n /// @param sideNodes: The sideNodes from the leaf to the root\n /// @param numLeaves: The total number of leaves in the tree\n /// @return currentPtr : The pointer to the root of the tree\n function updateWithSideNodes(\n bytes32 key,\n bytes memory value,\n bytes32[] memory sideNodes,\n uint256 numLeaves\n ) public pure returns (bytes32 currentPtr) {\n Node memory currentNode = hashLeaf(value);\n currentPtr = getPtrToNode(currentNode);\n\n // If numleaves <= 1, then the root is just the leaf hash (or ZERO)\n if (numLeaves > 1) {\n uint256 startingBit = getStartingBit(numLeaves);\n uint256 pathLength = pathLengthFromKey(uint256(key), numLeaves);\n\n for (uint256 i = 0; i < pathLength; i += 1) {\n if (getBitAtFromMSB(key, startingBit + pathLength - 1 - i) == 1) {\n currentNode = hashNode(\n sideNodes[i],\n currentPtr,\n getNodeAtPtr(sideNodes[i]).digest,\n currentNode.digest\n );\n } else {\n currentNode = hashNode(\n currentPtr,\n sideNodes[i],\n currentNode.digest,\n getNodeAtPtr(sideNodes[i]).digest\n );\n }\n\n currentPtr = getPtrToNode(currentNode);\n }\n }\n }\n\n /// @notice Add an array of branches and update one of them\n /// @param branches: The array of branches to add\n /// @param root: The root of the tree\n /// @param key: The key of the leaf to be added\n /// @param value: The data to update the leaf with\n /// @param numLeaves: The total number of leaves in the tree\n /// @return newRoot : The new root of the tree\n function addBranchesAndUpdate(\n MerkleBranch[] memory branches,\n bytes32 root,\n bytes32 key,\n bytes memory value,\n uint256 numLeaves\n ) public pure returns (bytes32 newRoot) {\n bytes32 rootPtr = Constants.ZERO;\n for (uint256 i = 0; i < branches.length; i++) {\n rootPtr = addBranch(\n branches[i].key,\n branches[i].value,\n branches[i].proof,\n root,\n rootPtr,\n numLeaves\n );\n }\n\n bytes32[] memory sideNodes = sideNodesForRoot(key, rootPtr, numLeaves);\n bytes32 newRootPtr = updateWithSideNodes(key, value, sideNodes, numLeaves);\n\n return getNodeAtPtr(newRootPtr).digest;\n }\n\n /// @notice Derive the proof for a new appended leaf from the proof for the last appended leaf\n /// @param oldProof: The proof to the last appeneded leaf\n /// @param lastLeaf: The last leaf hash\n /// @param key: The key of the new leaf\n /// @return : The proof for the appending of the new leaf\n /// @dev This function assumes that oldProof has been verified in position (key - 1)\n function deriveAppendProofFromLastProof(\n bytes32[] memory oldProof,\n bytes32 lastLeaf,\n uint256 key\n ) public pure returns (bytes32[] memory) {\n // First prepend last leaf to its proof.\n bytes32[] memory newProofBasis = new bytes32[](oldProof.length + 1);\n newProofBasis[0] = leafDigest(abi.encodePacked(lastLeaf));\n for (uint256 i = 0; i < oldProof.length; i += 1) {\n newProofBasis[i + 1] = oldProof[i];\n }\n\n // If the new leaf is \"even\", this will already be the new proof\n if (key & 1 == 1) {\n return newProofBasis;\n }\n\n // Otherwise, get the expected length of the new proof (it's the last leaf by definition, so numLeaves = key + 1)\n // Assuming old proof was valid, this will always be shorter than the old proof.\n uint256 expectedProofLength = pathLengthFromKey(key, key + 1);\n\n bytes32[] memory newProof = new bytes32[](expectedProofLength);\n\n // \"Hash up\" through old proof until we have the correct first sidenode\n bytes32 firstSideNode = newProofBasis[0];\n uint256 hashedUpIndex = 0;\n while (hashedUpIndex < (newProofBasis.length - expectedProofLength)) {\n firstSideNode = nodeDigest(newProofBasis[hashedUpIndex + 1], firstSideNode);\n hashedUpIndex += 1;\n }\n\n // Set the calculated first side node as the first element in the proof\n newProof[0] = firstSideNode;\n\n // Then append the remaining (unchanged) sidenodes, if any\n for (uint256 j = 1; j < expectedProofLength; j += 1) {\n newProof[j] = newProofBasis[hashedUpIndex + j];\n }\n\n return newProof;\n }\n}\n" - }, - "@fuel-contracts/merkle-sol/contracts/tree/binary/BinaryMerkleTreeUtils.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\nimport {Node} from \"./Node.sol\";\nimport {nodeDigest, leafDigest} from \"./TreeHasher.sol\";\nimport {parseNode, isLeaf} from \"./TreeHasher.sol\";\nimport {BinaryMerkleProof} from \"./BinaryMerkleProof.sol\";\nimport {Constants} from \"../Constants.sol\";\nimport {pathLengthFromKey, getStartingBit} from \"../Utils.sol\";\nimport {getBitAtFromMSB, reverseSideNodes} from \"../Utils.sol\";\nimport {shrinkBytes32Array} from \"../Utils.sol\";\n\n/// @notice Get the pointer to a node in memory\n/// @param node: The node to get the pointer to\n/// @return ptr : The pointer to the node\n// solhint-disable-next-line func-visibility\nfunction getPtrToNode(Node memory node) pure returns (bytes32 ptr) {\n assembly {\n ptr := node\n }\n}\n\n/// @notice Get a node at a given pointer\n/// @param ptr: The pointer to the node\n/// @return node : The node\n// solhint-disable-next-line func-visibility\nfunction getNodeAtPtr(bytes32 ptr) pure returns (Node memory node) {\n assembly {\n node := ptr\n }\n}\n\n/// @notice Verify if element (key, data) exists in Merkle tree, given data, proof, and root.\n/// @param root: The root of the tree in which verify the given leaf\n/// @param data: The data of the leaf to verify\n/// @param key: The key of the leaf to verify.\n/// @param proof: Binary Merkle Proof for the leaf.\n/// @param numLeaves: The number of leaves in the tree\n/// @return : Whether the proof is valid\n/// @dev numLeaves is necessary to determine height of sub-tree containing the data to prove\n// solhint-disable-next-line func-visibility\nfunction verifyBinaryTree(\n bytes32 root,\n bytes memory data,\n bytes32[] memory proof,\n uint256 key,\n uint256 numLeaves\n) pure returns (bool) {\n // A sibling at height 1 is created by getting the hash of the data to prove.\n return verifyBinaryTreeDigest(root, leafDigest(data), proof, key, numLeaves);\n}\n\n/// @notice Verify if element (key, digest) exists in Merkle tree, given digest, proof, and root.\n/// @param root: The root of the tree in which verify the given leaf\n/// @param digest: The digest of the data of the leaf to verify\n/// @param key: The key of the leaf to verify.\n/// @param proof: Binary Merkle Proof for the leaf.\n/// @param numLeaves: The number of leaves in the tree\n/// @return : Whether the proof is valid\n/// @dev numLeaves is necessary to determine height of sub-tree containing the data to prove\n// solhint-disable-next-line func-visibility\nfunction verifyBinaryTreeDigest(\n bytes32 root,\n bytes32 digest,\n bytes32[] memory proof,\n uint256 key,\n uint256 numLeaves\n) pure returns (bool) {\n // Check proof is correct length for the key it is proving\n if (numLeaves <= 1) {\n if (proof.length != 0) {\n return false;\n }\n } else if (proof.length != pathLengthFromKey(key, numLeaves)) {\n return false;\n }\n\n // Check key is in tree\n if (key >= numLeaves) {\n return false;\n }\n\n // Null proof is only valid if numLeaves = 1\n // If so, just verify digest is root\n if (proof.length == 0) {\n if (numLeaves == 1) {\n return (root == digest);\n } else {\n return false;\n }\n }\n\n uint256 height = 1;\n uint256 stableEnd = key;\n\n // While the current subtree (of height 'height') is complete, determine\n // the position of the next sibling using the complete subtree algorithm.\n // 'stableEnd' tells us the ending index of the last full subtree. It gets\n // initialized to 'key' because the first full subtree was the\n // subtree of height 1, created above (and had an ending index of\n // 'key').\n\n while (true) {\n // Determine if the subtree is complete. This is accomplished by\n // rounding down the key to the nearest 1 << 'height', adding 1\n // << 'height', and comparing the result to the number of leaves in the\n // Merkle tree.\n\n uint256 subTreeStartIndex = (key / (1 << height)) * (1 << height);\n uint256 subTreeEndIndex = subTreeStartIndex + (1 << height) - 1;\n\n // If the Merkle tree does not have a leaf at index\n // 'subTreeEndIndex', then the subtree of the current height is not\n // a complete subtree.\n if (subTreeEndIndex >= numLeaves) {\n break;\n }\n stableEnd = subTreeEndIndex;\n\n // Determine if the key is in the first or the second half of\n // the subtree.\n if (proof.length <= height - 1) {\n return false;\n }\n if (key - subTreeStartIndex < (1 << (height - 1))) {\n digest = nodeDigest(digest, proof[height - 1]);\n } else {\n digest = nodeDigest(proof[height - 1], digest);\n }\n\n height += 1;\n }\n\n // Determine if the next hash belongs to an orphan that was elevated. This\n // is the case IFF 'stableEnd' (the last index of the largest full subtree)\n // is equal to the number of leaves in the Merkle tree.\n if (stableEnd != numLeaves - 1) {\n if (proof.length <= height - 1) {\n return false;\n }\n digest = nodeDigest(digest, proof[height - 1]);\n height += 1;\n }\n\n // All remaining elements in the proof set will belong to a left sibling\\\n // i.e proof sideNodes are hashed in \"from the left\"\n while (height - 1 < proof.length) {\n digest = nodeDigest(proof[height - 1], digest);\n height += 1;\n }\n\n return (digest == root);\n}\n\n/// @notice Computes Merkle tree root from leaves.\n/// @param data: list of leaves' data in ascending for leaves order.\n/// @return : The root of the tree\n// solhint-disable-next-line func-visibility\nfunction computeBinaryTreeRoot(bytes[] memory data) pure returns (bytes32) {\n if (data.length == 0) {\n return Constants.EMPTY;\n }\n bytes32[] memory nodes = new bytes32[](data.length);\n for (uint256 i = 0; i < data.length; ++i) {\n nodes[i] = leafDigest(data[i]);\n }\n uint256 size = (nodes.length + 1) >> 1;\n uint256 odd = nodes.length & 1;\n // pNodes are nodes in previous level.\n // We use pNodes to avoid damaging the input leaves.\n bytes32[] memory pNodes = nodes;\n while (true) {\n uint256 i = 0;\n for (; i < size - odd; ++i) {\n uint256 j = i << 1;\n nodes[i] = nodeDigest(pNodes[j], pNodes[j + 1]);\n }\n if (odd == 1) {\n nodes[i] = pNodes[i << 1];\n }\n if (size == 1) {\n break;\n }\n odd = (size & 1);\n size = (size + 1) >> 1;\n pNodes = nodes;\n }\n return nodes[0];\n}\n\n/// @notice Appends a new element by calculating new root, returns new root and if successful, pure function.\n/// @param numLeaves, number of leaves in the tree currently.\n/// @param data, The data of the leaf to append.\n/// @param proof, Binary Merkle Proof to use for the leaf.\n/// @return : The root of the new tree\n/// @return : Whether the proof is valid\n// solhint-disable-next-line func-visibility\nfunction appendBinaryTree(\n uint256 numLeaves,\n bytes memory data,\n bytes32[] memory proof\n) pure returns (bytes32, bool) {\n bytes32 digest = leafDigest(data);\n\n // Since appended leaf is last leaf in tree by definition, its path consists only of set bits\n // (because all side nodes will be on its left)\n // Therefore, the number of steps in the proof should equal number of bits set in the key\n // E.g. If appending the 7th leaf, key = 0b110 => proofLength = 2.\n\n uint256 proofLength = 0;\n while (numLeaves > 0) {\n proofLength += numLeaves & 1;\n numLeaves = numLeaves >> 1;\n }\n\n if (proof.length != proofLength) {\n return (Constants.NULL, false);\n }\n\n // If proof length is correctly 0, tree is empty, and we are appending the first leaf\n if (proofLength == 0) {\n digest = leafDigest(data);\n }\n // Otherwise tree non-empty so we calculate nodes up to root\n else {\n for (uint256 i = 0; i < proofLength; ++i) {\n digest = nodeDigest(proof[i], digest);\n }\n }\n\n return (digest, true);\n}\n\n/// @notice Adds a branch to the in-storage sparse representation of tree\n/// @dev We store the minimum subset of nodes necessary to calculate the root\n/// @param key: The key of the leaf\n/// @param value : The data of the leaf\n/// @param root : The root of the tree containing the added branch\n/// @param rootPtr : The pointer to the root node\n/// @param proof: The proof (assumed valid) of the leaf up to the root\n/// @param numLeaves: The total number of leaves in the tree\n/// @return : The pointer to the root node\n// solhint-disable-next-line func-visibility\nfunction addBranch(\n bytes32 key,\n bytes memory value,\n bytes32[] memory proof,\n bytes32 root,\n bytes32 rootPtr,\n uint256 numLeaves\n) pure returns (bytes32) {\n // Handle case where tree has only one leaf (so it is the root)\n if (numLeaves == 1) {\n Node memory rootNode = Node(root, Constants.NULL, Constants.NULL);\n rootPtr = getPtrToNode(rootNode);\n return rootPtr;\n }\n uint256 startingBit = getStartingBit(numLeaves);\n\n AddBranchVariables memory variables;\n\n bytes32[] memory sideNodePtrs = new bytes32[](proof.length);\n bytes32[] memory nodePtrs = new bytes32[](proof.length);\n\n // Set root\n // When adding the first branch, rootPtr will not be set yet, set it here.\n if (rootPtr == Constants.NULL) {\n // Set the new root\n Node memory rootNode = Node(root, Constants.NULL, Constants.NULL);\n rootPtr = getPtrToNode(rootNode);\n variables.parent = rootNode;\n }\n // On subsequent branches, we need to retrieve root\n else {\n variables.parent = getNodeAtPtr(rootPtr);\n }\n\n // Step backwards through proof (from root down to leaf), getting pointers to the nodes/sideNodes\n // If node is not yet added, set digest to NULL (we'll set it when we hash back up the branch)\n for (uint256 i = proof.length; i > 0; i -= 1) {\n uint256 j = i - 1;\n\n // Descend into left or right subtree depending on key\n // If leaf is in the right subtree:\n if (getBitAtFromMSB(key, startingBit + proof.length - i) == 1) {\n // Subtree is on the right, so sidenode is on the left.\n // Check to see if sidenode already exists. If not, create it. and associate with parent\n if (variables.parent.leftChildPtr == Constants.NULL) {\n variables.sideNode = Node(proof[j], Constants.NULL, Constants.NULL);\n variables.sideNodePtr = getPtrToNode(variables.sideNode);\n variables.parent.leftChildPtr = variables.sideNodePtr;\n } else {\n variables.sideNodePtr = variables.parent.leftChildPtr;\n }\n\n // Check to see if node already exists. If not, create it. and associate with parent\n // Its digest is initially null. We calculate and set it when we climb back up the tree\n if (variables.parent.rightChildPtr == Constants.NULL) {\n variables.node = Node(Constants.NULL, Constants.NULL, Constants.NULL);\n variables.nodePtr = getPtrToNode(variables.node);\n variables.parent.rightChildPtr = variables.nodePtr;\n } else {\n variables.nodePtr = variables.parent.rightChildPtr;\n variables.node = getNodeAtPtr(variables.nodePtr);\n }\n\n // Mirror image of preceding code block, for when leaf is in the left subtree\n // If subtree is on the left, sideNode is on the right\n } else {\n if (variables.parent.rightChildPtr == Constants.NULL) {\n variables.sideNode = Node(proof[j], Constants.NULL, Constants.NULL);\n variables.sideNodePtr = getPtrToNode(variables.sideNode);\n variables.parent.rightChildPtr = variables.sideNodePtr;\n } else {\n variables.sideNodePtr = variables.parent.rightChildPtr;\n }\n\n if (variables.parent.leftChildPtr == Constants.NULL) {\n variables.node = Node(Constants.NULL, Constants.NULL, Constants.NULL);\n variables.nodePtr = getPtrToNode(variables.node);\n variables.parent.leftChildPtr = variables.nodePtr;\n } else {\n variables.nodePtr = variables.parent.leftChildPtr;\n variables.node = getNodeAtPtr(variables.nodePtr);\n }\n }\n\n // Keep pointers to sideNode and node\n sideNodePtrs[j] = variables.sideNodePtr;\n nodePtrs[j] = variables.nodePtr;\n\n variables.parent = variables.node;\n }\n\n // Set leaf digest\n Node memory leaf = getNodeAtPtr(nodePtrs[0]);\n leaf.digest = leafDigest(value);\n\n if (proof.length == 0) {\n return rootPtr;\n }\n\n // Go back up the tree, setting the digests of nodes on the branch\n for (uint256 i = 1; i < nodePtrs.length; i += 1) {\n variables.node = getNodeAtPtr(nodePtrs[i]);\n variables.node.digest = nodeDigest(\n getNodeAtPtr(variables.node.leftChildPtr).digest,\n getNodeAtPtr(variables.node.rightChildPtr).digest\n );\n }\n\n return rootPtr;\n}\n\n/// @notice Get the sidenodes for a given leaf key up to the root\n/// @param key: The key for which to find the sidenodes\n/// @param rootPtr: The memory pointer to the root of the tree\n/// @param numLeaves : The total number of leaves in the tree\n/// @return The sidenodes up to the root.\n// solhint-disable-next-line func-visibility\nfunction sideNodesForRoot(\n bytes32 key,\n bytes32 rootPtr,\n uint256 numLeaves\n) pure returns (bytes32[] memory) {\n // Allocate a large enough array for the sidenodes (we'll shrink it later)\n bytes32[] memory sideNodes = new bytes32[](256);\n\n Node memory currentNode = getNodeAtPtr(rootPtr);\n\n // If the root is a placeholder, the tree is empty, so there are no sidenodes to return.\n // The leaf pointer is the root pointer\n if (currentNode.digest == Constants.ZERO) {\n bytes32[] memory emptySideNodes;\n return emptySideNodes;\n }\n\n // If the root is a leaf, the tree has only one leaf, so there are also no sidenodes to return.\n // The leaf pointer is the root pointer\n if (isLeaf(currentNode)) {\n bytes32[] memory emptySideNodes;\n return emptySideNodes;\n }\n\n // Tree has at least 2 leaves\n SideNodesFunctionVariables memory variables;\n\n variables.sideNodeCount = 0;\n\n uint256 startingBit = getStartingBit(numLeaves);\n uint256 pathLength = pathLengthFromKey(uint256(key), numLeaves);\n\n // Descend the tree from the root according to the key, collecting side nodes\n for (uint256 i = startingBit; i < startingBit + pathLength; i++) {\n (variables.leftNodePtr, variables.rightNodePtr) = parseNode(currentNode);\n // Bifurcate left or right depending on bit in key\n if (getBitAtFromMSB(key, i) == 1) {\n (variables.nodePtr, variables.sideNodePtr) = (\n variables.rightNodePtr,\n variables.leftNodePtr\n );\n } else {\n (variables.nodePtr, variables.sideNodePtr) = (\n variables.leftNodePtr,\n variables.rightNodePtr\n );\n }\n\n sideNodes[variables.sideNodeCount] = variables.sideNodePtr;\n variables.sideNodeCount += 1;\n\n currentNode = getNodeAtPtr(variables.nodePtr);\n }\n\n return reverseSideNodes(shrinkBytes32Array(sideNodes, variables.sideNodeCount));\n}\n\nstruct AddBranchVariables {\n bytes32 nodePtr;\n bytes32 sideNodePtr;\n Node node;\n Node parent;\n Node sideNode;\n}\n\n/// @notice A struct to hold variables of the sidenodes function in memory\n/// @dev Necessary to circumvent stack-too-deep errors caused by too many\n/// @dev variables on the stack.\nstruct SideNodesFunctionVariables {\n bytes32 leftNodePtr;\n bytes32 rightNodePtr;\n bytes32 nodePtr;\n bytes32 sideNodePtr;\n uint256 sideNodeCount;\n}\n" - }, - "@fuel-contracts/merkle-sol/contracts/tree/binary/Branch.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\nstruct MerkleBranch {\n bytes32[] proof;\n bytes32 key;\n bytes value;\n}\n" - }, - "@fuel-contracts/merkle-sol/contracts/tree/binary/Node.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\n/// @notice Merkle Tree Node structure.\nstruct Node {\n bytes32 digest;\n // Left child.\n bytes32 leftChildPtr;\n // Right child.\n bytes32 rightChildPtr;\n}\n" - }, - "@fuel-contracts/merkle-sol/contracts/tree/binary/TreeHasher.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\nimport {CryptographyLib} from \"../Cryptography.sol\";\nimport {Constants} from \"../Constants.sol\";\nimport {Node} from \"./Node.sol\";\n\n/// @notice hash some data\n/// @param data: The data to be hashed\n// solhint-disable-next-line func-visibility\nfunction hash(bytes memory data) pure returns (bytes32) {\n return CryptographyLib.hash(data);\n}\n\n/// @notice Calculate the digest of a node\n/// @param left : The left child\n/// @param right: The right child\n/// @return digest : The node digest\n// solhint-disable-next-line func-visibility\nfunction nodeDigest(bytes32 left, bytes32 right) pure returns (bytes32 digest) {\n digest = hash(abi.encodePacked(Constants.NODE_PREFIX, left, right));\n}\n\n/// @notice Calculate the digest of a leaf\n/// @param data : The data of the leaf\n/// @return digest : The leaf digest\n// solhint-disable-next-line func-visibility\nfunction leafDigest(bytes memory data) pure returns (bytes32 digest) {\n digest = hash(abi.encodePacked(Constants.LEAF_PREFIX, data));\n}\n\n/// @notice Hash a leaf node.\n/// @param data, raw data of the leaf.\n/// @return The leaf represented as a Node struct\n// solhint-disable-next-line func-visibility\nfunction hashLeaf(bytes memory data) pure returns (Node memory) {\n bytes32 digest = leafDigest(data);\n return Node(digest, Constants.NULL, Constants.NULL);\n}\n\n/// @notice Hash a node, which is not a leaf.\n/// @param left, left child hash.\n/// @param right, right child hash.\n/// @param leftPtr, the pointer to the left child\n/// @param rightPtr, the pointer to the right child\n/// @return : The new Node object\n// solhint-disable-next-line func-visibility\nfunction hashNode(\n bytes32 leftPtr,\n bytes32 rightPtr,\n bytes32 left,\n bytes32 right\n) pure returns (Node memory) {\n bytes32 digest = nodeDigest(left, right);\n return Node(digest, leftPtr, rightPtr);\n}\n\n/// @notice Parse a node's data into its left and right children\n/// @param node: The node to be parsed\n/// @return : Pointers to the left and right children\n// solhint-disable-next-line func-visibility\nfunction parseNode(Node memory node) pure returns (bytes32, bytes32) {\n return (node.leftChildPtr, node.rightChildPtr);\n}\n\n/// @notice See if node has children, otherwise it is a leaf\n/// @param node: The node to be parsed\n/// @return : Whether the node is a leaf.\n// solhint-disable-next-line func-visibility\nfunction isLeaf(Node memory node) pure returns (bool) {\n return (node.leftChildPtr == Constants.ZERO || node.rightChildPtr == Constants.ZERO);\n}\n" - }, - "@fuel-contracts/merkle-sol/contracts/tree/Constants.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\nlibrary Constants {\n ///////////////\n // Constants //\n ///////////////\n\n /// @dev Maximum tree height\n uint256 internal constant MAX_HEIGHT = 256;\n\n /// @dev Empty node hash\n bytes32 internal constant EMPTY = sha256(\"\");\n\n /// @dev Default value for sparse Merkle tree node\n bytes32 internal constant ZERO = bytes32(0);\n\n /// @dev The null pointer\n bytes32 internal constant NULL = bytes32(0);\n\n /// @dev The prefixes of leaves and nodes\n bytes1 internal constant LEAF_PREFIX = 0x00;\n bytes1 internal constant NODE_PREFIX = 0x01;\n}\n" - }, - "@fuel-contracts/merkle-sol/contracts/tree/Cryptography.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\n/// @notice This library abstracts the hashing function used for the merkle tree implementation\nlibrary CryptographyLib {\n /// @notice The hash method\n /// @param data The bytes input data.\n /// @return The returned hash result.\n function hash(bytes memory data) internal pure returns (bytes32) {\n return sha256(data);\n }\n}\n" - }, - "@fuel-contracts/merkle-sol/contracts/tree/Utils.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.4;\n\nimport {Constants} from \"./Constants.sol\";\n\n/// @notice Calculate the starting bit of the path to a leaf\n/// @param numLeaves : The total number of leaves in the tree\n/// @return startingBit : The starting bit of the path\n// solhint-disable-next-line func-visibility\nfunction getStartingBit(uint256 numLeaves) pure returns (uint256 startingBit) {\n // Determine height of the left subtree. This is the maximum path length, so all paths start at this offset from the right-most bit\n startingBit = 0;\n while ((1 << startingBit) < numLeaves) {\n startingBit += 1;\n }\n return Constants.MAX_HEIGHT - startingBit;\n}\n\n/// @notice Calculate the length of the path to a leaf\n/// @param key: The key of the leaf\n/// @param numLeaves: The total number of leaves in the tree\n/// @return pathLength : The length of the path to the leaf\n/// @dev A precondition to this function is that `numLeaves > 1`, so that `(pathLength - 1)` does not cause an underflow when pathLength = 0.\n// solhint-disable-next-line func-visibility\nfunction pathLengthFromKey(uint256 key, uint256 numLeaves) pure returns (uint256 pathLength) {\n // Get the height of the left subtree. This is equal to the offset of the starting bit of the path\n pathLength = 256 - getStartingBit(numLeaves);\n\n // Determine the number of leaves in the left subtree\n uint256 numLeavesLeftSubTree = (1 << (pathLength - 1));\n\n // If leaf is in left subtree, path length is full height of left subtree\n if (key <= numLeavesLeftSubTree - 1) {\n return pathLength;\n }\n // Otherwise, if left sub tree has only one leaf, path has one additional step\n else if (numLeavesLeftSubTree == 1) {\n return 1;\n }\n // Otherwise, if right sub tree has only one leaf, path has one additional step\n else if (numLeaves - numLeavesLeftSubTree <= 1) {\n return 1;\n }\n // Otherwise, add 1 to height and recurse into right subtree\n else {\n return 1 + pathLengthFromKey(key - numLeavesLeftSubTree, numLeaves - numLeavesLeftSubTree);\n }\n}\n\n/// @notice Gets the bit at an offset from the most significant bit\n/// @param data: The data to check the bit\n/// @param position: The position of the bit to check\n// solhint-disable-next-line func-visibility\nfunction getBitAtFromMSB(bytes32 data, uint256 position) pure returns (uint256) {\n if (uint8(data[position / 8]) & (1 << (8 - 1 - (position % 8))) > 0) {\n return 1;\n } else {\n return 0;\n }\n}\n\n/// @notice Reverses an array\n/// @param sideNodes: The array of sidenodes to be reversed\n/// @return The reversed array\n// solhint-disable-next-line func-visibility\nfunction reverseSideNodes(bytes32[] memory sideNodes) pure returns (bytes32[] memory) {\n uint256 left = 0;\n uint256 right = sideNodes.length - 1;\n\n while (left < right) {\n (sideNodes[left], sideNodes[right]) = (sideNodes[right], sideNodes[left]);\n left = left + 1;\n right = right - 1;\n }\n return sideNodes;\n}\n\n/// @notice Counts the number of leading bits two bytes32 have in common\n/// @param data1: The first piece of data to compare\n/// @param data2: The second piece of data to compare\n/// @return The number of shared leading bits\n// solhint-disable-next-line func-visibility\nfunction countCommonPrefix(bytes32 data1, bytes32 data2) pure returns (uint256) {\n uint256 count = 0;\n\n for (uint256 i = 0; i < Constants.MAX_HEIGHT; i++) {\n if (getBitAtFromMSB(data1, i) == getBitAtFromMSB(data2, i)) {\n count += 1;\n } else {\n break;\n }\n }\n return count;\n}\n\n/// @notice Shrinks an over-allocated dynamic array of bytes32 to the correct size\n/// @param inputArray: The bytes32 array to be shrunk\n/// @param length: The length to shrink to\n/// @return finalArray : The full array of bytes32\n/// @dev Needed where an unknown number of elements are to be pushed to a dynamic array\n/// @dev We fist allocate a large-enough array, and then shrink once we're done populating it\n// solhint-disable-next-line func-visibility\nfunction shrinkBytes32Array(bytes32[] memory inputArray, uint256 length)\n pure\n returns (bytes32[] memory finalArray)\n{\n finalArray = new bytes32[](length);\n for (uint256 i = 0; i < length; i++) {\n finalArray[i] = inputArray[i];\n }\n return finalArray;\n}\n\n/// @notice compares a byte array to the (bytes32) default (ZERO) value\n/// @param value : The bytes to compare\n/// @dev No byte array comparison in solidity, so compare keccak hashes\n// solhint-disable-next-line func-visibility\nfunction isDefaultValue(bytes memory value) pure returns (bool) {\n return keccak256(value) == keccak256(abi.encodePacked(Constants.ZERO));\n}\n" - }, - "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../utils/StringsUpgradeable.sol\";\nimport \"../utils/introspection/ERC165Upgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable {\n function __AccessControl_init() internal onlyInitializing {\n }\n\n function __AccessControl_init_unchained() internal onlyInitializing {\n }\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n StringsUpgradeable.toHexString(account),\n \" is missing role \",\n StringsUpgradeable.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" - }, - "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControlUpgradeable {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" - }, - "@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822ProxiableUpgradeable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" - }, - "@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.3) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.9._\n */\ninterface IERC1967Upgradeable {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" - }, - "@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeaconUpgradeable {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" - }, - "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.3) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeaconUpgradeable.sol\";\nimport \"../../interfaces/IERC1967Upgradeable.sol\";\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/StorageSlotUpgradeable.sol\";\nimport \"../utils/Initializable.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {\n function __ERC1967Upgrade_init() internal onlyInitializing {\n }\n\n function __ERC1967Upgrade_init_unchained() internal onlyInitializing {\n }\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(AddressUpgradeable.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n _functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(AddressUpgradeable.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);\n }\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) {\n require(AddressUpgradeable.isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return AddressUpgradeable.verifyCallResult(success, returndata, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" - }, - "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../ERC1967/ERC1967UpgradeUpgradeable.sol\";\nimport \"./Initializable.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {\n function __UUPSUpgradeable_init() internal onlyInitializing {\n }\n\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\n }\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n address private immutable __self = address(this);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n require(address(this) != __self, \"Function must be called through delegatecall\");\n require(_getImplementation() == __self, \"Function must be called through active proxy\");\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n _;\n }\n\n /**\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n return _IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeTo(address newImplementation) external virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data, true);\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal override onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" - }, - "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" - }, - "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" - }, - "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" - }, - "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" - }, - "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" - }, - "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/draft-IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n function safeTransfer(\n IERC20Upgradeable token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20Upgradeable token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20Upgradeable token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20Upgradeable token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20Upgradeable token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721Upgradeable is IERC165Upgradeable {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\n function __ERC165_init() internal onlyInitializing {\n }\n\n function __ERC165_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165Upgradeable).interfaceId;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary MathUpgradeable {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlotUpgradeable {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/MathUpgradeable.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = MathUpgradeable.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, MathUpgradeable.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/ERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/ERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.2) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n using Address for address;\n using Strings for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: address zero is not a valid owner\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _ownerOf(tokenId);\n require(owner != address(0), \"ERC721: invalid token ID\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n _requireMinted(tokenId);\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not token owner or approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n _requireMinted(tokenId);\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n _safeTransfer(from, to, tokenId, data);\n }\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeTransfer(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n */\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n return _owners[tokenId];\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _ownerOf(tokenId) != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n address owner = ERC721.ownerOf(tokenId);\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(\n address to,\n uint256 tokenId,\n bytes memory data\n ) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId, 1);\n\n // Check that tokenId was not minted by `_beforeTokenTransfer` hook\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n unchecked {\n // Will not overflow unless all 2**256 token ids are minted to the same owner.\n // Given that tokens are minted one by one, it is impossible in practice that\n // this ever happens. Might change if we allow batch minting.\n // The ERC fails to describe this case.\n _balances[to] += 1;\n }\n\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n\n _afterTokenTransfer(address(0), to, tokenId, 1);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n * This is an internal function that does not check if the sender is authorized to operate on the token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId, 1);\n\n // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\n owner = ERC721.ownerOf(tokenId);\n\n // Clear approvals\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // Cannot overflow, as that would require more tokens to be burned/transferred\n // out than the owner initially received through minting and transferring in.\n _balances[owner] -= 1;\n }\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n\n _afterTokenTransfer(owner, address(0), tokenId, 1);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId, 1);\n\n // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n\n // Clear approvals from the previous owner\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\n // `from`'s balance is the number of token held, which is at least one before the current\n // transfer.\n // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\n // all 2**256 token ids to be minted, which in practice is impossible.\n _balances[from] -= 1;\n _balances[to] += 1;\n }\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n _afterTokenTransfer(from, to, tokenId, 1);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits an {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\n return retval == IERC721Receiver.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\n * - When `from` is zero, the tokens will be minted for `to`.\n * - When `to` is zero, ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 firstTokenId,\n uint256 batchSize\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\n * - When `from` is zero, the tokens were minted for `to`.\n * - When `to` is zero, ``from``'s tokens were burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 firstTokenId,\n uint256 batchSize\n ) internal virtual {}\n\n /**\n * @dev Unsafe write access to the balances, used by extensions that \"mint\" tokens using an {ownerOf} override.\n *\n * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant\n * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such\n * that `ownerOf(tokenId)` is `a`.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __unsafe_increaseBalance(address account, uint256 amount) internal {\n _balances[account] += amount;\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "@openzeppelin/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "@openzeppelin/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" - }, - "contracts/fuelchain/FuelChainState.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n// solhint-disable not-rely-on-time\npragma solidity 0.8.9;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {AccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {CryptographyLib} from \"../lib/Cryptography.sol\";\n\n/// @notice Structure for commits\nstruct Commit {\n bytes32 blockHash;\n uint32 timestamp;\n address reserved1;\n uint16 reserved2;\n}\n\n/// @notice The Fuel v2 chain state\ncontract FuelChainState is Initializable, PausableUpgradeable, AccessControlUpgradeable, UUPSUpgradeable {\n ///////////////\n // Constants //\n ///////////////\n\n /// @dev The commit proccess parameters\n //TODO: update these values once block time and commit frequency are finalized\n // days worth of commits\n // NUM_COMMIT_SLOTS an arbitrary number of commits to store before starting to overwrite\n uint256 public constant NUM_COMMIT_SLOTS = 240;\n // Number of blocks per commit interval\n // BLOCKS_PER_COMMIT_INTERVAL = (num of blocks per minute * target interval in minutes)\n uint256 public constant BLOCKS_PER_COMMIT_INTERVAL = 10800;\n // Time to fianlize in seconds\n // TIME_TO_FINALIZE = target interval in minutes * 60\n uint256 public constant TIME_TO_FINALIZE = 10800;\n\n /// @dev The admin related contract roles\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n bytes32 public constant COMMITTER_ROLE = keccak256(\"COMMITTER_ROLE\");\n\n ////////////\n // Events //\n ////////////\n\n /// @dev Emitted when a commit is first submitted\n event CommitSubmitted(uint256 indexed commitHeight, bytes32 blockHash);\n\n ////////////\n // Errors //\n ////////////\n\n error UnknownBlock();\n\n /////////////\n // Storage //\n /////////////\n\n /// @dev The commits buffer\n Commit[NUM_COMMIT_SLOTS] private _commitSlots;\n\n /////////////////////////////\n // Constructor/Initializer //\n /////////////////////////////\n\n /// @notice Constructor disables initialization for the implementation contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /// @notice Contract initializer to setup starting values\n function initialize() public initializer {\n __Pausable_init();\n __AccessControl_init();\n __UUPSUpgradeable_init();\n\n //grant initial roles\n _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _grantRole(PAUSER_ROLE, msg.sender);\n _grantRole(COMMITTER_ROLE, msg.sender);\n }\n\n /////////////////////\n // Admin Functions //\n /////////////////////\n\n /// @notice Pause block commitments\n function pause() external onlyRole(PAUSER_ROLE) {\n _pause();\n }\n\n /// @notice Unpause block commitments\n function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) {\n _unpause();\n }\n\n /// @notice Commits a block header.\n /// @dev Committing to the same commitHeight twice would have the effect of delaying\n /// finality, as the timestamp of the committed slot is taken from the ETH block\n /// timestamp. TODO: it might be reasonable to put a require here to disallow overwriting\n /// In the future we will want this to be challenge-able, and rewriting the slot\n /// could open for foul play during IVG\n /// @param blockHash The hash of a block\n /// @param commitHeight The height of the commit\n function commit(bytes32 blockHash, uint256 commitHeight) external whenNotPaused onlyRole(COMMITTER_ROLE) {\n uint256 slot = commitHeight % NUM_COMMIT_SLOTS;\n Commit storage commitSlot = _commitSlots[slot];\n commitSlot.blockHash = blockHash;\n commitSlot.timestamp = uint32(block.timestamp);\n\n emit CommitSubmitted(commitHeight, blockHash);\n }\n\n //////////////////////\n // Public Functions //\n //////////////////////\n\n /// @notice Checks if a given block is finalized\n /// @param blockHash The hash of the block to check\n /// @param blockHeight The height of the block to check\n /// @return true if the block is finalized\n function finalized(bytes32 blockHash, uint256 blockHeight) external view whenNotPaused returns (bool) {\n // TODO This division could be done offchain, or at least also could be assembly'ed to avoid non-zero division check\n uint256 commitHeight = blockHeight / BLOCKS_PER_COMMIT_INTERVAL;\n Commit storage commitSlot = _commitSlots[commitHeight % NUM_COMMIT_SLOTS];\n if (commitSlot.blockHash != blockHash) revert UnknownBlock();\n\n return block.timestamp >= uint256(commitSlot.timestamp) + TIME_TO_FINALIZE;\n }\n\n /// @notice Gets the block hash at the given commit height\n /// @param commitHeight The height of the commit\n /// @return hash of the block at the given commit height\n function blockHashAtCommit(uint256 commitHeight) external view returns (bytes32) {\n Commit storage commitSlot = _commitSlots[commitHeight % NUM_COMMIT_SLOTS];\n return commitSlot.blockHash;\n }\n\n ////////////////////////\n // Internal Functions //\n ////////////////////////\n\n /// @notice Executes a message in the given header\n // solhint-disable-next-line no-empty-blocks\n function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {\n //should revert if msg.sender is not authorized to upgrade the contract (currently only owner)\n }\n}\n" - }, - "contracts/fuelchain/FuelMessagePortal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {AccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {ReentrancyGuardUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport {verifyBinaryTree} from \"@fuel-contracts/merkle-sol/contracts/tree/binary/BinaryMerkleTree.sol\";\nimport {FuelChainState} from \"./FuelChainState.sol\";\nimport {FuelBlockHeader, FuelBlockHeaderLib} from \"./types/FuelBlockHeader.sol\";\nimport {FuelBlockHeaderLite, FuelBlockHeaderLiteLib} from \"./types/FuelBlockHeaderLite.sol\";\nimport {CryptographyLib} from \"../lib/Cryptography.sol\";\nimport {CommonPredicates} from \"../lib/CommonPredicates.sol\";\n\n/// @notice Structure for proving an element in a merkle tree\nstruct MerkleProof {\n uint256 key;\n bytes32[] proof;\n}\n\n/// @notice Structure containing all message details\nstruct Message {\n bytes32 sender;\n bytes32 recipient;\n bytes32 nonce;\n uint64 amount;\n bytes data;\n}\n\n/// @title FuelMessagePortal\n/// @notice The Fuel Message Portal contract sends messages to and from Fuel\ncontract FuelMessagePortal is\n Initializable,\n PausableUpgradeable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n UUPSUpgradeable\n{\n using FuelBlockHeaderLib for FuelBlockHeader;\n using FuelBlockHeaderLiteLib for FuelBlockHeaderLite;\n\n ////////////\n // Events //\n ////////////\n\n /// @dev Emitted when a message is sent from Ethereum to Fuel\n event MessageSent(\n bytes32 indexed sender,\n bytes32 indexed recipient,\n uint256 indexed nonce,\n uint64 amount,\n bytes data\n );\n\n /// @dev Emitted when a message is successfully relayed to Ethereum from Fuel\n event MessageRelayed(bytes32 indexed messageId, bytes32 indexed sender, bytes32 indexed recipient, uint64 amount);\n\n ////////////\n // Errors //\n ////////////\n\n error UnfinalizedBlock();\n error InvalidBlockInHistoryProof();\n error InvalidMessageInBlockProof();\n error CurrentMessageSenderNotSet();\n error MessageDataTooLarge();\n error AmountPrecisionIncompatibility();\n error AmountTooBig();\n error AlreadyRelayed();\n\n ///////////////\n // Constants //\n ///////////////\n\n /// @dev The admin related contract roles\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n /// @dev The number of decimals that the base Fuel asset uses\n uint256 public constant FUEL_BASE_ASSET_DECIMALS = 9;\n uint256 public constant ETH_DECIMALS = 18;\n uint256 public constant PRECISION = 10 ** (ETH_DECIMALS - FUEL_BASE_ASSET_DECIMALS);\n\n /// @dev The max message data size in bytes\n uint256 public constant MAX_MESSAGE_DATA_SIZE = 2 ** 16;\n\n /// @dev Non-zero null value to optimize gas costs\n bytes32 internal constant NULL_MESSAGE_SENDER = 0x000000000000000000000000000000000000000000000000000000000000dead;\n\n /////////////\n // Storage //\n /////////////\n\n /// @notice Current message sender for other contracts to reference\n bytes32 internal _incomingMessageSender;\n\n /// @notice The Fuel chain state contract\n FuelChainState internal _fuelChainState;\n\n /// @notice Nonce for the next message to be sent\n uint256 internal _outgoingMessageNonce;\n\n /// @notice Mapping of message hash to boolean success value\n mapping(bytes32 => bool) internal _incomingMessageSuccessful;\n\n /////////////////////////////\n // Constructor/Initializer //\n /////////////////////////////\n\n /// @notice Constructor disables initialization for the implementation contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /// @notice Contract initializer to setup starting values\n /// @param fuelChainState Chain state contract\n function initialize(FuelChainState fuelChainState) public initializer {\n __Pausable_init();\n __AccessControl_init();\n __ReentrancyGuard_init();\n __UUPSUpgradeable_init();\n\n //grant initial roles\n _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _grantRole(PAUSER_ROLE, msg.sender);\n\n //chain state contract\n _fuelChainState = fuelChainState;\n\n //outgoing message data\n _outgoingMessageNonce = 0;\n\n //incoming message data\n _incomingMessageSender = NULL_MESSAGE_SENDER;\n }\n\n /////////////////////\n // Admin Functions //\n /////////////////////\n\n /// @notice Pause outbound messages\n function pause() external virtual onlyRole(PAUSER_ROLE) {\n _pause();\n }\n\n /// @notice Unpause outbound messages\n function unpause() external virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n _unpause();\n }\n\n //////////////////////\n // Public Functions //\n //////////////////////\n\n /// @notice Gets the number of decimals used in the Fuel base asset\n /// @return decimals of the Fuel base asset\n function fuelBaseAssetDecimals() public pure virtual returns (uint8) {\n return uint8(FUEL_BASE_ASSET_DECIMALS);\n }\n\n /// @notice Gets the set Fuel chain state contract\n /// @return fuel chain state contract\n function fuelChainStateContract() public view virtual returns (address) {\n return address(_fuelChainState);\n }\n\n function getNextOutgoingMessageNonce() public view virtual returns (uint256) {\n return _outgoingMessageNonce;\n }\n\n ///////////////////////////////////////\n // Incoming Message Public Functions //\n ///////////////////////////////////////\n\n /// @notice Relays a message published on Fuel from a given block\n /// @param message The message to relay\n /// @param rootBlockHeader The root block for proving chain history\n /// @param blockHeader The block containing the message\n /// @param blockInHistoryProof Proof that the message block exists in the history of the root block\n /// @param messageInBlockProof Proof that message exists in block\n /// @dev Made payable to reduce gas costs\n function relayMessage(\n Message calldata message,\n FuelBlockHeaderLite calldata rootBlockHeader,\n FuelBlockHeader calldata blockHeader,\n MerkleProof calldata blockInHistoryProof,\n MerkleProof calldata messageInBlockProof\n ) external payable virtual whenNotPaused {\n //verify root block header\n if (!_fuelChainState.finalized(rootBlockHeader.computeConsensusHeaderHash(), rootBlockHeader.height)) {\n revert UnfinalizedBlock();\n }\n\n //verify block in history\n if (\n !verifyBinaryTree(\n rootBlockHeader.prevRoot,\n abi.encodePacked(blockHeader.computeConsensusHeaderHash()),\n blockInHistoryProof.proof,\n blockInHistoryProof.key,\n rootBlockHeader.height\n )\n ) revert InvalidBlockInHistoryProof();\n\n //verify message in block\n bytes32 messageId = CryptographyLib.hash(\n abi.encodePacked(message.sender, message.recipient, message.nonce, message.amount, message.data)\n );\n if (\n !verifyBinaryTree(\n blockHeader.outputMessagesRoot,\n abi.encodePacked(messageId),\n messageInBlockProof.proof,\n messageInBlockProof.key,\n blockHeader.outputMessagesCount\n )\n ) revert InvalidMessageInBlockProof();\n\n //execute message\n _executeMessage(messageId, message);\n }\n\n /// @notice Gets if the given message ID has been relayed successfully\n /// @param messageId Message ID\n /// @return true if message has been relayed successfully\n function incomingMessageSuccessful(bytes32 messageId) public view virtual returns (bool) {\n return _incomingMessageSuccessful[messageId];\n }\n\n /// @notice Used by message receiving contracts to get the address on Fuel that sent the message\n /// @return sender the address of the sender on Fuel\n function messageSender() external view virtual returns (bytes32) {\n if (_incomingMessageSender == NULL_MESSAGE_SENDER) revert CurrentMessageSenderNotSet();\n return _incomingMessageSender;\n }\n\n ///////////////////////////////////////\n // Outgoing Message Public Functions //\n ///////////////////////////////////////\n\n /// @notice Send a message to a recipient on Fuel\n /// @param recipient The target message receiver address or predicate root\n /// @param data The message data to be sent to the receiver\n function sendMessage(bytes32 recipient, bytes calldata data) external payable virtual whenNotPaused {\n _sendOutgoingMessage(recipient, data);\n }\n\n /// @notice Send only ETH to the given recipient\n /// @param recipient The target message receiver\n function depositETH(bytes32 recipient) external payable virtual whenNotPaused {\n _sendOutgoingMessage(recipient, new bytes(0));\n }\n\n ////////////////////////\n // Internal Functions //\n ////////////////////////\n\n /// @notice Performs all necessary logic to send a message to a target on Fuel\n /// @param recipient The message receiver address or predicate root\n /// @param data The message data to be sent to the receiver\n function _sendOutgoingMessage(bytes32 recipient, bytes memory data) internal virtual {\n bytes32 sender = bytes32(uint256(uint160(msg.sender)));\n unchecked {\n //make sure data size is not too large\n if (data.length >= MAX_MESSAGE_DATA_SIZE) revert MessageDataTooLarge();\n\n //make sure amount fits into the Fuel base asset decimal level\n uint256 precision = 10 ** (ETH_DECIMALS - FUEL_BASE_ASSET_DECIMALS);\n uint256 amount = msg.value / precision;\n if (msg.value > 0) {\n if (amount * PRECISION != msg.value) revert AmountPrecisionIncompatibility();\n if (amount > type(uint64).max) revert AmountTooBig();\n }\n\n //emit message for Fuel clients to pickup (messageID calculated offchain)\n uint256 nonce = _outgoingMessageNonce;\n emit MessageSent(sender, recipient, nonce, uint64(amount), data);\n\n // increment nonce for next message\n _outgoingMessageNonce = nonce + 1;\n }\n }\n\n /// @notice Executes a message in the given header\n /// @param messageId The id of message to execute\n /// @param message The message to execute\n function _executeMessage(bytes32 messageId, Message calldata message) internal virtual nonReentrant {\n if (_incomingMessageSuccessful[messageId]) revert AlreadyRelayed();\n\n //set message sender for receiving contract to reference\n _incomingMessageSender = message.sender;\n\n (bool success, bytes memory result) = address(uint160(uint256(message.recipient))).call{\n value: message.amount * (10 ** (ETH_DECIMALS - FUEL_BASE_ASSET_DECIMALS))\n }(message.data);\n\n if (!success) {\n // Look for revert reason and bubble it up if present\n if (result.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(result)\n revert(add(32, result), returndata_size)\n }\n }\n revert(\"Message relay failed\");\n }\n\n //unset message sender reference\n _incomingMessageSender = NULL_MESSAGE_SENDER;\n\n //keep track of successfully relayed messages\n _incomingMessageSuccessful[messageId] = true;\n\n //emit event for successful message relay\n emit MessageRelayed(messageId, message.sender, message.recipient, message.amount);\n }\n\n /// @notice Executes a message in the given header\n // solhint-disable-next-line no-empty-blocks\n function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {\n //should revert if msg.sender is not authorized to upgrade the contract (currently only admin)\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" - }, - "contracts/fuelchain/FuelMessagePortal/v2/FuelMessagePortalV2.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport \"../../FuelMessagePortal.sol\";\n\n/// @custom:oz-upgrades-unsafe-allow constructor state-variable-immutable\ncontract FuelMessagePortalV2 is FuelMessagePortal {\n error GlobalDepositLimit();\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 public immutable depositLimitGlobal;\n\n uint256 public totalDeposited;\n\n constructor(uint256 _depositLimitGlobal) {\n /// @custom:oz-upgrades-unsafe-allow state-variable-assignment\n depositLimitGlobal = _depositLimitGlobal;\n }\n\n ////////////////////////\n // Internal Functions //\n ////////////////////////\n\n /// @notice Performs all necessary logic to send a message to a target on Fuel\n /// @param recipient The message receiver address or predicate root\n /// @param data The message data to be sent to the receiver\n function _sendOutgoingMessage(bytes32 recipient, bytes memory data) internal virtual override {\n bytes32 sender = bytes32(uint256(uint160(msg.sender)));\n unchecked {\n //make sure data size is not too large\n if (data.length >= MAX_MESSAGE_DATA_SIZE) revert MessageDataTooLarge();\n\n // v2: increase global deposited ether\n uint256 globalDepositedAmount = totalDeposited += msg.value;\n if (globalDepositedAmount > depositLimitGlobal) {\n revert GlobalDepositLimit();\n }\n\n //make sure amount fits into the Fuel base asset decimal level\n uint256 amount = msg.value / PRECISION;\n if (msg.value > 0) {\n if (amount * PRECISION != msg.value) revert AmountPrecisionIncompatibility();\n if (amount > type(uint64).max) revert AmountTooBig();\n }\n\n //emit message for Fuel clients to pickup (messageID calculated offchain)\n uint256 nonce = _outgoingMessageNonce;\n emit MessageSent(sender, recipient, nonce, uint64(amount), data);\n\n // increment nonce for next message\n _outgoingMessageNonce = nonce + 1;\n }\n }\n\n /// @notice Executes a message in the given header\n /// @param messageId The id of message to execute\n /// @param message The message to execute\n function _executeMessage(bytes32 messageId, Message calldata message) internal virtual override nonReentrant {\n if (_incomingMessageSuccessful[messageId]) revert AlreadyRelayed();\n\n //set message sender for receiving contract to reference\n _incomingMessageSender = message.sender;\n\n // v2: update accounting if the message carries an amount\n bool success;\n bytes memory result;\n if (message.amount > 0) {\n uint256 withdrawnAmount = message.amount * PRECISION;\n\n // Underflow check enabled since the amount is coded in `message`\n totalDeposited -= withdrawnAmount;\n\n (success, result) = address(uint160(uint256(message.recipient))).call{value: withdrawnAmount}(message.data);\n } else {\n (success, result) = address(uint160(uint256(message.recipient))).call(message.data);\n }\n\n if (!success) {\n // Look for revert reason and bubble it up if present\n if (result.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(result)\n revert(add(32, result), returndata_size)\n }\n }\n revert(\"Message relay failed\");\n }\n\n //unset message sender reference\n _incomingMessageSender = NULL_MESSAGE_SENDER;\n\n //keep track of successfully relayed messages\n _incomingMessageSuccessful[messageId] = true;\n\n //emit event for successful message relay\n emit MessageRelayed(messageId, message.sender, message.recipient, message.amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" - }, - "contracts/fuelchain/FuelMessagePortal/v3/FuelMessagePortalV3.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport \"../v2/FuelMessagePortalV2.sol\";\n\n/// @custom:oz-upgrades-unsafe-allow constructor state-variable-immutable\ncontract FuelMessagePortalV3 is FuelMessagePortalV2 {\n using FuelBlockHeaderLib for FuelBlockHeader;\n using FuelBlockHeaderLiteLib for FuelBlockHeaderLite;\n\n error MessageBlacklisted();\n error WithdrawalsPaused();\n\n bool public withdrawalsPaused;\n mapping(bytes32 => bool) public messageIsBlacklisted;\n\n constructor(uint256 _depositLimitGlobal) FuelMessagePortalV2(_depositLimitGlobal) {}\n\n function pauseWithdrawals() external payable onlyRole(PAUSER_ROLE) {\n withdrawalsPaused = true;\n }\n\n function unpauseWithdrawals() external payable onlyRole(PAUSER_ROLE) {\n withdrawalsPaused = false;\n }\n\n function setMessageBlacklist(bytes32 messageId, bool value) external payable onlyRole(PAUSER_ROLE) {\n messageIsBlacklisted[messageId] = value;\n }\n\n ///////////////////////////////////////\n // Incoming Message Public Functions //\n ///////////////////////////////////////\n\n /// @notice Relays a message published on Fuel from a given block\n /// @param message The message to relay\n /// @param rootBlockHeader The root block for proving chain history\n /// @param blockHeader The block containing the message\n /// @param blockInHistoryProof Proof that the message block exists in the history of the root block\n /// @param messageInBlockProof Proof that message exists in block\n /// @dev Made payable to reduce gas costs\n function relayMessage(\n Message calldata message,\n FuelBlockHeaderLite calldata rootBlockHeader,\n FuelBlockHeader calldata blockHeader,\n MerkleProof calldata blockInHistoryProof,\n MerkleProof calldata messageInBlockProof\n ) external payable virtual override whenNotPaused {\n if (withdrawalsPaused) {\n revert WithdrawalsPaused();\n }\n\n //verify root block header\n if (!_fuelChainState.finalized(rootBlockHeader.computeConsensusHeaderHash(), rootBlockHeader.height)) {\n revert UnfinalizedBlock();\n }\n\n //verify block in history\n if (\n !verifyBinaryTree(\n rootBlockHeader.prevRoot,\n abi.encodePacked(blockHeader.computeConsensusHeaderHash()),\n blockInHistoryProof.proof,\n blockInHistoryProof.key,\n rootBlockHeader.height\n )\n ) revert InvalidBlockInHistoryProof();\n\n //verify message in block\n bytes32 messageId = CryptographyLib.hash(\n abi.encodePacked(message.sender, message.recipient, message.nonce, message.amount, message.data)\n );\n\n if (messageIsBlacklisted[messageId]) {\n revert MessageBlacklisted();\n }\n\n if (\n !verifyBinaryTree(\n blockHeader.outputMessagesRoot,\n abi.encodePacked(messageId),\n messageInBlockProof.proof,\n messageInBlockProof.key,\n blockHeader.outputMessagesCount\n )\n ) revert InvalidMessageInBlockProof();\n\n //execute message\n _executeMessage(messageId, message);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" - }, - "contracts/fuelchain/types/FuelBlockHeader.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {CryptographyLib} from \"../../lib/Cryptography.sol\";\n\n/// @title Fuel Chain Block Header\n/// @dev The Fuel chain block header structure\nstruct FuelBlockHeader {\n ///////////////\n // Consensus //\n ///////////////\n // Merkle root of all previous consensus header hashes (not including this block)\n bytes32 prevRoot;\n // Height of this block\n uint32 height;\n // Time this block was created, in TAI64 format\n uint64 timestamp;\n /////////////////\n // Application //\n /////////////////\n //Height of the data availability layer up to which (inclusive) input messages are processed\n uint64 daHeight;\n // Number of transactions in this block\n uint64 txCount;\n // Number of output messages in this block\n uint64 outputMessagesCount;\n // Merkle root of transactions in this block\n bytes32 txRoot;\n // Merkle root of output messages in this block\n bytes32 outputMessagesRoot;\n}\n\n/// @title Block Header Library\n/// @dev Provides useful functions for dealing with Fuel blocks\nlibrary FuelBlockHeaderLib {\n /////////////\n // Methods //\n /////////////\n\n /// @notice Serialize a block application header.\n /// @param header The block header structure.\n /// @return The serialized block application header.\n function serializeApplicationHeader(FuelBlockHeader memory header) internal pure returns (bytes memory) {\n return\n abi.encodePacked(\n header.daHeight,\n header.txCount,\n header.outputMessagesCount,\n header.txRoot,\n header.outputMessagesRoot\n );\n }\n\n /// @notice Produce the block application header hash.\n /// @param header The block header structure.\n /// @return The block application header hash.\n function computeApplicationHeaderHash(FuelBlockHeader memory header) internal pure returns (bytes32) {\n return CryptographyLib.hash(serializeApplicationHeader(header));\n }\n\n /// @notice Serialize a block consensus header.\n /// @param header The block header structure.\n /// @return The serialized block consensus header.\n function serializeConsensusHeader(FuelBlockHeader memory header) internal pure returns (bytes memory) {\n return abi.encodePacked(header.prevRoot, header.height, header.timestamp, computeApplicationHeaderHash(header));\n }\n\n /// @notice Produce the block consensus header hash.\n /// @param header The block header structure.\n /// @return The block consensus header hash.\n function computeConsensusHeaderHash(FuelBlockHeader memory header) internal pure returns (bytes32) {\n return CryptographyLib.hash(serializeConsensusHeader(header));\n }\n}\n" - }, - "contracts/fuelchain/types/FuelBlockHeaderLite.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {CryptographyLib} from \"../../lib/Cryptography.sol\";\n\n/// @title Lightweight Fuel Chain Block Header\n/// @dev The Fuel chain block header structure with just a hash of the application header\nstruct FuelBlockHeaderLite {\n // Merkle root of all previous consensus header hashes (not including this block)\n bytes32 prevRoot;\n // Height of this block\n uint32 height;\n // Time this block was created, in TAI64 format\n uint64 timestamp;\n // Hash of serialized application header for this block\n bytes32 applicationHash;\n}\n\n/// @title Block Header Library\n/// @dev Provides useful functions for dealing with Fuel blocks\nlibrary FuelBlockHeaderLiteLib {\n /////////////\n // Methods //\n /////////////\n\n /// @notice Serialize a block consensus header.\n /// @param header The block header structure.\n /// @return The serialized block consensus header.\n function serializeConsensusHeader(FuelBlockHeaderLite memory header) internal pure returns (bytes memory) {\n return abi.encodePacked(header.prevRoot, (uint32)(header.height), header.timestamp, header.applicationHash);\n }\n\n /// @notice Produce the block consensus header hash.\n /// @param header The block header structure.\n /// @return The block consensus header hash.\n function computeConsensusHeaderHash(FuelBlockHeaderLite memory header) internal pure returns (bytes32) {\n return CryptographyLib.hash(serializeConsensusHeader(header));\n }\n}\n" - }, - "contracts/lib/CommonPredicates.sol": { - "content": "// SPDX-License-Identifier: Apache 2.0\n\npragma solidity 0.8.9;\n\n/// @notice Common predicates for Fuel inputs\nlibrary CommonPredicates {\n bytes32 public constant CONTRACT_MESSAGE_PREDICATE =\n 0xb12658c759d8bae2cdc523ebd7aa8637912f32b1763d242ad3618448057b79cd;\n}\n" - }, - "contracts/lib/Cryptography.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\n/// @notice This is the Fuel protocol cryptography library.\nlibrary CryptographyLib {\n /////////////\n // Methods //\n /////////////\n\n // secp256k1n / 2\n uint256 private constant MAX_SIGNATURE_S_VALUE = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0;\n\n /// @notice The primary hash method for Fuel.\n /// @param data The bytes input data.\n /// @return The returned hash result.\n function hash(bytes memory data) internal pure returns (bytes32) {\n return sha256(data);\n }\n\n function addressFromSignatureComponents(\n uint8 v,\n bytes32 r,\n bytes32 s,\n bytes32 message\n ) internal pure returns (address) {\n // reject high s values to prevent signature malleability\n // https://eips.ethereum.org/EIPS/eip-2\n require(uint256(s) <= MAX_SIGNATURE_S_VALUE, \"signature-invalid-s\");\n\n address signer = ecrecover(message, v, r, s);\n require(signer != address(0), \"signature-invalid\");\n\n return signer;\n }\n\n /// @notice Get the signing address from a signature and the signed data\n /// @param signature: The compact (64 byte) ECDSA signature\n /// @param message: The message which was signed over\n /// @return : The address of the signer, or address(0) in case of an error\n function addressFromSignature(bytes memory signature, bytes32 message) internal pure returns (address) {\n // ECDSA signatures must be 64 bytes (https://eips.ethereum.org/EIPS/eip-2098)\n require(signature.length == 64, \"signature-invalid-length\");\n\n // Signature is concatenation of r and v-s, both 32 bytes\n // https://github.com/celestiaorg/celestia-specs/blob/ec98170398dfc6394423ee79b00b71038879e211/src/specs/data_structures.md#signature\n bytes32 vs;\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n (r, vs) = abi.decode(signature, (bytes32, bytes32));\n\n // v is first bit of vs as uint8\n // yParity parameter is always either 0 or 1 (canonically the values used have been 27 and 28), so adjust accordingly\n v = 27 + uint8(uint256(vs) & (1 << 255) > 0 ? 1 : 0);\n\n // s is vs with first bit replaced by a 0\n s = bytes32((uint256(vs) << 1) >> 1);\n\n return addressFromSignatureComponents(v, r, s, message);\n }\n}\n" - }, - "contracts/messaging/FuelMessagesEnabled.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport {FuelMessagePortal} from \"../fuelchain/FuelMessagePortal.sol\";\n\n/// @title FuelMessagesEnabled\n/// @notice Helper contract for contracts sending and receiving messages from Fuel\nabstract contract FuelMessagesEnabled {\n ////////////\n // Errors //\n ////////////\n\n error CallerIsNotPortal();\n error InvalidMessageSender();\n\n /////////////\n // Storage //\n /////////////\n\n /// @notice FuelMessagePortal contract used to send and receive messages from Fuel\n FuelMessagePortal internal _fuelMessagePortal;\n\n ////////////////////////\n // Function Modifiers //\n ////////////////////////\n\n /// @notice Enforces that the modified function is only callable by the Fuel message portal\n modifier onlyFromPortal() {\n if (msg.sender != address(_fuelMessagePortal)) revert CallerIsNotPortal();\n _;\n }\n\n /// @notice Enforces that the modified function is only callable by the portal and a specific Fuel account\n /// @param fuelSender The only sender on Fuel which is authenticated to call this function\n modifier onlyFromFuelSender(bytes32 fuelSender) {\n if (msg.sender != address(_fuelMessagePortal)) revert CallerIsNotPortal();\n if (_fuelMessagePortal.messageSender() != fuelSender) revert InvalidMessageSender();\n _;\n }\n\n //////////////////////\n // Public Functions //\n //////////////////////\n\n /// @notice Gets the currently set message portal address\n /// @return fuelMessagePortal Fuel message portal address\n function fuelMessagePortal() public view returns (address) {\n return address(_fuelMessagePortal);\n }\n\n ////////////////////////\n // Internal Functions //\n ////////////////////////\n\n /// @notice Send a message to a recipient on Fuel\n /// @param recipient The message receiver address or predicate root\n /// @param data The message data to be sent to the receiver\n function sendMessage(bytes32 recipient, bytes memory data) internal {\n _fuelMessagePortal.sendMessage(recipient, data);\n }\n\n /// @notice Send a message to a recipient on Fuel\n /// @param recipient The message receiver address or predicate root\n /// @param amount The amount of ETH to send with message\n /// @param data The message data to be sent to the receiver\n function sendMessage(bytes32 recipient, uint256 amount, bytes memory data) internal {\n _fuelMessagePortal.sendMessage{value: amount}(recipient, data);\n }\n\n /// @notice Used by message receiving contracts to get the address on Fuel that sent the message\n function messageSender() internal view returns (bytes32) {\n return _fuelMessagePortal.messageSender();\n }\n}\n" - }, - "contracts/messaging/FuelMessagesEnabledUpgradeable.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {FuelMessagePortal} from \"../fuelchain/FuelMessagePortal.sol\";\nimport {FuelMessagesEnabled} from \"./FuelMessagesEnabled.sol\";\n\n/// @title FuelMessagesEnabledUpgradeable\n/// @notice Helper contract for contracts sending and receiving messages from Fuel\nabstract contract FuelMessagesEnabledUpgradeable is Initializable, FuelMessagesEnabled {\n /////////////////\n // Initializer //\n /////////////////\n\n /// @dev Initializes the contract\n // solhint-disable-next-line func-name-mixedcase\n function __FuelMessagesEnabled_init(FuelMessagePortal fuelMessagePortal) internal onlyInitializing {\n __FuelMessagesEnabled_init_unchained(fuelMessagePortal);\n }\n\n // solhint-disable-next-line func-name-mixedcase\n function __FuelMessagesEnabled_init_unchained(FuelMessagePortal fuelMessagePortal) internal onlyInitializing {\n _fuelMessagePortal = fuelMessagePortal;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" - }, - "contracts/messaging/gateway/FuelBridgeBase.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nabstract contract FuelBridgeBase {\n /// @notice Finalizes the withdrawal process from the Fuel side gateway contract\n /// @param to Account to send withdrawn tokens to\n /// @param tokenAddress Address of the token being withdrawn from Fuel\n /// @param amount Amount of tokens to withdraw\n /// @param tokenId Discriminator for ERC721 / ERC1155 tokens. For ERC20, it must be 0\n /// @dev Made payable to reduce gas costs\n function finalizeWithdrawal(\n address to,\n address tokenAddress,\n uint256 amount,\n uint256 tokenId\n ) external payable virtual;\n}\n" - }, - "contracts/messaging/gateway/FuelERC20Gateway.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {AccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {FuelBridgeBase} from \"./FuelBridgeBase.sol\";\nimport {FuelMessagePortal, CommonPredicates} from \"../../fuelchain/FuelMessagePortal.sol\";\nimport {FuelMessagesEnabledUpgradeable} from \"../FuelMessagesEnabledUpgradeable.sol\";\n\n/// @title FuelERC20Gateway\n/// @notice The L1 side of the general ERC20 gateway with Fuel\n/// @dev This contract can be used as a template for future gateways to Fuel\ncontract FuelERC20Gateway is\n Initializable,\n FuelBridgeBase,\n FuelMessagesEnabledUpgradeable,\n PausableUpgradeable,\n AccessControlUpgradeable,\n UUPSUpgradeable\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n ////////////\n // Events //\n ////////////\n\n /// @dev Emitted when tokens are deposited from Ethereum to Fuel\n event Deposit(bytes32 indexed sender, address indexed tokenAddress, bytes32 indexed fuelContractId, uint256 amount);\n\n /// @dev Emitted when tokens are withdrawn from Fuel to Ethereum\n event Withdrawal(\n bytes32 indexed recipient,\n address indexed tokenAddress,\n bytes32 indexed fuelContractId,\n uint256 amount\n );\n\n ///////////////\n // Constants //\n ///////////////\n\n /// @dev The admin related contract roles\n bytes1 public constant DEPOSIT_TO_CONTRACT = bytes1(keccak256(\"DEPOSIT_TO_CONTRACT\"));\n\n /// @dev The admin related contract roles\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n /////////////\n // Storage //\n /////////////\n\n /// @notice Maps ERC20 tokens to Fuel tokens to balance of the ERC20 tokens deposited\n mapping(address => mapping(bytes32 => uint256)) internal _deposits;\n\n /////////////////////////////\n // Constructor/Initializer //\n /////////////////////////////\n\n /// @notice Constructor disables initialization for the implementation contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /// @notice Contract initializer to setup starting values\n /// @param fuelMessagePortal The FuelMessagePortal contract\n function initialize(FuelMessagePortal fuelMessagePortal) public initializer {\n __FuelMessagesEnabled_init(fuelMessagePortal);\n __Pausable_init();\n __AccessControl_init();\n __UUPSUpgradeable_init();\n\n //grant initial roles\n _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _grantRole(PAUSER_ROLE, msg.sender);\n }\n\n /////////////////////\n // Admin Functions //\n /////////////////////\n\n /// @notice Pause ERC20 transfers\n function pause() external onlyRole(PAUSER_ROLE) {\n _pause();\n }\n\n /// @notice Unpause ERC20 transfers\n function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) {\n _unpause();\n }\n\n //////////////////////\n // Public Functions //\n //////////////////////\n\n /// @notice Gets the amount of tokens deposited to a corresponding token on Fuel\n /// @param tokenAddress ERC-20 token address\n /// @param fuelContractId ID of the corresponding token on Fuel\n /// @return amount of tokens deposited\n function tokensDeposited(address tokenAddress, bytes32 fuelContractId) public view virtual returns (uint256) {\n return _deposits[tokenAddress][fuelContractId];\n }\n\n /// @notice Deposits the given tokens to an account on Fuel\n /// @param to Fuel address to deposit tokens to\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param amount Amount of tokens to deposit\n /// @dev Made payable to reduce gas costs\n function deposit(\n bytes32 to,\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 amount\n ) external payable virtual whenNotPaused {\n bytes memory messageData = abi.encodePacked(\n fuelContractId,\n bytes32(uint256(uint160(tokenAddress))), // OFFSET_TOKEN_ADDRESS = 32\n bytes32(0), // OFFSET_TOKEN_ID = 64\n bytes32(uint256(uint160(msg.sender))), //from, OFFSET_FROM = 96\n to, // OFFSET_TO = 128\n amount // OFFSET_AMOUNT = 160\n );\n _deposit(tokenAddress, fuelContractId, amount, messageData);\n }\n\n /// @notice Deposits the given tokens to a contract on Fuel with optional data\n /// @param to Fuel account or contract to deposit tokens to\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param amount Amount of tokens to deposit\n /// @param data Optional data to send with the deposit\n /// @dev Made payable to reduce gas costs\n function depositWithData(\n bytes32 to,\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 amount,\n bytes calldata data\n ) external payable virtual whenNotPaused {\n bytes memory messageData = abi.encodePacked(\n fuelContractId,\n bytes32(uint256(uint160(tokenAddress))), // OFFSET_TOKEN_ADDRESS = 32\n bytes32(0), // OFFSET_TOKEN_ID = 64\n bytes32(uint256(uint160(msg.sender))), //from, OFFSET_FROM = 96\n to, // OFFSET_TO = 128\n amount, // OFFSET_AMOUNT = 160\n DEPOSIT_TO_CONTRACT, // OFFSET_ROLE = 161\n data\n );\n _deposit(tokenAddress, fuelContractId, amount, messageData);\n }\n\n /// @notice Finalizes the withdrawal process from the Fuel side gateway contract\n /// @param to Account to send withdrawn tokens to\n /// @param tokenAddress Address of the token being withdrawn from Fuel\n /// @param amount Amount of tokens to withdraw\n /// @param tokenId Discriminator for ERC721 / ERC1155 tokens. For ERC20, it must be 0\n /// @dev Made payable to reduce gas costs\n function finalizeWithdrawal(\n address to,\n address tokenAddress,\n uint256 amount,\n uint256 tokenId\n ) external payable virtual override whenNotPaused onlyFromPortal {\n require(amount > 0, \"Cannot withdraw zero\");\n require(tokenId == 0, \"Fungible tokens cannot have a tokenId\");\n bytes32 fuelContractId = messageSender();\n\n //reduce deposit balance and transfer tokens (math will underflow if amount is larger than allowed)\n _deposits[tokenAddress][fuelContractId] = _deposits[tokenAddress][fuelContractId] - amount;\n IERC20Upgradeable(tokenAddress).safeTransfer(to, amount);\n\n //emit event for successful token withdraw\n emit Withdrawal(bytes32(uint256(uint160(to))), tokenAddress, fuelContractId, amount);\n }\n\n /// @notice Allows the admin to rescue ETH sent to this contract by accident\n /// @dev Made payable to reduce gas costs\n function rescueETH() external payable virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n (bool success, ) = address(msg.sender).call{value: address(this).balance}(\"\");\n require(success);\n }\n\n ////////////////////////\n // Internal Functions //\n ////////////////////////\n\n /// @notice Deposits the given tokens to an account or contract on Fuel\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param amount Amount of tokens to deposit\n /// @param messageData The data of the message to send for deposit\n function _deposit(\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 amount,\n bytes memory messageData\n ) internal virtual {\n require(amount > 0, \"Cannot deposit zero\");\n\n //transfer tokens to this contract and update deposit balance\n IERC20Upgradeable(tokenAddress).safeTransferFrom(msg.sender, address(this), amount);\n _deposits[tokenAddress][fuelContractId] = _deposits[tokenAddress][fuelContractId] + amount;\n\n //send message to gateway on Fuel to finalize the deposit\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, messageData);\n\n //emit event for successful token deposit\n emit Deposit(bytes32(uint256(uint160(msg.sender))), tokenAddress, fuelContractId, amount);\n }\n\n /// @notice Executes a message in the given header\n // solhint-disable-next-line no-empty-blocks\n function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {\n //should revert if msg.sender is not authorized to upgrade the contract (currently only owner)\n }\n}\n" - }, - "contracts/messaging/gateway/FuelERC20Gateway/FuelERC20GatewayV4.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {AccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {FuelERC20GatewayV3} from \"../v3/FuelERC20GatewayV3.sol\";\nimport {CommonPredicates} from \"../../../lib/CommonPredicates.sol\";\nimport {FuelMessagePortal} from \"../../../fuelchain/FuelMessagePortal.sol\";\nimport {FuelBridgeBase} from \"../FuelBridgeBase.sol\";\nimport {FuelMessagesEnabledUpgradeable} from \"../../FuelMessagesEnabledUpgradeable.sol\";\n\n/// @title FuelERC20GatewayV4\n/// @notice The L1 side of the general ERC20 gateway with Fuel. Not backwards compatible with previous implementations\n\ncontract FuelERC20GatewayV4 is\n Initializable,\n FuelBridgeBase,\n FuelMessagesEnabledUpgradeable,\n PausableUpgradeable,\n AccessControlUpgradeable,\n UUPSUpgradeable\n{\n using SafeERC20Upgradeable for IERC20MetadataUpgradeable;\n\n ////////////\n // Types //\n ////////////\n error BridgeFull();\n error GlobalDepositLimit();\n error CannotDepositZero();\n error CannotWithdrawZero();\n error InvalidSender();\n error InvalidAmount();\n\n /// @dev Emitted when tokens are deposited from Ethereum to Fuel\n event Deposit(bytes32 indexed sender, address indexed tokenAddress, uint256 amount);\n\n /// @dev Emitted when tokens are withdrawn from Fuel to Ethereum\n event Withdrawal(bytes32 indexed recipient, address indexed tokenAddress, uint256 amount);\n\n enum MessageType {\n DEPOSIT,\n METADATA\n }\n\n ///////////////\n // Constants //\n ///////////////\n\n bytes1 public constant DEPOSIT_TO_CONTRACT = bytes1(keccak256(\"DEPOSIT_TO_CONTRACT\"));\n\n /// @dev The admin related contract roles\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n uint256 public constant FUEL_ASSET_DECIMALS = 9;\n uint256 constant NO_DECIMALS = type(uint256).max;\n\n /////////////\n // Storage //\n /////////////\n\n bool public whitelistRequired;\n bytes32 public assetIssuerId;\n\n mapping(address => uint256) internal _deposits;\n mapping(address => uint256) internal _depositLimits;\n mapping(address => uint256) internal _decimalsCache;\n mapping(bytes32 => bool) internal _isBridge;\n\n /// @notice Contract initializer to setup starting values\n /// @param fuelMessagePortal The FuelMessagePortal contract\n function initialize(FuelMessagePortal fuelMessagePortal) public initializer {\n __FuelMessagesEnabled_init(fuelMessagePortal);\n __Pausable_init();\n __AccessControl_init();\n __UUPSUpgradeable_init();\n\n //grant initial roles\n _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _grantRole(PAUSER_ROLE, msg.sender);\n }\n\n /////////////////////\n // Admin Functions //\n /////////////////////\n\n /// @notice Pause ERC20 transfers\n function pause() external onlyRole(PAUSER_ROLE) {\n _pause();\n }\n\n /// @notice Unpause ERC20 transfers\n function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) {\n _unpause();\n }\n\n /// @notice sets the entity on L2 that will mint the tokens\n function setAssetIssuerId(bytes32 id) external payable virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n assetIssuerId = id;\n }\n\n /// @notice if enabled, only deposits for tokens allowed through `setGlobalDepositLimit` will be allowed\n function requireWhitelist(bool value) external onlyRole(DEFAULT_ADMIN_ROLE) {\n whitelistRequired = value;\n }\n\n /// @notice see `requireWhitelist`\n function setGlobalDepositLimit(address token, uint256 limit) external payable virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n _depositLimits[token] = limit;\n }\n\n /// @notice Allows the admin to rescue ETH sent to this contract by accident\n /// @dev Made payable to reduce gas costs\n function rescueETH() external payable virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n (bool success, ) = address(msg.sender).call{value: address(this).balance}(\"\");\n require(success);\n }\n\n //////////////////////\n // Public Functions //\n //////////////////////\n\n /// @notice Gets the amount of tokens deposited to a corresponding token on Fuel\n /// @param tokenAddress ERC-20 token address\n /// @return amount of tokens deposited\n function tokensDeposited(address tokenAddress) public view virtual returns (uint256) {\n return _deposits[tokenAddress];\n }\n\n /// @notice Gets the amount of tokens deposited to a corresponding token on Fuel\n /// @param tokenAddress ERC-20 token address\n /// @return amount of tokens deposited\n function depositLimits(address tokenAddress) public view virtual returns (uint256) {\n return _deposits[tokenAddress];\n }\n\n /// @notice Deposits the given tokens to an account on Fuel\n /// @param to Fuel address to deposit tokens to\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param amount Amount of tokens to deposit\n /// @dev Made payable to reduce gas costs\n function deposit(bytes32 to, address tokenAddress, uint256 amount) external payable virtual whenNotPaused {\n uint8 decimals = _getTokenDecimals(tokenAddress);\n\n bytes memory messageData = abi.encodePacked(\n MessageType.DEPOSIT,\n assetIssuerId,\n bytes32(uint256(uint160(tokenAddress))),\n bytes32(0),\n bytes32(uint256(uint160(msg.sender))),\n to,\n amount,\n decimals\n );\n _deposit(tokenAddress, amount, messageData);\n }\n\n /// @notice Deposits the given tokens to a contract on Fuel with optional data\n /// @param to Fuel account or contract to deposit tokens to\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param amount Amount of tokens to deposit\n /// @param data Optional data to send with the deposit\n /// @dev Made payable to reduce gas costs\n function depositWithData(\n bytes32 to,\n address tokenAddress,\n uint256 amount,\n bytes calldata data\n ) external payable virtual whenNotPaused {\n uint8 decimals = _getTokenDecimals(tokenAddress);\n\n bytes memory messageData = abi.encodePacked(\n MessageType.DEPOSIT,\n assetIssuerId,\n bytes32(uint256(uint160(tokenAddress))),\n bytes32(0),\n bytes32(uint256(uint160(msg.sender))),\n to,\n amount,\n decimals,\n DEPOSIT_TO_CONTRACT,\n data\n );\n _deposit(tokenAddress, amount, messageData);\n }\n\n function sendMetadata(address tokenAddress) external payable virtual whenNotPaused {\n bytes memory messageData = abi.encodePacked(\n MessageType.METADATA,\n abi.encode(IERC20MetadataUpgradeable(tokenAddress).symbol(), IERC20MetadataUpgradeable(tokenAddress).name())\n );\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, messageData);\n }\n\n /// @notice Deposits the given tokens to an account or contract on Fuel\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param amount Amount of tokens to deposit\n /// @param messageData The data of the message to send for deposit\n function _deposit(address tokenAddress, uint256 amount, bytes memory messageData) internal virtual {\n ////////////\n // Checks //\n ////////////\n if (amount == 0) revert CannotDepositZero();\n if (amount > uint256(type(uint64).max)) revert CannotDepositZero();\n\n /////////////\n // Effects //\n /////////////\n uint256 updatedDeposits = _deposits[tokenAddress] + amount;\n if (updatedDeposits > type(uint64).max) revert BridgeFull();\n\n if (whitelistRequired && updatedDeposits > _depositLimits[tokenAddress]) {\n revert GlobalDepositLimit();\n }\n\n _deposits[tokenAddress] = updatedDeposits;\n\n /////////////\n // Actions //\n /////////////\n //send message to gateway on Fuel to finalize the deposit\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, messageData);\n\n //transfer tokens to this contract and update deposit balance\n IERC20MetadataUpgradeable(tokenAddress).safeTransferFrom(msg.sender, address(this), amount);\n\n //emit event for successful token deposit\n emit Deposit(bytes32(uint256(uint160(msg.sender))), tokenAddress, amount);\n }\n\n /// @notice Finalizes the withdrawal process from the Fuel side gateway contract\n /// @param to Account to send withdrawn tokens to\n /// @param tokenAddress Address of the token being withdrawn from Fuel\n /// @param amount Amount of tokens to withdraw\n /// @dev Made payable to reduce gas costs\n function finalizeWithdrawal(\n address to,\n address tokenAddress,\n uint256 amount,\n uint256\n ) external payable virtual override whenNotPaused onlyFromPortal {\n if (amount == 0) {\n revert CannotWithdrawZero();\n }\n\n if (messageSender() != assetIssuerId) {\n revert InvalidSender();\n }\n\n //reduce deposit balance and transfer tokens (math will underflow if amount is larger than allowed)\n _deposits[tokenAddress] = _deposits[tokenAddress] - amount;\n IERC20MetadataUpgradeable(tokenAddress).safeTransfer(to, amount);\n\n //emit event for successful token withdraw\n emit Withdrawal(bytes32(uint256(uint160(to))), tokenAddress, amount);\n }\n\n function _getTokenDecimals(address tokenAddress) internal virtual returns (uint8) {\n uint256 decimals = _decimalsCache[tokenAddress];\n\n if (decimals == 0) {\n try IERC20MetadataUpgradeable(tokenAddress).decimals() returns (uint8 returnedDecimals) {\n _decimalsCache[tokenAddress] = returnedDecimals == 0 ? NO_DECIMALS : returnedDecimals;\n return returnedDecimals;\n } catch {\n _decimalsCache[tokenAddress] == NO_DECIMALS;\n return 0;\n }\n }\n\n if (decimals == NO_DECIMALS) return 0;\n return uint8(decimals);\n }\n\n function _adjustDecimals(uint8 tokenDecimals, uint256 amount) internal virtual returns (uint256) {\n // Most common case: 18 decimals\n unchecked {\n if (tokenDecimals > 9) {\n uint256 precision = 10 ** (tokenDecimals - 9);\n if (amount % precision != 0) {\n revert InvalidAmount();\n }\n return divByNonZero(amount, precision);\n }\n }\n\n // Next most common case: less than 9 decimals\n if (tokenDecimals < 9) {\n return amount * (10 ** (9 - tokenDecimals));\n }\n\n // Less common case: 9 decimals\n return amount;\n }\n\n function divByNonZero(uint256 _num, uint256 _div) internal pure returns (uint256 result) {\n assembly {\n result := div(_num, _div)\n }\n }\n\n /// @notice Executes a message in the given header\n // solhint-disable-next-line no-empty-blocks\n function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {\n //should revert if msg.sender is not authorized to upgrade the contract (currently only owner)\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" - }, - "contracts/messaging/gateway/FuelERC721Gateway.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {AccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {IERC721Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\";\nimport {FuelBridgeBase} from \"./FuelBridgeBase.sol\";\nimport {FuelMessagePortal, CommonPredicates} from \"../../fuelchain/FuelMessagePortal.sol\";\nimport {FuelMessagesEnabledUpgradeable} from \"../FuelMessagesEnabledUpgradeable.sol\";\n\nimport \"hardhat/console.sol\";\n\n/// @title FuelERC721Gateway\n/// @notice The L1 side of the general ERC721 gateway with Fuel\n/// @dev This contract can be used as a template for future gateways to Fuel\ncontract FuelERC721Gateway is\n Initializable,\n FuelBridgeBase,\n FuelMessagesEnabledUpgradeable,\n PausableUpgradeable,\n AccessControlUpgradeable,\n UUPSUpgradeable\n{\n ////////////\n // Events //\n ////////////\n\n /// @dev Emitted when tokens are deposited from Ethereum to Fuel\n event Deposit(\n bytes32 indexed sender,\n address indexed tokenAddress,\n bytes32 indexed fuelContractId,\n uint256 tokenId\n );\n\n /// @dev Emitted when tokens are withdrawn from Fuel to Ethereum\n event Withdrawal(\n bytes32 indexed recipient,\n address indexed tokenAddress,\n bytes32 indexed fuelContractId,\n uint256 tokenId\n );\n\n ///////////////\n // Constants //\n ///////////////\n\n /// @dev The admin related contract roles\n bytes1 public constant DEPOSIT_TO_CONTRACT = bytes1(keccak256(\"DEPOSIT_TO_CONTRACT\"));\n\n /// @dev The admin related contract roles\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n /////////////\n // Storage //\n /////////////\n\n /// @notice Maps ERC721 tokens to its fuel bridge counterpart\n mapping(address => mapping(uint256 => bytes32)) internal _deposits;\n\n /////////////////////////////\n // Constructor/Initializer //\n /////////////////////////////\n\n /// @notice Constructor disables initialization for the implementation contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /// @notice Contract initializer to setup starting values\n /// @param fuelMessagePortal The FuelMessagePortal contract\n function initialize(FuelMessagePortal fuelMessagePortal) public initializer {\n __FuelMessagesEnabled_init(fuelMessagePortal);\n __Pausable_init();\n __AccessControl_init();\n __UUPSUpgradeable_init();\n\n //grant initial roles\n _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _grantRole(PAUSER_ROLE, msg.sender);\n }\n\n /////////////////////\n // Admin Functions //\n /////////////////////\n\n /// @notice Pause ERC721 transfers\n function pause() external onlyRole(PAUSER_ROLE) {\n _pause();\n }\n\n /// @notice Unpause ERC721 transfers\n function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) {\n _unpause();\n }\n\n //////////////////////\n // Public Functions //\n //////////////////////\n\n /// @notice Gets the FuelContractId of an ERC-721 token\n /// @param tokenAddress ERC-721 token address\n /// @param tokenId tokenId\n /// @return fuelContractId ID of the Fuel contract\n function tokensDeposited(address tokenAddress, uint256 tokenId) public view returns (bytes32) {\n return _deposits[tokenAddress][tokenId];\n }\n\n /// @notice Deposits the given tokens to an account on Fuel\n /// @param to Fuel address to deposit tokens to\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param tokenId tokenId to deposit\n /// @dev Made payable to reduce gas costs\n function deposit(\n bytes32 to,\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 tokenId\n ) external payable whenNotPaused {\n bytes memory messageData = abi.encodePacked(\n fuelContractId,\n bytes32(uint256(uint160(tokenAddress))), // OFFSET_TOKEN_ADDRESS = 32\n tokenId,\n bytes32(uint256(uint160(msg.sender))), //from, OFFSET_FROM = 96\n to, // OFFSET_TO = 128\n uint256(1) // OFFSET_AMOUNT = 160\n );\n _deposit(tokenAddress, fuelContractId, tokenId, messageData);\n }\n\n /// @notice Deposits the given tokens to a contract on Fuel with optional data\n /// @param to Fuel account or contract to deposit tokens to\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param tokenId tokenId to deposit\n /// @param data Optional data to send with the deposit\n /// @dev Made payable to reduce gas costs\n function depositWithData(\n bytes32 to,\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 tokenId,\n bytes calldata data\n ) external payable whenNotPaused {\n bytes memory messageData = abi.encodePacked(\n fuelContractId,\n bytes32(uint256(uint160(tokenAddress))), // OFFSET_TOKEN_ADDRESS = 32\n tokenId, // OFFSET_TOKEN_ID = 64\n bytes32(uint256(uint160(msg.sender))), //from, OFFSET_FROM = 96\n to, // OFFSET_TO = 128\n uint256(1), // OFFSET_AMOUNT = 160\n DEPOSIT_TO_CONTRACT, // OFFSET_ROLE = 161\n data\n );\n _deposit(tokenAddress, fuelContractId, tokenId, messageData);\n }\n\n /// @notice Finalizes the withdrawal process from the Fuel side gateway contract\n /// @param to Account to send withdrawn tokens to\n /// @param tokenAddress Address of the token being withdrawn from Fuel\n /// @param tokenId Discriminator for ERC721 / ERC1155 tokens\n /// @dev Made payable to reduce gas costs.\n /// @dev Could remove the amount param to further reduce cost, but that implies changes in the Fuel contract\n function finalizeWithdrawal(\n address to,\n address tokenAddress,\n uint256 /*amount*/,\n uint256 tokenId\n ) external payable override whenNotPaused onlyFromPortal {\n bytes32 fuelContractId = messageSender();\n require(_deposits[tokenAddress][tokenId] == fuelContractId, \"Fuel bridge does not own this token\");\n\n delete _deposits[tokenAddress][tokenId];\n\n IERC721Upgradeable(tokenAddress).transferFrom(address(this), to, tokenId);\n //emit event for successful token withdraw\n emit Withdrawal(bytes32(uint256(uint160(to))), tokenAddress, fuelContractId, 1);\n }\n\n ////////////////////////\n // Internal Functions //\n ////////////////////////\n\n /// @notice Deposits the given tokens to an account or contract on Fuel\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param tokenId tokenId to deposit\n /// @param messageData The data of the message to send for deposit\n function _deposit(\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 tokenId,\n bytes memory messageData\n ) internal virtual {\n // TODO: this check might be unnecessary. If the token is conformant to ERC721\n // it should not be possible to deposit the same token again\n require(_deposits[tokenAddress][tokenId] == 0, \"tokenId is already owned by another fuel bridge\");\n _deposits[tokenAddress][tokenId] = fuelContractId;\n\n //send message to gateway on Fuel to finalize the deposit\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, messageData);\n\n IERC721Upgradeable(tokenAddress).transferFrom(msg.sender, address(this), tokenId);\n //emit event for successful token deposit\n emit Deposit(bytes32(uint256(uint160(msg.sender))), tokenAddress, fuelContractId, tokenId);\n }\n\n /// @notice Executes a message in the given header\n // solhint-disable-next-line no-empty-blocks\n function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {\n //should revert if msg.sender is not authorized to upgrade the contract (currently only owner)\n }\n}\n" - }, - "contracts/messaging/gateway/v2/FuelBridgeBaseV2.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nabstract contract FuelBridgeBaseV2 {\n error FuelContractIsNotBridge();\n\n event ReceiverRegistered(bytes32 indexed fuelContractId, address indexed tokenAddress);\n\n mapping(bytes32 => mapping(address => bool)) public isBridge;\n\n /// @notice Accepts a message from a fuel entity to acknowledge it can receive tokens\n /// @param tokenAddress The token address that the fuel entity can receive\n /// @dev Made payable to reduce gas costs\n /// @dev funcSig: aec97dc6 => registerAsReceiver(address)\n function registerAsReceiver(address tokenAddress) external payable virtual;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" - }, - "contracts/messaging/gateway/v2/FuelERC20GatewayV2.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport \"../FuelERC20Gateway.sol\";\nimport \"./FuelBridgeBaseV2.sol\";\n\ncontract FuelERC20GatewayV2 is FuelERC20Gateway, FuelBridgeBaseV2 {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n function registerAsReceiver(address tokenAddress) external payable virtual override onlyFromPortal {\n bytes32 sender = messageSender();\n\n isBridge[sender][tokenAddress] = true;\n\n emit ReceiverRegistered(sender, tokenAddress);\n }\n\n /// @notice Deposits the given tokens to an account or contract on Fuel\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param amount Amount of tokens to deposit\n /// @param messageData The data of the message to send for deposit\n function _deposit(\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 amount,\n bytes memory messageData\n ) internal virtual override {\n require(amount > 0, \"Cannot deposit zero\");\n if (!isBridge[fuelContractId][tokenAddress]) revert FuelContractIsNotBridge();\n\n //transfer tokens to this contract and update deposit balance\n IERC20Upgradeable(tokenAddress).safeTransferFrom(msg.sender, address(this), amount);\n _deposits[tokenAddress][fuelContractId] = _deposits[tokenAddress][fuelContractId] + amount;\n\n //send message to gateway on Fuel to finalize the deposit\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, messageData);\n\n //emit event for successful token deposit\n emit Deposit(bytes32(uint256(uint160(msg.sender))), tokenAddress, fuelContractId, amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" - }, - "contracts/messaging/gateway/v2/FuelERC721GatewayV2.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.9;\n\nimport \"../FuelERC721Gateway.sol\";\nimport \"./FuelBridgeBaseV2.sol\";\n\ncontract FuelERC721GatewayV2 is FuelERC721Gateway, FuelBridgeBaseV2 {\n function registerAsReceiver(address tokenAddress) external payable virtual override onlyFromPortal {\n bytes32 sender = messageSender();\n\n isBridge[sender][tokenAddress] = true;\n\n emit ReceiverRegistered(sender, tokenAddress);\n }\n\n /// @notice Deposits the given tokens to an account or contract on Fuel\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param tokenId tokenId to deposit\n /// @param messageData The data of the message to send for deposit\n function _deposit(\n address tokenAddress,\n bytes32 fuelContractId,\n uint256 tokenId,\n bytes memory messageData\n ) internal virtual override {\n // TODO: this check might be unnecessary. If the token is conformant to ERC721\n // it should not be possible to deposit the same token again\n require(_deposits[tokenAddress][tokenId] == 0, \"tokenId is already owned by another fuel bridge\");\n if (!isBridge[fuelContractId][tokenAddress]) revert FuelContractIsNotBridge();\n\n _deposits[tokenAddress][tokenId] = fuelContractId;\n\n //send message to gateway on Fuel to finalize the deposit\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, messageData);\n\n IERC721Upgradeable(tokenAddress).transferFrom(msg.sender, address(this), tokenId);\n //emit event for successful token deposit\n emit Deposit(bytes32(uint256(uint160(msg.sender))), tokenAddress, fuelContractId, tokenId);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" - }, - "contracts/messaging/gateway/v3/FuelERC20GatewayV3.sol": { - "content": "// SPDX-License-Identifier: Apache 2.0\npragma solidity ^0.8.0;\n\nimport \"../v2/FuelERC20GatewayV2.sol\";\n\ncontract FuelERC20GatewayV3 is FuelERC20GatewayV2 {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n error GlobalDepositLimit();\n error CannotDepositZero();\n error CannotWithdrawZero();\n error TokenIdNotAllowed();\n\n mapping(address => uint256) public depositLimitGlobal;\n mapping(address => uint256) public depositTotals;\n\n function setGlobalDepositLimit(address token, uint256 limit)\n external\n payable\n virtual\n onlyRole(DEFAULT_ADMIN_ROLE)\n {\n depositLimitGlobal[token] = limit;\n }\n\n /// @notice Deposits the given tokens to an account or contract on Fuel\n /// @param tokenAddress Address of the token being transferred to Fuel\n /// @param fuelContractId ID of the contract on Fuel that manages the deposited tokens\n /// @param amount Amount of tokens to deposit\n /// @param messageData The data of the message to send for deposit\n function _deposit(address tokenAddress, bytes32 fuelContractId, uint256 amount, bytes memory messageData)\n internal\n virtual\n override\n {\n ////////////\n // Checks //\n ////////////\n if (amount == 0) revert CannotDepositZero();\n\n uint256 updatedDepositTotals = depositTotals[tokenAddress] + amount;\n if (updatedDepositTotals > depositLimitGlobal[tokenAddress]) revert GlobalDepositLimit();\n\n if (!isBridge[fuelContractId][tokenAddress]) revert FuelContractIsNotBridge();\n\n /////////////\n // Effects //\n /////////////\n _deposits[tokenAddress][fuelContractId] += amount;\n depositTotals[tokenAddress] = updatedDepositTotals;\n\n /////////////\n // Actions //\n /////////////\n //send message to gateway on Fuel to finalize the deposit\n sendMessage(CommonPredicates.CONTRACT_MESSAGE_PREDICATE, messageData);\n\n //transfer tokens to this contract and update deposit balance\n IERC20Upgradeable(tokenAddress).safeTransferFrom(msg.sender, address(this), amount);\n\n //emit event for successful token deposit\n emit Deposit(bytes32(uint256(uint160(msg.sender))), tokenAddress, fuelContractId, amount);\n }\n\n /// @notice Finalizes the withdrawal process from the Fuel side gateway contract\n /// @param to Account to send withdrawn tokens to\n /// @param tokenAddress Address of the token being withdrawn from Fuel\n /// @param amount Amount of tokens to withdraw\n /// @param tokenId Discriminator for ERC721 / ERC1155 tokens. For ERC20, it must be 0\n /// @dev Made payable to reduce gas costs\n function finalizeWithdrawal(address to, address tokenAddress, uint256 amount, uint256 tokenId)\n external\n payable\n override\n whenNotPaused\n onlyFromPortal\n {\n ////////////\n // Checks //\n ////////////\n if (amount == 0) revert CannotWithdrawZero();\n if (tokenId > 0) revert TokenIdNotAllowed();\n\n /////////////\n // Effects //\n /////////////\n bytes32 fuelContractId = messageSender();\n\n //reduce deposit balance and transfer tokens (math will underflow if amount is larger than allowed)\n _deposits[tokenAddress][fuelContractId] -= amount;\n depositTotals[tokenAddress] -= amount;\n\n /////////////\n // Actions //\n /////////////\n IERC20Upgradeable(tokenAddress).safeTransfer(to, amount);\n\n //emit event for successful token withdraw\n emit Withdrawal(bytes32(uint256(uint160(to))), tokenAddress, fuelContractId, amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" - }, - "contracts/test/MessageTester.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {FuelMessagesEnabled} from \"../messaging/FuelMessagesEnabled.sol\";\nimport {FuelMessagePortal} from \"../fuelchain/FuelMessagePortal.sol\";\n\n/// @notice This contract allows for testing message receiving.\ncontract MessageTester is FuelMessagesEnabled {\n bytes32 internal constant TRUSTED_SENDER = 0xf40001353a6b162f0ff9d59cae46ed49355aa4c424e3f79f6d84352f85715576;\n\n /// @notice Storage to hold and test incoming data\n uint256 public data1;\n uint256 public data2;\n\n /// @notice Constructor.\n /// @param fuelMessagePortal The FuelMessagePortal contract\n constructor(FuelMessagePortal fuelMessagePortal) {\n _fuelMessagePortal = fuelMessagePortal;\n }\n\n /// @notice Message receiving function.\n /// @param d1 Test param 1\n /// @param d2 Test param 2\n function receiveMessage(uint256 d1, uint256 d2) external payable onlyFromFuelSender(TRUSTED_SENDER) {\n data1 = d1;\n data2 = d2;\n }\n\n /// @notice Send a message to a recipient on Fuel\n /// @param recipient The target message receiver\n /// @param data The message data to be sent to the receiver\n function attemptSendMessage(bytes32 recipient, bytes memory data) external {\n sendMessage(recipient, data);\n }\n\n /// @notice Send a message to a recipient on Fuel\n /// @param recipient The target message receiver\n /// @param amount The amount of ETH to send with message\n /// @param data The message data to be sent to the receiver\n function attemptSendMessageWithAmount(bytes32 recipient, uint256 amount, bytes memory data) external {\n sendMessage(recipient, amount, data);\n }\n\n /// @notice Gets the address of the trusted message sender.\n /// @return Address of the trusted message sender\n function getTrustedSender() external pure returns (bytes32) {\n return TRUSTED_SENDER;\n }\n\n /// @notice Default receive function\n // solhint-disable-next-line no-empty-blocks\n receive() external payable {\n // handle incoming eth\n }\n}\n" - }, - "contracts/test/MockCryptography.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {CryptographyLib} from \"../lib/Cryptography.sol\";\n\ncontract MockCryptography {\n function hash(bytes memory data) public pure returns (bytes32) {\n return CryptographyLib.hash(data);\n }\n\n function addressFromSignatureComponents(\n uint8 v,\n bytes32 r,\n bytes32 s,\n bytes32 message\n ) external pure returns (address) {\n return CryptographyLib.addressFromSignatureComponents(v, r, s, message);\n }\n\n function addressFromSignature(bytes memory signature, bytes32 message) external pure returns (address) {\n return CryptographyLib.addressFromSignature(signature, message);\n }\n}\n" - }, - "contracts/test/MockFuelMessagePortal.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.9;\n\ncontract MockFuelMessagePortal {\n event SendMessageCalled(bytes32 indexed target, bytes data);\n\n bytes32 private _messageSender;\n\n function setMessageSender(bytes32 value) external {\n _messageSender = value;\n }\n\n function messageSender() external view returns (bytes32) {\n return _messageSender;\n }\n\n function sendMessage(bytes32 target, bytes calldata data) external {\n emit SendMessageCalled(target, data);\n }\n}\n" - }, - "contracts/test/NFT.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >=0.8.9;\n\nimport \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\n\ncontract NFT is ERC721 {\n constructor() ERC721(\"TestNFT\", \"TestNFT\") {}\n\n function mint(address to, uint tokenID) external {\n _mint(to, tokenID);\n }\n}\n" - }, - "contracts/test/Token.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/// @notice This token is for testing purposes.\ncontract Token is ERC20 {\n address public _owner;\n\n /// @notice Constructor.\n constructor() ERC20(\"Token\", \"TKN\") {\n _owner = msg.sender;\n }\n\n /// @notice This is a simple mint function.\n /// @param owner The owner of the token.\n /// @param amount The amount of the token to mint to the owner.\n /// @dev Allows anyone to mint the token.\n function mint(address owner, uint256 amount) external {\n _mint(owner, amount);\n }\n}\n" - }, - "contracts/test/UpgradeableTester.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.9;\n\nimport {FuelMessagesEnabledUpgradeable} from \"../messaging/FuelMessagesEnabledUpgradeable.sol\";\nimport {FuelMessagePortal} from \"../fuelchain/FuelMessagePortal.sol\";\n\n/// @notice This contract allows for testing message receiving.\ncontract UpgradeableTester is FuelMessagesEnabledUpgradeable {\n /// @notice Test the init function for FuelMessagesEnabledUpgradeable\n function testFuelMessagesEnabledInit(FuelMessagePortal fuelMessagePortal) external {\n __FuelMessagesEnabled_init(fuelMessagePortal);\n }\n\n /// @notice Test the init unchained function for FuelMessagesEnabledUpgradeable\n function testFuelMessagesEnabledInitUnchained(FuelMessagePortal fuelMessagePortal) external {\n __FuelMessagesEnabled_init_unchained(fuelMessagePortal);\n }\n}\n" - }, - "contracts/vendor/SafeCall.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\n/**\n * @title SafeCall\n * @notice Perform low level safe calls. See https://github.com/nomad-xyz/ExcessivelySafeCall\n */\nlibrary SafeCall {\n /**\n * @notice Perform a low level call without copying any returndata\n *\n * @param _target Address to call\n * @param _value Amount of value to pass to the call\n * @param _calldata Calldata to pass to the call\n */\n function call(address _target, uint256 _value, bytes memory _calldata) internal returns (bool) {\n bool _success;\n uint256 _gas = gasleft();\n assembly {\n _success := call(\n _gas,\n _target,\n _value,\n add(_calldata, 0x20), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n}\n" - }, - "hardhat/console.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nlibrary console {\n address constant CONSOLE_ADDRESS =\n 0x000000000000000000636F6e736F6c652e6c6f67;\n\n function _sendLogPayloadImplementation(bytes memory payload) internal view {\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n pop(\n staticcall(\n gas(),\n consoleAddress,\n add(payload, 32),\n mload(payload),\n 0,\n 0\n )\n )\n }\n }\n\n function _castToPure(\n function(bytes memory) internal view fnIn\n ) internal pure returns (function(bytes memory) pure fnOut) {\n assembly {\n fnOut := fnIn\n }\n }\n\n function _sendLogPayload(bytes memory payload) internal pure {\n _castToPure(_sendLogPayloadImplementation)(payload);\n }\n\n function log() internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n function logInt(int256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function logUint(uint256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function logString(string memory p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function log(string memory p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint256 p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256)\", p0, p1));\n }\n\n function log(uint256 p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string)\", p0, p1));\n }\n\n function log(uint256 p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool)\", p0, p1));\n }\n\n function log(uint256 p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address)\", p0, p1));\n }\n\n function log(string memory p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 10000 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "storageLayout", - "devdoc", - "userdoc", - "evm.gasEstimates" - ], - "": ["ast"] - } - }, - "metadata": { - "useLiteralContent": true - } - } -} diff --git a/packages/solidity-contracts/deployments/testnet/.chainId b/packages/solidity-contracts/deployments/testnet/.chainId deleted file mode 100644 index bd8d1cd4..00000000 --- a/packages/solidity-contracts/deployments/testnet/.chainId +++ /dev/null @@ -1 +0,0 @@ -11155111 \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/.migrations.json b/packages/solidity-contracts/deployments/testnet/.migrations.json deleted file mode 100644 index de166f4d..00000000 --- a/packages/solidity-contracts/deployments/testnet/.migrations.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "chain_state": 1714255660, - "fuel_message_portal": 1714255695, - "fuel_erc20_gateway_v4": 1714255717, - "token": 1714255743, - "register_committer": 1714255753 -} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/FuelChainState.json b/packages/solidity-contracts/deployments/testnet/FuelChainState.json deleted file mode 100644 index 6bd96bcf..00000000 --- a/packages/solidity-contracts/deployments/testnet/FuelChainState.json +++ /dev/null @@ -1,528 +0,0 @@ -{ - "address": "0x8097500F4168240f4334589170d99fE8797b6fF8", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "UnknownBlock", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "commitHeight", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - } - ], - "name": "CommitSubmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "inputs": [], - "name": "BLOCKS_PER_COMMIT_INTERVAL", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "COMMITTER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "NUM_COMMIT_SLOTS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PAUSER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "TIME_TO_FINALIZE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "commitHeight", - "type": "uint256" - } - ], - "name": "blockHashAtCommit", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "commitHeight", - "type": "uint256" - } - ], - "name": "commit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "blockHeight", - "type": "uint256" - } - ], - "name": "finalized", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "proxiableUUID", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - } - ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "upgradeToAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } - ], - "numDeployments": 1, - "implementation": "0xba98eDC9AC0B6191180562bF68CE001B1D71C11D" -} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/FuelMessagePortal.json b/packages/solidity-contracts/deployments/testnet/FuelMessagePortal.json deleted file mode 100644 index afe6218a..00000000 --- a/packages/solidity-contracts/deployments/testnet/FuelMessagePortal.json +++ /dev/null @@ -1,926 +0,0 @@ -{ - "address": "0x768f9459E3339A1F7d59CcF24C80Eb4A711a01FB", - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_depositLimitGlobal", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AlreadyRelayed", - "type": "error" - }, - { - "inputs": [], - "name": "AmountPrecisionIncompatibility", - "type": "error" - }, - { - "inputs": [], - "name": "AmountTooBig", - "type": "error" - }, - { - "inputs": [], - "name": "CurrentMessageSenderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "GlobalDepositLimit", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidBlockInHistoryProof", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidMessageInBlockProof", - "type": "error" - }, - { - "inputs": [], - "name": "MessageBlacklisted", - "type": "error" - }, - { - "inputs": [], - "name": "MessageDataTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "UnfinalizedBlock", - "type": "error" - }, - { - "inputs": [], - "name": "WithdrawalsPaused", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "messageId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "sender", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "recipient", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "amount", - "type": "uint64" - } - ], - "name": "MessageRelayed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "sender", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "recipient", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "amount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "MessageSent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ETH_DECIMALS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "FUEL_BASE_ASSET_DECIMALS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_MESSAGE_DATA_SIZE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PAUSER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PRECISION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "messageId", - "type": "bytes32" - } - ], - "name": "addMessageToBlacklist", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "recipient", - "type": "bytes32" - } - ], - "name": "depositETH", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "depositLimitGlobal", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "fuelBaseAssetDecimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "fuelChainStateContract", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getNextOutgoingMessageNonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "messageId", - "type": "bytes32" - } - ], - "name": "incomingMessageSuccessful", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract FuelChainState", - "name": "fuelChainState", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "messageIsBlacklisted", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "messageSender", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pauseWithdrawals", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "proxiableUUID", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "sender", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "recipient", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "nonce", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "amount", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Message", - "name": "message", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "prevRoot", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "height", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "applicationHash", - "type": "bytes32" - } - ], - "internalType": "struct FuelBlockHeaderLite", - "name": "rootBlockHeader", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "prevRoot", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "height", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "daHeight", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "txCount", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "outputMessagesCount", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "txRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "outputMessagesRoot", - "type": "bytes32" - } - ], - "internalType": "struct FuelBlockHeader", - "name": "blockHeader", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "key", - "type": "uint256" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "internalType": "struct MerkleProof", - "name": "blockInHistoryProof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "key", - "type": "uint256" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "internalType": "struct MerkleProof", - "name": "messageInBlockProof", - "type": "tuple" - } - ], - "name": "relayMessage", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "messageId", - "type": "bytes32" - } - ], - "name": "removeMessageFromBlacklist", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "recipient", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "sendMessage", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalDeposited", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpauseWithdrawals", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - } - ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "upgradeToAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawalsPaused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "numDeployments": 1, - "implementation": "0xC9C453fA30cd0c6A2f09Af5e1C32F839Ff7a3DD0" -} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/Token.json b/packages/solidity-contracts/deployments/testnet/Token.json deleted file mode 100644 index d4dea8d9..00000000 --- a/packages/solidity-contracts/deployments/testnet/Token.json +++ /dev/null @@ -1,475 +0,0 @@ -{ - "address": "0x25E869bc5FC45e2786B4B1bEace61287e071C60e", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [], - "name": "_owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x310a12e685caa9ef3b4186ab13e9ad9745b5335c8d076b4cba6012fb53cef8c0", - "receipt": { - "to": null, - "from": "0xC0cBA65C478C90D779419799687f6DaF8F9F01b1", - "contractAddress": "0x25E869bc5FC45e2786B4B1bEace61287e071C60e", - "transactionIndex": 59, - "gasUsed": "817074", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x6be8cfd73c319afc4815911196414227f0a84a7beaa59930fb52ad7d9fc6c452", - "transactionHash": "0x310a12e685caa9ef3b4186ab13e9ad9745b5335c8d076b4cba6012fb53cef8c0", - "logs": [], - "blockNumber": 5791370, - "cumulativeGasUsed": "7119154", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "31fce82f72204deb1c3e677ecb77fe87", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"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.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"mint(address,uint256)\":{\"details\":\"Allows anyone to mint the token.\",\"params\":{\"amount\":\"The amount of the token to mint to the owner.\",\"owner\":\"The owner of the token.\"}},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"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`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Constructor.\"},\"mint(address,uint256)\":{\"notice\":\"This is a simple mint function.\"}},\"notice\":\"This token is for testing purposes.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/Token.sol\":\"Token\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xa92e4fa126feb6907daa0513ddd816b2eb91f30a808de54f63c17d0e162c3439\",\"license\":\"MIT\"},\"contracts/test/Token.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.9;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n/// @notice This token is for testing purposes.\\ncontract Token is ERC20 {\\n address public _owner;\\n\\n /// @notice Constructor.\\n constructor() ERC20(\\\"Token\\\", \\\"TKN\\\") {\\n _owner = msg.sender;\\n }\\n\\n /// @notice This is a simple mint function.\\n /// @param owner The owner of the token.\\n /// @param amount The amount of the token to mint to the owner.\\n /// @dev Allows anyone to mint the token.\\n function mint(address owner, uint256 amount) external {\\n _mint(owner, amount);\\n }\\n}\\n\",\"keccak256\":\"0xbf1a9c1cb145ebd98b1f6159fb8d617c284044ca5ab8f07678a209c411083797\",\"license\":\"UNLICENSED\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b50604051806040016040528060058152602001642a37b5b2b760d91b815250604051806040016040528060038152602001622a25a760e91b81525081600390805190602001906200006492919062000095565b5080516200007a90600490602084019062000095565b5050600580546001600160a01b031916331790555062000178565b828054620000a3906200013b565b90600052602060002090601f016020900481019282620000c7576000855562000112565b82601f10620000e257805160ff191683800117855562000112565b8280016001018555821562000112579182015b8281111562000112578251825591602001919060010190620000f5565b506200012092915062000124565b5090565b5b8082111562000120576000815560010162000125565b600181811c908216806200015057607f821691505b602082108114156200017257634e487b7160e01b600052602260045260246000fd5b50919050565b610c9780620001886000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c806340c10f191161008c578063a457c2d711610066578063a457c2d7146101bf578063a9059cbb146101d2578063b2bdfa7b146101e5578063dd62ed3e1461022a57600080fd5b806340c10f191461016c57806370a082311461018157806395d89b41146101b757600080fd5b806323b872dd116100bd57806323b872dd14610137578063313ce5671461014a578063395093511461015957600080fd5b806306fdde03146100e4578063095ea7b31461010257806318160ddd14610125575b600080fd5b6100ec610270565b6040516100f99190610a77565b60405180910390f35b610115610110366004610b13565b610302565b60405190151581526020016100f9565b6002545b6040519081526020016100f9565b610115610145366004610b3d565b61031a565b604051601281526020016100f9565b610115610167366004610b13565b61033e565b61017f61017a366004610b13565b61038a565b005b61012961018f366004610b79565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100ec610398565b6101156101cd366004610b13565b6103a7565b6101156101e0366004610b13565b61047d565b6005546102059073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f9565b610129610238366004610b9b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60606003805461027f90610bce565b80601f01602080910402602001604051908101604052809291908181526020018280546102ab90610bce565b80156102f85780601f106102cd576101008083540402835291602001916102f8565b820191906000526020600020905b8154815290600101906020018083116102db57829003601f168201915b5050505050905090565b60003361031081858561048b565b5060019392505050565b60003361032885828561063e565b610333858585610715565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906103109082908690610385908790610c22565b61048b565b6103948282610984565b5050565b60606004805461027f90610bce565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610333828686840361048b565b600033610310818585610715565b73ffffffffffffffffffffffffffffffffffffffff831661052d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff82166105d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461070f5781811015610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610467565b61070f848484840361048b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166107b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff821661085b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361070f565b73ffffffffffffffffffffffffffffffffffffffff8216610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610467565b8060026000828254610a139190610c22565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b81811015610aa457858101830151858201604001528201610a88565b81811115610ab6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b0e57600080fd5b919050565b60008060408385031215610b2657600080fd5b610b2f83610aea565b946020939093013593505050565b600080600060608486031215610b5257600080fd5b610b5b84610aea565b9250610b6960208501610aea565b9150604084013590509250925092565b600060208284031215610b8b57600080fd5b610b9482610aea565b9392505050565b60008060408385031215610bae57600080fd5b610bb783610aea565b9150610bc560208401610aea565b90509250929050565b600181811c90821680610be257607f821691505b60208210811415610c1c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008219821115610c5c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea26469706673582212208229be857565d410e6d53feda1bd4d1a3faa25a0f5741d49827aa48b07a9084e64736f6c63430008090033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100df5760003560e01c806340c10f191161008c578063a457c2d711610066578063a457c2d7146101bf578063a9059cbb146101d2578063b2bdfa7b146101e5578063dd62ed3e1461022a57600080fd5b806340c10f191461016c57806370a082311461018157806395d89b41146101b757600080fd5b806323b872dd116100bd57806323b872dd14610137578063313ce5671461014a578063395093511461015957600080fd5b806306fdde03146100e4578063095ea7b31461010257806318160ddd14610125575b600080fd5b6100ec610270565b6040516100f99190610a77565b60405180910390f35b610115610110366004610b13565b610302565b60405190151581526020016100f9565b6002545b6040519081526020016100f9565b610115610145366004610b3d565b61031a565b604051601281526020016100f9565b610115610167366004610b13565b61033e565b61017f61017a366004610b13565b61038a565b005b61012961018f366004610b79565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100ec610398565b6101156101cd366004610b13565b6103a7565b6101156101e0366004610b13565b61047d565b6005546102059073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f9565b610129610238366004610b9b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60606003805461027f90610bce565b80601f01602080910402602001604051908101604052809291908181526020018280546102ab90610bce565b80156102f85780601f106102cd576101008083540402835291602001916102f8565b820191906000526020600020905b8154815290600101906020018083116102db57829003601f168201915b5050505050905090565b60003361031081858561048b565b5060019392505050565b60003361032885828561063e565b610333858585610715565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906103109082908690610385908790610c22565b61048b565b6103948282610984565b5050565b60606004805461027f90610bce565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610333828686840361048b565b600033610310818585610715565b73ffffffffffffffffffffffffffffffffffffffff831661052d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff82166105d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461070f5781811015610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610467565b61070f848484840361048b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166107b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff821661085b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361070f565b73ffffffffffffffffffffffffffffffffffffffff8216610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610467565b8060026000828254610a139190610c22565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b81811015610aa457858101830151858201604001528201610a88565b81811115610ab6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b0e57600080fd5b919050565b60008060408385031215610b2657600080fd5b610b2f83610aea565b946020939093013593505050565b600080600060608486031215610b5257600080fd5b610b5b84610aea565b9250610b6960208501610aea565b9150604084013590509250925092565b600060208284031215610b8b57600080fd5b610b9482610aea565b9392505050565b60008060408385031215610bae57600080fd5b610bb783610aea565b9150610bc560208401610aea565b90509250929050565b600181811c90821680610be257607f821691505b60208210811415610c1c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008219821115610c5c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea26469706673582212208229be857565d410e6d53feda1bd4d1a3faa25a0f5741d49827aa48b07a9084e64736f6c63430008090033", - "devdoc": { - "kind": "dev", - "methods": { - "allowance(address,address)": { - "details": "See {IERC20-allowance}." - }, - "approve(address,uint256)": { - "details": "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." - }, - "balanceOf(address)": { - "details": "See {IERC20-balanceOf}." - }, - "decimals()": { - "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." - }, - "decreaseAllowance(address,uint256)": { - "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." - }, - "increaseAllowance(address,uint256)": { - "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." - }, - "mint(address,uint256)": { - "details": "Allows anyone to mint the token.", - "params": { - "amount": "The amount of the token to mint to the owner.", - "owner": "The owner of the token." - } - }, - "name()": { - "details": "Returns the name of the token." - }, - "symbol()": { - "details": "Returns the symbol of the token, usually a shorter version of the name." - }, - "totalSupply()": { - "details": "See {IERC20-totalSupply}." - }, - "transfer(address,uint256)": { - "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`." - }, - "transferFrom(address,address,uint256)": { - "details": "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`." - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "constructor": { - "notice": "Constructor." - }, - "mint(address,uint256)": { - "notice": "This is a simple mint function." - } - }, - "notice": "This token is for testing purposes.", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 5990, - "contract": "contracts/test/Token.sol:Token", - "label": "_balances", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 5996, - "contract": "contracts/test/Token.sol:Token", - "label": "_allowances", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" - }, - { - "astId": 5998, - "contract": "contracts/test/Token.sol:Token", - "label": "_totalSupply", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 6000, - "contract": "contracts/test/Token.sol:Token", - "label": "_name", - "offset": 0, - "slot": "3", - "type": "t_string_storage" - }, - { - "astId": 6002, - "contract": "contracts/test/Token.sol:Token", - "label": "_symbol", - "offset": 0, - "slot": "4", - "type": "t_string_storage" - }, - { - "astId": 13868, - "contract": "contracts/test/Token.sol:Token", - "label": "_owner", - "offset": 0, - "slot": "5", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file From 49d5d74d7ad946689f0fe5c6cde591d9eb218b4f Mon Sep 17 00:00:00 2001 From: DefiCake Date: Fri, 3 May 2024 12:16:47 +0200 Subject: [PATCH 05/28] chore: deploy testnet instances --- .../.openzeppelin/sepolia.json | 10 + packages/solidity-contracts/DEPLOYMENTS.MD | 16 +- .../deploy/testnet/001.chain_state.ts | 39 + .../testnet/002.fuel_message_portal_v3.ts | 48 + .../deployments/testnet/.chainId | 1 + .../deployments/testnet/.migrations.json | 4 + .../deployments/testnet/FuelChainState.json | 528 ++++++++++ .../testnet/FuelMessagePortal.json | 926 ++++++++++++++++++ 8 files changed, 1562 insertions(+), 10 deletions(-) create mode 100644 packages/solidity-contracts/deploy/testnet/001.chain_state.ts create mode 100644 packages/solidity-contracts/deploy/testnet/002.fuel_message_portal_v3.ts create mode 100644 packages/solidity-contracts/deployments/testnet/.chainId create mode 100644 packages/solidity-contracts/deployments/testnet/.migrations.json create mode 100644 packages/solidity-contracts/deployments/testnet/FuelChainState.json create mode 100644 packages/solidity-contracts/deployments/testnet/FuelMessagePortal.json diff --git a/packages/solidity-contracts/.openzeppelin/sepolia.json b/packages/solidity-contracts/.openzeppelin/sepolia.json index 0c67ff61..acab5f76 100644 --- a/packages/solidity-contracts/.openzeppelin/sepolia.json +++ b/packages/solidity-contracts/.openzeppelin/sepolia.json @@ -115,6 +115,16 @@ "address": "0xbdf7256C718FCede6f0af19e86D4aBDdc4DC2Ff2", "txHash": "0x5e93f7942b84271090b9a8e44a95e2f3532d517fc73591e78711a01fccd2eea2", "kind": "uups" + }, + { + "address": "0x404F391F96798B14C5e99BBB4a9C858da9Cf63b5", + "txHash": "0xbc2cd5b2b5ef31e24e146c50dec2e11e3f075ea04c8f374420947c6a3ccab9b2", + "kind": "uups" + }, + { + "address": "0x01855B78C1f8868DE70e84507ec735983bf262dA", + "txHash": "0xfe7d426ed7e823f4ef65c2cc10cae603ded0dedfb458073e275488f640b87c0a", + "kind": "uups" } ], "impls": { diff --git a/packages/solidity-contracts/DEPLOYMENTS.MD b/packages/solidity-contracts/DEPLOYMENTS.MD index a2aac4f9..9f11afd5 100644 --- a/packages/solidity-contracts/DEPLOYMENTS.MD +++ b/packages/solidity-contracts/DEPLOYMENTS.MD @@ -22,19 +22,15 @@ FuelERC721GatewayV2 at 0xc17a3694B01238308Fd1140E2F13928ff6564f84 ## Devnet ``` -FuelChainState at 0x0880932521f0E3a90d56bC96fD49c0c98CFCf4A7 -FuelMessagePortal at 0x01eb5b6122E1f65eaF4566093C2431aa0c0eaCd5 -FuelERC20GatewayV2 at 0x83114982BDe057a8907F8a081225C7d301898aDd +FuelChainState at 0x8097500F4168240f4334589170d99fE8797b6fF8 +FuelMessagePortal at 0x768f9459E3339A1F7d59CcF24C80Eb4A711a01FB +FuelERC20GatewayV4 at 0xbdf7256C718FCede6f0af19e86D4aBDdc4DC2Ff2 +Token deployed at0x25E869bc5FC45e2786B4B1bEace61287e071C60e ``` ## Testnet ``` -FuelChainState at 0x8097500F4168240f4334589170d99fE8797b6fF8 - -FuelMessagePortal at 0x768f9459E3339A1F7d59CcF24C80Eb4A711a01FB - -FuelERC20GatewayV4 at 0xbdf7256C718FCede6f0af19e86D4aBDdc4DC2Ff2 - -Token deployed at0x25E869bc5FC45e2786B4B1bEace61287e071C60e +FuelChainState at 0x404F391F96798B14C5e99BBB4a9C858da9Cf63b5 +FuelMessagePortal at 0x01855B78C1f8868DE70e84507ec735983bf262dA ``` \ No newline at end of file diff --git a/packages/solidity-contracts/deploy/testnet/001.chain_state.ts b/packages/solidity-contracts/deploy/testnet/001.chain_state.ts new file mode 100644 index 00000000..65c1e9b7 --- /dev/null +++ b/packages/solidity-contracts/deploy/testnet/001.chain_state.ts @@ -0,0 +1,39 @@ +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; + +import { FuelChainState__factory as FuelChainState } from '../../typechain'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { + ethers, + upgrades: { deployProxy, erc1967 }, + deployments: { save, execute }, + } = hre; + const [deployer] = await ethers.getSigners(); + + const contract = await deployProxy(new FuelChainState(deployer), [], { + initializer: 'initialize', + }); + await contract.waitForDeployment(); + const address = await contract.getAddress(); + const implementation = await erc1967.getImplementationAddress(address); + + console.log('Deployed FuelChainState at', address); + await save('FuelChainState', { + address, + abi: [...FuelChainState.abi], + implementation, + }); + + await execute( + 'FuelChainState', + { log: true, from: deployer.address }, + 'pause' + ); + + return true; +}; + +func.tags = ['state', 'chain-state', 'chain_state', 'FuelChainState']; +func.id = 'chain_state'; +export default func; diff --git a/packages/solidity-contracts/deploy/testnet/002.fuel_message_portal_v3.ts b/packages/solidity-contracts/deploy/testnet/002.fuel_message_portal_v3.ts new file mode 100644 index 00000000..5ca0d404 --- /dev/null +++ b/packages/solidity-contracts/deploy/testnet/002.fuel_message_portal_v3.ts @@ -0,0 +1,48 @@ +import { MaxUint256 } from 'ethers'; +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; + +import { FuelMessagePortalV3__factory as FuelMessagePortal } from '../../typechain'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { + ethers, + upgrades: { deployProxy, erc1967 }, + deployments: { get, save, execute }, + } = hre; + const [deployer] = await ethers.getSigners(); + + const { address: fuelChainState } = await get('FuelChainState'); + + const contract = await deployProxy( + new FuelMessagePortal(deployer), + [fuelChainState], + { + initializer: 'initialize', + constructorArgs: [MaxUint256], + } + ); + await contract.waitForDeployment(); + + const address = await contract.getAddress(); + const implementation = await erc1967.getImplementationAddress(address); + + console.log('Deployed FuelMessagePortal at', address); + await save('FuelMessagePortal', { + address, + abi: [...FuelMessagePortal.abi], + implementation, + }); + + await execute( + 'FuelMessagePortal', + { log: true, from: deployer.address }, + 'pause' + ); + + return true; +}; + +func.tags = ['portal', 'message_portal', 'FuelMessagePortal']; +func.id = 'fuel_message_portal'; +export default func; diff --git a/packages/solidity-contracts/deployments/testnet/.chainId b/packages/solidity-contracts/deployments/testnet/.chainId new file mode 100644 index 00000000..bd8d1cd4 --- /dev/null +++ b/packages/solidity-contracts/deployments/testnet/.chainId @@ -0,0 +1 @@ +11155111 \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/.migrations.json b/packages/solidity-contracts/deployments/testnet/.migrations.json new file mode 100644 index 00000000..9f29ecd8 --- /dev/null +++ b/packages/solidity-contracts/deployments/testnet/.migrations.json @@ -0,0 +1,4 @@ +{ + "chain_state": 1714731339, + "fuel_message_portal": 1714731385 +} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/FuelChainState.json b/packages/solidity-contracts/deployments/testnet/FuelChainState.json new file mode 100644 index 00000000..fe53f88e --- /dev/null +++ b/packages/solidity-contracts/deployments/testnet/FuelChainState.json @@ -0,0 +1,528 @@ +{ + "address": "0x404F391F96798B14C5e99BBB4a9C858da9Cf63b5", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "UnknownBlock", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "commitHeight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "name": "CommitSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKS_PER_COMMIT_INTERVAL", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COMMITTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NUM_COMMIT_SLOTS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAUSER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TIME_TO_FINALIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "commitHeight", + "type": "uint256" + } + ], + "name": "blockHashAtCommit", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "commitHeight", + "type": "uint256" + } + ], + "name": "commit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "blockHeight", + "type": "uint256" + } + ], + "name": "finalized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "numDeployments": 1, + "implementation": "0xba98eDC9AC0B6191180562bF68CE001B1D71C11D" +} \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/testnet/FuelMessagePortal.json b/packages/solidity-contracts/deployments/testnet/FuelMessagePortal.json new file mode 100644 index 00000000..baf2ae24 --- /dev/null +++ b/packages/solidity-contracts/deployments/testnet/FuelMessagePortal.json @@ -0,0 +1,926 @@ +{ + "address": "0x01855B78C1f8868DE70e84507ec735983bf262dA", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_depositLimitGlobal", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyRelayed", + "type": "error" + }, + { + "inputs": [], + "name": "AmountPrecisionIncompatibility", + "type": "error" + }, + { + "inputs": [], + "name": "AmountTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "CurrentMessageSenderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "GlobalDepositLimit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBlockInHistoryProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidMessageInBlockProof", + "type": "error" + }, + { + "inputs": [], + "name": "MessageBlacklisted", + "type": "error" + }, + { + "inputs": [], + "name": "MessageDataTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "UnfinalizedBlock", + "type": "error" + }, + { + "inputs": [], + "name": "WithdrawalsPaused", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "messageId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "sender", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "amount", + "type": "uint64" + } + ], + "name": "MessageRelayed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sender", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "amount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "MessageSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_DECIMALS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FUEL_BASE_ASSET_DECIMALS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_MESSAGE_DATA_SIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAUSER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PRECISION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "messageId", + "type": "bytes32" + } + ], + "name": "addMessageToBlacklist", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + } + ], + "name": "depositETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "depositLimitGlobal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fuelBaseAssetDecimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "fuelChainStateContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNextOutgoingMessageNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "messageId", + "type": "bytes32" + } + ], + "name": "incomingMessageSuccessful", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract FuelChainState", + "name": "fuelChainState", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "messageIsBlacklisted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "messageSender", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pauseWithdrawals", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "sender", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "amount", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Message", + "name": "message", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "prevRoot", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "height", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "applicationHash", + "type": "bytes32" + } + ], + "internalType": "struct FuelBlockHeaderLite", + "name": "rootBlockHeader", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "prevRoot", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "height", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "daHeight", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "txCount", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "outputMessagesCount", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "txRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "outputMessagesRoot", + "type": "bytes32" + } + ], + "internalType": "struct FuelBlockHeader", + "name": "blockHeader", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "key", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct MerkleProof", + "name": "blockInHistoryProof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "key", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct MerkleProof", + "name": "messageInBlockProof", + "type": "tuple" + } + ], + "name": "relayMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "messageId", + "type": "bytes32" + } + ], + "name": "removeMessageFromBlacklist", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDeposited", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpauseWithdrawals", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawalsPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "numDeployments": 1, + "implementation": "0xC9C453fA30cd0c6A2f09Af5e1C32F839Ff7a3DD0" +} \ No newline at end of file From bcdac290b0120b3977bb78767dfe24a22ff1d7d6 Mon Sep 17 00:00:00 2001 From: DefiCake Date: Tue, 7 May 2024 20:32:57 +0200 Subject: [PATCH 06/28] chore: upgrade FuelMessagePortal for devnet --- .../.openzeppelin/sepolia.json | 251 ++++++++++++++++++ .../devnet/006.fuel_message_portal_v3.ts | 47 ++++ .../007.fuel_message_portal_v3_unpause.ts | 22 ++ .../deployments/devnet/.migrations.json | 3 +- .../deployments/devnet/FuelMessagePortal.json | 44 ++- 5 files changed, 354 insertions(+), 13 deletions(-) create mode 100644 packages/solidity-contracts/deploy/devnet/006.fuel_message_portal_v3.ts create mode 100644 packages/solidity-contracts/deploy/devnet/007.fuel_message_portal_v3_unpause.ts diff --git a/packages/solidity-contracts/.openzeppelin/sepolia.json b/packages/solidity-contracts/.openzeppelin/sepolia.json index acab5f76..d8856461 100644 --- a/packages/solidity-contracts/.openzeppelin/sepolia.json +++ b/packages/solidity-contracts/.openzeppelin/sepolia.json @@ -3099,6 +3099,257 @@ }, "namespaces": {} } + }, + "8b16077ce2a68c7e3c6f38f1c61c607d3f53d55ac1c12268c2bee149e0ddc9bb": { + "address": "0xA517017C3d004F1C5fE1CeC4207787627BAd4011", + "txHash": "0x6ecab59ae9c496ed9e34d4e45a65760d56f863d90cd684d6a61d484ecd4c6020", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_paused", + "offset": 0, + "slot": "51", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_roles", + "offset": 0, + "slot": "151", + "type": "t_mapping(t_bytes32,t_struct(RoleData)2324_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:57" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:260" + }, + { + "label": "_status", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:88" + }, + { + "label": "__gap", + "offset": 0, + "slot": "251", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "301", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "_incomingMessageSender", + "offset": 0, + "slot": "351", + "type": "t_bytes32", + "contract": "FuelMessagePortal", + "src": "contracts/fuelchain/FuelMessagePortal.sol:96" + }, + { + "label": "_fuelChainState", + "offset": 0, + "slot": "352", + "type": "t_contract(FuelChainState)9632", + "contract": "FuelMessagePortal", + "src": "contracts/fuelchain/FuelMessagePortal.sol:99" + }, + { + "label": "_outgoingMessageNonce", + "offset": 0, + "slot": "353", + "type": "t_uint256", + "contract": "FuelMessagePortal", + "src": "contracts/fuelchain/FuelMessagePortal.sol:102" + }, + { + "label": "_incomingMessageSuccessful", + "offset": 0, + "slot": "354", + "type": "t_mapping(t_bytes32,t_bool)", + "contract": "FuelMessagePortal", + "src": "contracts/fuelchain/FuelMessagePortal.sol:105" + }, + { + "label": "__gap", + "offset": 0, + "slot": "355", + "type": "t_array(t_uint256)49_storage", + "contract": "FuelMessagePortal", + "src": "contracts/fuelchain/FuelMessagePortal.sol:333" + }, + { + "label": "totalDeposited", + "offset": 0, + "slot": "404", + "type": "t_uint256", + "contract": "FuelMessagePortalV2", + "src": "contracts/fuelchain/FuelMessagePortal/v2/FuelMessagePortalV2.sol:14" + }, + { + "label": "__gap", + "offset": 0, + "slot": "405", + "type": "t_array(t_uint256)49_storage", + "contract": "FuelMessagePortalV2", + "src": "contracts/fuelchain/FuelMessagePortal/v2/FuelMessagePortalV2.sol:107" + }, + { + "label": "withdrawalsPaused", + "offset": 0, + "slot": "454", + "type": "t_bool", + "contract": "FuelMessagePortalV3", + "src": "contracts/fuelchain/FuelMessagePortal/v3/FuelMessagePortalV3.sol:15" + }, + { + "label": "messageIsBlacklisted", + "offset": 0, + "slot": "455", + "type": "t_mapping(t_bytes32,t_bool)", + "contract": "FuelMessagePortalV3", + "src": "contracts/fuelchain/FuelMessagePortal/v3/FuelMessagePortalV3.sol:16" + }, + { + "label": "__gap", + "offset": 0, + "slot": "456", + "type": "t_array(t_uint256)49_storage", + "contract": "FuelMessagePortalV3", + "src": "contracts/fuelchain/FuelMessagePortal/v3/FuelMessagePortalV3.sol:148" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(FuelChainState)9632": { + "label": "contract FuelChainState", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)2324_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_struct(RoleData)2324_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/solidity-contracts/deploy/devnet/006.fuel_message_portal_v3.ts b/packages/solidity-contracts/deploy/devnet/006.fuel_message_portal_v3.ts new file mode 100644 index 00000000..5553ca5a --- /dev/null +++ b/packages/solidity-contracts/deploy/devnet/006.fuel_message_portal_v3.ts @@ -0,0 +1,47 @@ +import { MaxUint256 } from 'ethers'; +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; + +import { FuelMessagePortalV3__factory as FuelMessagePortal } from '../../typechain'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { + ethers, + upgrades: { upgradeProxy, erc1967 }, + deployments: { get, save, execute }, + } = hre; + const [deployer] = await ethers.getSigners(); + + const { address: fuelMessagePortalAddress } = await get('FuelMessagePortal'); + + const contract = await upgradeProxy( + fuelMessagePortalAddress, + new FuelMessagePortal(deployer), + { + constructorArgs: [MaxUint256], + } + ); + await contract.waitForDeployment(); + + const address = await contract.getAddress(); + const implementation = await erc1967.getImplementationAddress(address); + + console.log('Deployed FuelMessagePortal at', address); + await save('FuelMessagePortal', { + address, + abi: [...FuelMessagePortal.abi], + implementation, + }); + + await execute( + 'FuelMessagePortal', + { log: true, from: deployer.address }, + 'unpause' + ); + + return true; +}; + +func.tags = ['portal_redeploy']; +func.id = 'fuel_message_portal_redeploy'; +export default func; diff --git a/packages/solidity-contracts/deploy/devnet/007.fuel_message_portal_v3_unpause.ts b/packages/solidity-contracts/deploy/devnet/007.fuel_message_portal_v3_unpause.ts new file mode 100644 index 00000000..c35abbeb --- /dev/null +++ b/packages/solidity-contracts/deploy/devnet/007.fuel_message_portal_v3_unpause.ts @@ -0,0 +1,22 @@ +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { + ethers, + deployments: { execute }, + } = hre; + const [deployer] = await ethers.getSigners(); + + await execute( + 'FuelMessagePortal', + { log: true, from: deployer.address }, + 'unpause' + ); + + return true; +}; + +func.tags = ['portal_unpause']; +func.id = 'portal_unpause'; +export default func; diff --git a/packages/solidity-contracts/deployments/devnet/.migrations.json b/packages/solidity-contracts/deployments/devnet/.migrations.json index 30a2d580..bd0274cc 100644 --- a/packages/solidity-contracts/deployments/devnet/.migrations.json +++ b/packages/solidity-contracts/deployments/devnet/.migrations.json @@ -3,5 +3,6 @@ "fuel_message_portal": 1714255695, "fuel_erc20_gateway_v4": 1714255717, "token": 1714255743, - "register_committer": 1714731217 + "register_committer": 1714731217, + "portal_unpause": 1715106411 } \ No newline at end of file diff --git a/packages/solidity-contracts/deployments/devnet/FuelMessagePortal.json b/packages/solidity-contracts/deployments/devnet/FuelMessagePortal.json index afe6218a..412cca7b 100644 --- a/packages/solidity-contracts/deployments/devnet/FuelMessagePortal.json +++ b/packages/solidity-contracts/deployments/devnet/FuelMessagePortal.json @@ -57,6 +57,11 @@ "name": "MessageDataTooLarge", "type": "error" }, + { + "inputs": [], + "name": "MessageRelayFailed", + "type": "error" + }, { "inputs": [], "name": "UnfinalizedBlock", @@ -683,11 +688,6 @@ "name": "prevRoot", "type": "bytes32" }, - { - "internalType": "uint32", - "name": "height", - "type": "uint32" - }, { "internalType": "uint64", "name": "timestamp", @@ -699,14 +699,24 @@ "type": "uint64" }, { - "internalType": "uint64", - "name": "txCount", - "type": "uint64" + "internalType": "uint32", + "name": "outputMessagesCount", + "type": "uint32" }, { - "internalType": "uint64", - "name": "outputMessagesCount", - "type": "uint64" + "internalType": "uint32", + "name": "consensusParametersVersion", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stateTransitionBytecodeVersion", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "height", + "type": "uint32" }, { "internalType": "bytes32", @@ -717,6 +727,16 @@ "internalType": "bytes32", "name": "outputMessagesRoot", "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "eventInboxRoot", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "txCount", + "type": "uint16" } ], "internalType": "struct FuelBlockHeader", @@ -921,6 +941,6 @@ "type": "function" } ], - "numDeployments": 1, + "numDeployments": 2, "implementation": "0xC9C453fA30cd0c6A2f09Af5e1C32F839Ff7a3DD0" } \ No newline at end of file From fcd21647c1807a41b95a34c62ae7bf392b7bf2d5 Mon Sep 17 00:00:00 2001 From: DefiCake Date: Tue, 7 May 2024 20:38:11 +0200 Subject: [PATCH 07/28] chore: upgrade FuelChainState --- .../.openzeppelin/sepolia.json | 197 ++++++++++++++++++ .../devnet/006.fuel_message_portal_v3.ts | 11 +- .../deploy/devnet/008.chain_state.ts | 46 ++++ .../deploy/devnet/009.chain_state_unpause.ts | 21 ++ .../deployments/devnet/.migrations.json | 7 +- .../deployments/devnet/FuelChainState.json | 20 +- 6 files changed, 292 insertions(+), 10 deletions(-) create mode 100644 packages/solidity-contracts/deploy/devnet/008.chain_state.ts create mode 100644 packages/solidity-contracts/deploy/devnet/009.chain_state_unpause.ts diff --git a/packages/solidity-contracts/.openzeppelin/sepolia.json b/packages/solidity-contracts/.openzeppelin/sepolia.json index d8856461..a519fbd1 100644 --- a/packages/solidity-contracts/.openzeppelin/sepolia.json +++ b/packages/solidity-contracts/.openzeppelin/sepolia.json @@ -3350,6 +3350,203 @@ }, "namespaces": {} } + }, + "b5feea167d06c3eb8552b94bb84496f46ae670c5449e5d110b92b8bb9d4a817b": { + "address": "0x99448d0C551a9B2A5c6280E586c36A8A33BAA968", + "txHash": "0x5fdd5d436bc4626e917a512278c40638d596f97e7998651e82c30d8620da0544", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_paused", + "offset": 0, + "slot": "51", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_roles", + "offset": 0, + "slot": "151", + "type": "t_mapping(t_bytes32,t_struct(RoleData)2324_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:57" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:260" + }, + { + "label": "__gap", + "offset": 0, + "slot": "201", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "251", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "_commitSlots", + "offset": 0, + "slot": "301", + "type": "t_array(t_struct(Commit)9369_storage)240_storage", + "contract": "FuelChainState", + "src": "contracts/fuelchain/FuelChainState.sol:61" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Commit)9369_storage)240_storage": { + "label": "struct Commit[240]", + "numberOfBytes": "15360" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)2324_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_struct(Commit)9369_storage": { + "label": "struct Commit", + "members": [ + { + "label": "blockHash", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "timestamp", + "type": "t_uint32", + "offset": 0, + "slot": "1" + }, + { + "label": "reserved1", + "type": "t_address", + "offset": 4, + "slot": "1" + }, + { + "label": "reserved2", + "type": "t_uint16", + "offset": 24, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(RoleData)2324_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/solidity-contracts/deploy/devnet/006.fuel_message_portal_v3.ts b/packages/solidity-contracts/deploy/devnet/006.fuel_message_portal_v3.ts index 5553ca5a..a2b8028a 100644 --- a/packages/solidity-contracts/deploy/devnet/006.fuel_message_portal_v3.ts +++ b/packages/solidity-contracts/deploy/devnet/006.fuel_message_portal_v3.ts @@ -8,7 +8,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { ethers, upgrades: { upgradeProxy, erc1967 }, - deployments: { get, save, execute }, + deployments: { get, save }, } = hre; const [deployer] = await ethers.getSigners(); @@ -23,6 +23,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { ); await contract.waitForDeployment(); + const tx = contract.deploymentTransaction(); + await tx.wait(); + const address = await contract.getAddress(); const implementation = await erc1967.getImplementationAddress(address); @@ -33,12 +36,6 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { implementation, }); - await execute( - 'FuelMessagePortal', - { log: true, from: deployer.address }, - 'unpause' - ); - return true; }; diff --git a/packages/solidity-contracts/deploy/devnet/008.chain_state.ts b/packages/solidity-contracts/deploy/devnet/008.chain_state.ts new file mode 100644 index 00000000..21eea2fc --- /dev/null +++ b/packages/solidity-contracts/deploy/devnet/008.chain_state.ts @@ -0,0 +1,46 @@ +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; + +import { FuelChainState__factory as FuelChainState } from '../../typechain'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { + ethers, + upgrades: { upgradeProxy, erc1967 }, + deployments: { save, execute, get }, + } = hre; + const [deployer] = await ethers.getSigners(); + + const { address: fuelChainStateAddress } = await get('FuelChainState'); + + console.log('Upgrading FuelChainState...'); + const contract = await upgradeProxy( + fuelChainStateAddress, + new FuelChainState(deployer) + ); + await contract.waitForDeployment(); + const tx = contract.deploymentTransaction(); + await tx.wait(); + + const address = await contract.getAddress(); + const implementation = await erc1967.getImplementationAddress(address); + + console.log('Deployed new implementation at', implementation); + await save('FuelChainState', { + address, + abi: [...FuelChainState.abi], + implementation, + }); + + await execute( + 'FuelChainState', + { log: true, from: deployer.address }, + 'unpause' + ); + + return true; +}; + +func.tags = ['state_redeploy']; +func.id = 'state_redeploy'; +export default func; diff --git a/packages/solidity-contracts/deploy/devnet/009.chain_state_unpause.ts b/packages/solidity-contracts/deploy/devnet/009.chain_state_unpause.ts new file mode 100644 index 00000000..6e32d02f --- /dev/null +++ b/packages/solidity-contracts/deploy/devnet/009.chain_state_unpause.ts @@ -0,0 +1,21 @@ +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { + ethers, + deployments: { execute }, + } = hre; + const [deployer] = await ethers.getSigners(); + await execute( + 'FuelChainState', + { log: true, from: deployer.address }, + 'unpause' + ); + + return true; +}; + +func.tags = ['state_unpause']; +func.id = 'state_unpause'; +export default func; diff --git a/packages/solidity-contracts/deployments/devnet/.migrations.json b/packages/solidity-contracts/deployments/devnet/.migrations.json index bd0274cc..9230bf12 100644 --- a/packages/solidity-contracts/deployments/devnet/.migrations.json +++ b/packages/solidity-contracts/deployments/devnet/.migrations.json @@ -4,5 +4,8 @@ "fuel_erc20_gateway_v4": 1714255717, "token": 1714255743, "register_committer": 1714731217, - "portal_unpause": 1715106411 -} \ No newline at end of file + "fuel_message_portal_redeploy": 1715106411, + "portal_unpause": 1715106411, + "state_redeploy": 1715107035, + "state_unpause": 1715107035 +} diff --git a/packages/solidity-contracts/deployments/devnet/FuelChainState.json b/packages/solidity-contracts/deployments/devnet/FuelChainState.json index 6bd96bcf..bc77f98b 100644 --- a/packages/solidity-contracts/deployments/devnet/FuelChainState.json +++ b/packages/solidity-contracts/deployments/devnet/FuelChainState.json @@ -6,6 +6,11 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [], + "name": "CannotRecommit", + "type": "error" + }, { "inputs": [], "name": "UnknownBlock", @@ -215,6 +220,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "COMMIT_COOLDOWN", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "DEFAULT_ADMIN_ROLE", @@ -523,6 +541,6 @@ "type": "function" } ], - "numDeployments": 1, + "numDeployments": 2, "implementation": "0xba98eDC9AC0B6191180562bF68CE001B1D71C11D" } \ No newline at end of file From d274fe6192857cf6ebcf8d0639d9ef2522030aac Mon Sep 17 00:00:00 2001 From: DefiCake Date: Wed, 8 May 2024 12:14:34 +0200 Subject: [PATCH 08/28] feat: use forc 0.56 --- Forc.lock | 22 +++++++++++++------ fuel-toolchain.toml | 2 +- .../bridge-fungible-token/Forc.toml | 2 +- .../bridge-fungible-token/src/main.sw | 11 ++++------ 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/Forc.lock b/Forc.lock index 6f0a8cbf..1342601c 100644 --- a/Forc.lock +++ b/Forc.lock @@ -3,9 +3,9 @@ name = "bridge_fungible_token" source = "member" dependencies = [ "contract_message_receiver", - "reentrancy", "src_20", "std", + "sway_libs", ] [[package]] @@ -23,23 +23,31 @@ dependencies = [ [[package]] name = "core" -source = "path+from-root-0EE950A4219DB4B4" +source = "path+from-root-03A6E3005278C326" [[package]] -name = "reentrancy" -source = "git+https://github.com/FuelLabs/sway-libs?tag=v0.17.2#5d69f665207158517eba14c35c7d28cb1cb93aa9" +name = "src_20" +source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.2.2#6989cf8224b0d8aabea62f3d3c648fc754948705" dependencies = ["std"] [[package]] -name = "src_20" -source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.2.2#6989cf8224b0d8aabea62f3d3c648fc754948705" +name = "standards" +source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.4.3#6f63eb7dff2458a7d976184e565b5cbf26f61da2" dependencies = ["std"] [[package]] name = "std" -source = "git+https://github.com/fuellabs/sway?tag=v0.54.0#d90cbc8419e47283519e39046c3ea5616e64df84" +source = "git+https://github.com/fuellabs/sway?tag=v0.56.0#b495d0df6956524fd68dab7e062df04d2e581ac3" dependencies = ["core"] +[[package]] +name = "sway_libs" +source = "git+https://github.com/FuelLabs/sway-libs?tag=v0.21.0#6a227ed34c86fe1ebd334dbdfeccf66c43e3915b" +dependencies = [ + "standards", + "std", +] + [[package]] name = "test_deposit_recipient_contract" source = "member" diff --git a/fuel-toolchain.toml b/fuel-toolchain.toml index 9142df94..620f44d2 100644 --- a/fuel-toolchain.toml +++ b/fuel-toolchain.toml @@ -3,4 +3,4 @@ channel = "latest-2023-11-30" [components] fuel-core = "0.26.0" -forc = "0.54.0" +forc = "0.56.0" diff --git a/packages/fungible-token/bridge-fungible-token/Forc.toml b/packages/fungible-token/bridge-fungible-token/Forc.toml index cb922182..ffa25361 100644 --- a/packages/fungible-token/bridge-fungible-token/Forc.toml +++ b/packages/fungible-token/bridge-fungible-token/Forc.toml @@ -6,5 +6,5 @@ name = "bridge_fungible_token" [dependencies] contract_message_receiver = { path = "../../message-predicates/contract-message-receiver" } -reentrancy = { git = "https://github.com/FuelLabs/sway-libs", tag = "v0.17.2" } +sway_libs = { git = "https://github.com/FuelLabs/sway-libs", tag = "v0.21.0" } src_20 = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.2.2" } diff --git a/packages/fungible-token/bridge-fungible-token/src/main.sw b/packages/fungible-token/bridge-fungible-token/src/main.sw index 08abd29e..09b9da7d 100644 --- a/packages/fungible-token/bridge-fungible-token/src/main.sw +++ b/packages/fungible-token/bridge-fungible-token/src/main.sw @@ -32,17 +32,14 @@ use data_structures::{ }; use events::{ClaimRefundEvent, DepositEvent, MetadataEvent, RefundRegisteredEvent, WithdrawalEvent}; use interface::{bridge::Bridge, src7::{Metadata, SRC7}}; -use reentrancy::reentrancy_guard; +use sway_libs::reentrancy::reentrancy_guard; use std::{ asset::{ burn, mint, transfer, }, - call_frames::{ - contract_id, - msg_asset_id, - }, + call_frames::msg_asset_id, constants::ZERO_B256, context::msg_amount, flags::{ @@ -300,7 +297,7 @@ fn _process_deposit(message_data: DepositMessage, msg_idx: u64) { } }; let sub_id = _generate_sub_id_from_metadata(message_data.token_address, message_data.token_id); - let asset_id = AssetId::new(contract_id(), sub_id); + let asset_id = AssetId::new(ContractId::this(), sub_id); let _ = disable_panic_on_overflow(); @@ -376,7 +373,7 @@ fn _process_deposit(message_data: DepositMessage, msg_idx: u64) { #[storage(read, write)] fn _process_metadata(metadata: MetadataMessage) { let sub_id = _generate_sub_id_from_metadata(metadata.token_address, metadata.token_id); - let asset_id = AssetId::new(contract_id(), sub_id); + let asset_id = AssetId::new(ContractId::this(), sub_id); // Important to note: in order to register metadata for an asset, // it must have been deposited first From 8a868b6a87eebafd17d5c30d4645a2343eb5c9bf Mon Sep 17 00:00:00 2001 From: DefiCake Date: Wed, 8 May 2024 13:32:32 +0200 Subject: [PATCH 09/28] feat: add wip, adapt predicate to new sway encoding --- Cargo.lock | 166 +++++++++++------- Cargo.toml | 8 +- .../bridge-fungible-token/Cargo.toml | 2 +- packages/message-predicates/Forc.lock | 4 +- .../contract-message-predicate/Cargo.toml | 3 +- .../contract-message-predicate/script_asm.rs | 19 +- .../src/contract_message_test.sw | 46 ++--- .../contract-message-predicate/src/lib.rs | 40 ++--- ...e__tests__snapshot_predicate_bytecode.snap | 2 +- ...cate__tests__snapshot_script_bytecode.snap | 2 +- .../tests/harness.rs | 6 +- 11 files changed, 169 insertions(+), 129 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e53d7213..a302b7dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -955,6 +955,7 @@ dependencies = [ "encode_unicode", "lazy_static", "libc", + "unicode-width", "windows-sys 0.45.0", ] @@ -2161,9 +2162,9 @@ dependencies = [ [[package]] name = "fuel-asm" -version = "0.48.0" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20bc683784e35f3421aab3dc5a31a94c8ad80f1e9ec614ddddac930b4081cd92" +checksum = "42df651415e443094f86102473b7f9fa23633ab6c3c98dd3f713adde251acf0f" dependencies = [ "bitflags 2.4.0", "fuel-types", @@ -2187,9 +2188,9 @@ dependencies = [ [[package]] name = "fuel-core" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16acbaac42aceb26c704ed078314e7e7f9d1e20d6eaf147cada559e7e9f967ae" +checksum = "6b030e12851d70598e12722886b899e28884d168367fc20d9a809951dd599004" dependencies = [ "anyhow", "async-graphql", @@ -2215,6 +2216,7 @@ dependencies = [ "futures", "hex", "hyper", + "indicatif", "itertools 0.12.0", "rand", "serde", @@ -2223,7 +2225,6 @@ dependencies = [ "strum_macros 0.25.3", "thiserror", "tokio", - "tokio-rayon", "tokio-stream", "tokio-util", "tower-http", @@ -2233,12 +2234,13 @@ dependencies = [ [[package]] name = "fuel-core-chain-config" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23929afd8e279a463941ed18c8a23d9e29df4c3587ba19ad56c68f24c14484f5" +checksum = "d202fe1dfeb98882bdc5a0206a58e469d76fd09d952c4050bb979102bd690398" dependencies = [ "anyhow", "bech32 0.9.1", + "derivative", "fuel-core-storage", "fuel-core-types", "itertools 0.12.0", @@ -2252,9 +2254,9 @@ dependencies = [ [[package]] name = "fuel-core-client" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67d4a6c96cd1827d04361f8b76416273168efc9eb0951293b03bc18e52d409b6" +checksum = "bc636a8706e36c713606ee4226fdef5260e3650ba0e8a57f0fc06258d0078a34" dependencies = [ "anyhow", "cynic", @@ -2276,9 +2278,9 @@ dependencies = [ [[package]] name = "fuel-core-consensus-module" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b1d8ec2205453a563f9ac620867febb711c4ec7a930f063899f8c8673921417" +checksum = "0f99179c08972efffe7628f0ff8d59028218b126347a6f9eba86f71e20966eeb" dependencies = [ "anyhow", "fuel-core-chain-config", @@ -2289,9 +2291,9 @@ dependencies = [ [[package]] name = "fuel-core-database" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a87cc2351d5a3205d4a6673904bb3b876203540595e1746a1f466d5900b3c3e" +checksum = "f5b1fd08a72609ebf0c8106359a37a4b205055be15e9f4fc30a4c0b5f0644c6b" dependencies = [ "anyhow", "derive_more", @@ -2301,12 +2303,11 @@ dependencies = [ [[package]] name = "fuel-core-executor" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e159969d168d4b7cbaa9a55efb842604f0abe116d1baa0b0486c73f2261f63a" +checksum = "1f98d89798007bc781d56e02681144683f5c645ee0725e7717e38694e8e5e31d" dependencies = [ "anyhow", - "fuel-core-chain-config", "fuel-core-storage", "fuel-core-types", "hex", @@ -2317,13 +2318,12 @@ dependencies = [ [[package]] name = "fuel-core-importer" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b858caa4d262891964f55c09f86d6f93d368f7d9a073e5828e02616db88e014" +checksum = "f51837a53f2d8b78a701aee61b99c7f1873f23e864f01f4b4d0644a06e1f7c41" dependencies = [ "anyhow", "derive_more", - "fuel-core-chain-config", "fuel-core-metrics", "fuel-core-storage", "fuel-core-types", @@ -2334,9 +2334,9 @@ dependencies = [ [[package]] name = "fuel-core-metrics" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003381d1f9f5def3685171b340c4bb56d3681897f3baa616aaf6cf7085013462" +checksum = "bacc62bc4fec2fe6a818a1a7145b892bd486d69266190ca8dd31a036a3a327b7" dependencies = [ "axum", "once_cell", @@ -2348,9 +2348,9 @@ dependencies = [ [[package]] name = "fuel-core-p2p" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c513afe591125230e3fd9f6cdf1add00a2aba3f11a19e9e77e020ec14b863b6e" +checksum = "d6496068f0f5736f9e51bba8f8bb04cb83f68df2f6142e410fe62854b47621b3" dependencies = [ "anyhow", "async-trait", @@ -2380,9 +2380,9 @@ dependencies = [ [[package]] name = "fuel-core-poa" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8608758b49855f33c3e6a78917dada96265233096aae04628d6c1ff9fe6d3dca" +checksum = "68d189ecd635688ddc896b44c8497b29c04bb4a3719a24eea0ca9691a6f76d5e" dependencies = [ "anyhow", "async-trait", @@ -2397,9 +2397,9 @@ dependencies = [ [[package]] name = "fuel-core-producer" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c662d29fafeeb686057f3ba1f2cd349e3c437c32d59ae4f6c61400cee26f27e7" +checksum = "4d2901a7ba2c0e724bbb88a3111fdb9844f5faf9f0bd4005944f61f093730b4d" dependencies = [ "anyhow", "async-trait", @@ -2413,9 +2413,9 @@ dependencies = [ [[package]] name = "fuel-core-services" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca69ccc3a055e0a645c7e76e0623feec6945d4cf95b4131a3a1bf1ffc076d1bb" +checksum = "cf2ab4d3931b8cafdb2e69fe8ca97918a168d74c73c070481ca0e552cc37bb93" dependencies = [ "anyhow", "async-trait", @@ -2428,9 +2428,9 @@ dependencies = [ [[package]] name = "fuel-core-storage" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb47f4fabcec096b78137c782895a52aeed134f931256656511b10083cbd967" +checksum = "e039c1c6ebef314c74c34728e1f2199dcf9ede041d6f5c6e11479517c8f4d320" dependencies = [ "anyhow", "derive_more", @@ -2452,18 +2452,18 @@ dependencies = [ [[package]] name = "fuel-core-txpool" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e62e3bf2e4ee38e248131293ad908d8ba82b7d02dff432f68bc49b252eda509" +checksum = "985684e2d67d5018e9227a4f9ed79cac02b23b207e457ee95833ab047769c2ac" dependencies = [ "anyhow", "async-trait", - "fuel-core-chain-config", "fuel-core-metrics", "fuel-core-services", "fuel-core-storage", "fuel-core-types", "futures", + "mockall", "parking_lot", "tokio", "tokio-rayon", @@ -2473,9 +2473,9 @@ dependencies = [ [[package]] name = "fuel-core-types" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385b3c9e9d51ca11e129ec1c713ffd2f4f2f2ad89c16b1808a4c661887a88bfb" +checksum = "cf038dd8df8d3aa665a13295c9ef888ba8118600cccdf8fb4587410e0e102fdf" dependencies = [ "anyhow", "bs58 0.5.0", @@ -2492,9 +2492,9 @@ dependencies = [ [[package]] name = "fuel-core-upgradable-executor" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123e31a87f925f6403cf960e04db1403c4093d0fbacb1a5a8333c2756b980a42" +checksum = "cc54c84a7dc13f76930761ebca391b167caa096dc2bdb2413b5a2400bf65f99d" dependencies = [ "fuel-core-executor", "fuel-core-storage", @@ -2503,9 +2503,9 @@ dependencies = [ [[package]] name = "fuel-crypto" -version = "0.48.0" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6112c726b5254cad831e61db36dcd0d83b28c50180ea22cb8815343fb162526" +checksum = "71cef93970fb8a26d3a683ae211833c6bbf391066887f501bd5859f29992b59a" dependencies = [ "coins-bip32", "coins-bip39", @@ -2524,9 +2524,9 @@ dependencies = [ [[package]] name = "fuel-derive" -version = "0.48.0" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5896603b839f04f27e8bddbae2990dc799fb119f5e62973d6666b2ea1a4b036b" +checksum = "2b85e8e508b26d088262075fcfe9921b7009c931fef1cc55fe1dafb116c99884" dependencies = [ "proc-macro2", "quote", @@ -2536,9 +2536,9 @@ dependencies = [ [[package]] name = "fuel-merkle" -version = "0.48.0" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8f75d97f6d43fbd15aa5ca0d594b33cc59ba5fd73ce42f4a10dfa9288a9a4a4" +checksum = "5198b4eab5a19b0034971da88199dae7dd61806ebd8df366d6af1f17cda2e151" dependencies = [ "derive_more", "digest 0.10.7", @@ -2551,15 +2551,15 @@ dependencies = [ [[package]] name = "fuel-storage" -version = "0.48.0" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6899452bbf8b09d536b0adf98d6a28d1081ce38c3490fa2d8cc1dd47ba153351" +checksum = "fa738e9c244f3f312af09faef108ec9a285f02afcefbc579c19c242cea742dd0" [[package]] name = "fuel-tx" -version = "0.48.0" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305c12d87f47d139505cbbaee1effa7750ce171c9a4362d212f4f7a651902121" +checksum = "8e4b4ea79ffe711af7bbf363b25f383fc6e481e652cf55a5ef8b5a458fcf4ef9" dependencies = [ "bitflags 2.4.0", "derivative", @@ -2570,6 +2570,7 @@ dependencies = [ "fuel-types", "hashbrown 0.14.0", "itertools 0.10.5", + "postcard", "rand", "serde", "serde_json", @@ -2579,9 +2580,9 @@ dependencies = [ [[package]] name = "fuel-types" -version = "0.48.0" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d92d34c6625f0c3b88463f01027e836ba561125f6ccfb1402d12743fc7b2c96" +checksum = "455cf5275d96f6907e81ed1825c4e6a9dd79f7c1c37a4e15134562f83024c7e7" dependencies = [ "fuel-derive", "hex", @@ -2591,9 +2592,9 @@ dependencies = [ [[package]] name = "fuel-vm" -version = "0.48.0" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06f02e86ebf357689e34412af34faf7f0d35a9b8b6ccb2ec42fd369559d6914" +checksum = "8811f949db8ce61cc68dcf81644047df4ee23be55879efcfe9f1aa5adc378965" dependencies = [ "anyhow", "async-trait", @@ -2625,9 +2626,9 @@ dependencies = [ [[package]] name = "fuels" -version = "0.58.0" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765b5ed07397fa814e91a4a2dd76711403b931ae9dc87ddb8f39f5ba0061624f" +checksum = "13f6212d1e08a52222b7120d5a11f350720f5564f2dbf3b825619bd497fdf1bd" dependencies = [ "fuel-core", "fuel-core-client", @@ -2642,9 +2643,9 @@ dependencies = [ [[package]] name = "fuels-accounts" -version = "0.58.0" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f63be865265782b0b70405af3c2881d5ea91bfbc746af198689211e5b2b822" +checksum = "bf220a834d5425d3e54fe867035dafa5e5313358a505b04e48ecde460571bc0e" dependencies = [ "async-trait", "chrono", @@ -2661,15 +2662,14 @@ dependencies = [ "tai64", "thiserror", "tokio", - "tracing", "zeroize", ] [[package]] name = "fuels-code-gen" -version = "0.58.0" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54669c711d1c7d97a6944c13357aa5c2dda0c09d422af8a1cc99eb0752e69c15" +checksum = "b0df90f02675a65a015a5c7ed86865acb9376b34cc93b2c58208f21286badb02" dependencies = [ "Inflector", "fuel-abi-types", @@ -2683,9 +2683,9 @@ dependencies = [ [[package]] name = "fuels-core" -version = "0.58.0" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aa642e56e3c4adcdf57c8211a0ee210eab9c08b35b12ad0f39fc78a60f04a4d" +checksum = "be24620ea84d29b56537b21723c4db0853424d3e75599c0ff7f5eaa3ca96143b" dependencies = [ "async-trait", "bech32 0.9.1", @@ -2703,16 +2703,15 @@ dependencies = [ "itertools 0.12.0", "serde", "serde_json", - "sha2 0.10.8", "thiserror", "uint", ] [[package]] name = "fuels-macros" -version = "0.58.0" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826b05edc9b48e229df70661df98f14c85f598891412e3c942bc72f16bcf29a4" +checksum = "de5713fc740bf297647cdfbed4acc65796b2a3a6e7ab28b9498de3fc89d9b824" dependencies = [ "fuels-code-gen", "itertools 0.12.0", @@ -2724,9 +2723,9 @@ dependencies = [ [[package]] name = "fuels-programs" -version = "0.58.0" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1983fcead46f5c9069873ff53c10a114e0aef325f4032785aef38b19190087f8" +checksum = "fcafe1b5372ed2b97c2550db28262016df80d78286eeb47e999c6bd3fa3a353a" dependencies = [ "async-trait", "bytes", @@ -2744,9 +2743,9 @@ dependencies = [ [[package]] name = "fuels-test-helpers" -version = "0.58.0" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdcb48ed9d79d59bdae86a580a117578f0d76c97bfe8c514a66a2bd455a8ebce" +checksum = "5fb2c6749b65cb6a0e6cfd24f140ed4792df0745195c2bceb2033ad5fefc162b" dependencies = [ "fuel-core", "fuel-core-chain-config", @@ -3523,6 +3522,19 @@ dependencies = [ "serde", ] +[[package]] +name = "indicatif" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + [[package]] name = "inout" version = "0.1.3" @@ -4609,6 +4621,12 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "object" version = "0.31.1" @@ -4985,6 +5003,12 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + [[package]] name = "portpicker" version = "0.1.1" @@ -6830,6 +6854,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" + [[package]] name = "unicode-xid" version = "0.2.4" diff --git a/Cargo.toml b/Cargo.toml index f36b6b37..b48f5813 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,14 +18,14 @@ rust-version = "1.72.0" [workspace.dependencies] # Dependencies from fuel-vm repository: -fuel-asm = "0.48.0" -fuel-tx = "0.48.0" +fuel-asm = "0.49.0" +fuel-tx = "0.49.0" # Dependencies from fuel-core repository: -fuel-core-types = { version = "0.24.3", default-features = false } +fuel-core-types = { version = "0.26.0", default-features = false } # Dependencies from fuels-rs repository: -fuels = { version = "0.58.0", features = ["fuel-core-lib", "legacy_encoding"] } +fuels = { version = "0.60.0", features = ["fuel-core-lib"] } # Third-party dependencies tokio = { version = "1.32.0", features = ["rt", "macros"] } diff --git a/packages/fungible-token/bridge-fungible-token/Cargo.toml b/packages/fungible-token/bridge-fungible-token/Cargo.toml index c9a1e5b8..3ba5bdeb 100644 --- a/packages/fungible-token/bridge-fungible-token/Cargo.toml +++ b/packages/fungible-token/bridge-fungible-token/Cargo.toml @@ -14,7 +14,7 @@ ethers = {version = "=2.0.14"} # Dependencies from fuel-core repository: fuel-core-types = { workspace = true } # Dependencies from fuels-rs repository: -fuels = { workspace = true, features = ["fuel-core-lib", "legacy_encoding"] } +fuels = { workspace = true, features = ["fuel-core-lib"] } hex = "0.4.3" primitive-types = "0.12.1" diff --git a/packages/message-predicates/Forc.lock b/packages/message-predicates/Forc.lock index dbeb750e..934a5e96 100644 --- a/packages/message-predicates/Forc.lock +++ b/packages/message-predicates/Forc.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "core" -source = "path+from-root-C3992B43B72ADB8C" +source = "path+from-root-03A6E3005278C326" [[package]] name = "std" -source = "git+https://github.com/fuellabs/sway?tag=v0.49.1#2ac7030570f22510b0ac2a7b5ddf7baa20bdc0e1" +source = "git+https://github.com/fuellabs/sway?tag=v0.56.0#b495d0df6956524fd68dab7e062df04d2e581ac3" dependencies = ["core"] diff --git a/packages/message-predicates/contract-message-predicate/Cargo.toml b/packages/message-predicates/contract-message-predicate/Cargo.toml index 88a7954e..f5e4ba9c 100644 --- a/packages/message-predicates/contract-message-predicate/Cargo.toml +++ b/packages/message-predicates/contract-message-predicate/Cargo.toml @@ -10,6 +10,7 @@ rust-version = { workspace = true } description = "Script and predicate for relaying contract messages." [dependencies] +fuels = { workspace = true, features = ["fuel-core-lib"] } # Dependencies from the `fuel-vm` repository: fuel-asm = { workspace = true } fuel-tx = { workspace = true } @@ -18,13 +19,13 @@ sha2 = "0.10.6" [dev-dependencies] fuel-core-types = { workspace = true } -fuels = { workspace = true, features = ["fuel-core-lib", "legacy_encoding"] } hex = { workspace = true } insta = "1.28" tokio = { workspace = true } [build-dependencies] sha2 = "0.10.6" +fuels = { workspace = true, features = ["fuel-core-lib"] } # Dependencies from the `fuel-vm` repository: fuel-asm = { workspace = true } diff --git a/packages/message-predicates/contract-message-predicate/script_asm.rs b/packages/message-predicates/contract-message-predicate/script_asm.rs index 24391f5c..ab2012ad 100644 --- a/packages/message-predicates/contract-message-predicate/script_asm.rs +++ b/packages/message-predicates/contract-message-predicate/script_asm.rs @@ -1,15 +1,14 @@ + use fuel_asm::{op, GTFArgs, RegId}; -use sha2::{Digest, Sha256}; -const PROCESS_MESSAGE_FUNCTION_SIGNATURE: &str = "process_message(u64)"; +const PROCESS_MESSAGE_FUNCTION_SIGNATURE: &str = "process_message"; const BYTES_PER_INSTR: u16 = 4; // Gets the bytecode for the message-to-contract script pub fn bytecode() -> Vec { - //calculate function selector - let mut fn_sel_hasher = Sha256::new(); - fn_sel_hasher.update(PROCESS_MESSAGE_FUNCTION_SIGNATURE); - let fn_sel_hash: [u8; 32] = fn_sel_hasher.finalize().into(); + let mut fn_selector_bytes = fuels::core::codec::encode_fn_selector(PROCESS_MESSAGE_FUNCTION_SIGNATURE); + const FN_SEL_BYTES_LEN: u16 = 23; // new encoding: len of the function signature as u64 (8 bytes) + 15 bytes of function signature ("process_message" has 15 characters) + assert_eq!(fn_selector_bytes.len() as u16, FN_SEL_BYTES_LEN); //register names const REG_MEMORY_START_PTR: u8 = 0x10; @@ -33,9 +32,9 @@ pub fn bytecode() -> Vec { let mut script: Vec = vec![ //extend stack for contract call data op::move_(REG_MEMORY_START_PTR, RegId::SP), //REG_MEMORY_START_PTR = stack pointer - op::cfei(32 + 32 + 8 + 8), //extends current call frame stack by 32+32+8+8 bytes [base asset id, contract id, param1, param2] + op::cfei(32 + 32 + 23 + 8), //extends current call frame stack by 32+32+23+8 bytes [base asset id, contract id, fn_selector, param2] op::addi(REG_DATA_PTR, REG_MEMORY_START_PTR, 32), //REG_DATA_PTR = REG_MEMORY_START_PTR + 32bytes [memory start pointer + 32] - op::addi(REG_DATA_FN_SEL_PTR, REG_DATA_PTR, 32 + 4), //REG_DATA_FN_SEL_PTR = REG_DATA_PTR + 32bytes + 4bytes [call data start pointer + 32 + 4] + op::addi(REG_DATA_FN_SEL_PTR, REG_DATA_PTR, 32), //REG_DATA_FN_SEL_PTR = REG_DATA_PTR + 32bytes [call data start pointer + 32] //prep call parameters op::gtf( REG_MSG_AMOUNT, @@ -49,7 +48,7 @@ pub fn bytecode() -> Vec { ), //REG_CONTRACT_ADDR_PTR = memory location of the message data from input[0] op::addi(REG_FN_SELECTOR_PTR, RegId::IS, REF_DATA_START_PTR), //REG_FN_SELECTOR_PTR = function selector at end of program op::mcpi(REG_DATA_PTR, REG_CONTRACT_ADDR_PTR, 32), //32 bytes at REG_DATA_PTR = the 32 bytes at REG_CONTRACT_ADDR_PTR - op::mcpi(REG_DATA_FN_SEL_PTR, REG_FN_SELECTOR_PTR, 4), //4 bytes at REG_DATA_FN_SEL_PTR = the 4 bytes at REG_FN_SELECTOR_PTR + op::mcpi(REG_DATA_FN_SEL_PTR, REG_FN_SELECTOR_PTR, FN_SEL_BYTES_LEN), //23 bytes at REG_DATA_FN_SEL_PTR = the 23 bytes at REG_FN_SELECTOR_PTR //make contract call op::call(REG_DATA_PTR, REG_MSG_AMOUNT, REG_ASSET_PTR, RegId::CGAS), op::ret(RegId::ZERO), @@ -60,6 +59,6 @@ pub fn bytecode() -> Vec { .collect(); //add referenced data (function selector) - script.append(&mut fn_sel_hash[0..4].to_vec()); + script.append(&mut fn_selector_bytes); script } diff --git a/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw b/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw index 8ca9dc47..22785160 100644 --- a/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw +++ b/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw @@ -41,27 +41,33 @@ impl MessageReceiver for Contract { #[storage(read, write)] #[payable] fn process_message(msg_idx: u64) { - storage.counter.write(0); // Temporary fix for: https://github.com/FuelLabs/sway/issues/4634 - storage.counter.write(storage.counter.read() + 1); - // Parse the message data - let data_length = input_message_data_length(msg_idx); - if (data_length >= 32u16) { - let contract_id: b256 = input_message_data(msg_idx, 0).into(); - storage.data1.write(ContractId::from(contract_id)); - } - if (data_length >= 32u16 + 8u16) { - let num: u64 = into_u64(input_message_data(msg_idx, 32)); - storage.data2.write(num); - } - if (data_length >= 32u16 + 8u16 + 32u16) { - let big_num: b256 = input_message_data(msg_idx, 32 + 8).into(); - storage.data3.write(big_num); - } - if (data_length >= 32u16 + 8u16 + 32u16 + 32u16) { - let address: b256 = input_message_data(msg_idx, 32 + 8 + 32).into(); - storage.data4.write(Address::from(address)); - } + log(255); + log(255); + log(255); + log(255); + + // storage.counter.write(0); // Temporary fix for: https://github.com/FuelLabs/sway/issues/4634 + // storage.counter.write(storage.counter.read() + 1); + + // // Parse the message data + // let data_length = input_message_data_length(msg_idx); + // if (data_length >= 32u16) { + // let contract_id: b256 = input_message_data(msg_idx, 0).into(); + // storage.data1.write(ContractId::from(contract_id)); + // } + // if (data_length >= 32u16 + 8u16) { + // let num: u64 = into_u64(input_message_data(msg_idx, 32)); + // storage.data2.write(num); + // } + // if (data_length >= 32u16 + 8u16 + 32u16) { + // let big_num: b256 = input_message_data(msg_idx, 32 + 8).into(); + // storage.data3.write(big_num); + // } + // if (data_length >= 32u16 + 8u16 + 32u16 + 32u16) { + // let address: b256 = input_message_data(msg_idx, 32 + 8 + 32).into(); + // storage.data4.write(Address::from(address)); + // } } } diff --git a/packages/message-predicates/contract-message-predicate/src/lib.rs b/packages/message-predicates/contract-message-predicate/src/lib.rs index 9cdfc42b..9daf5fb6 100644 --- a/packages/message-predicates/contract-message-predicate/src/lib.rs +++ b/packages/message-predicates/contract-message-predicate/src/lib.rs @@ -40,23 +40,23 @@ pub fn predicate_root() -> [u8; 32] { root.into() } -#[cfg(test)] -mod tests { - use super::*; - - // Ensure the predicate bytecode doesn't change - #[test] - fn snapshot_predicate_bytecode() { - let bytecode = predicate_bytecode(); - let serialized = hex::encode(bytecode); - insta::assert_snapshot!(serialized); - } - - // Ensure the script bytecode doesn't change - #[test] - fn snapshot_script_bytecode() { - let bytecode = script_bytecode(); - let serialized = hex::encode(bytecode); - insta::assert_snapshot!(serialized); - } -} +// #[cfg(test)] +// mod tests { +// use super::*; + +// // Ensure the predicate bytecode doesn't change +// #[test] +// fn snapshot_predicate_bytecode() { +// let bytecode = predicate_bytecode(); +// let serialized = hex::encode(bytecode); +// insta::assert_snapshot!(serialized); +// } + +// // Ensure the script bytecode doesn't change +// #[test] +// fn snapshot_script_bytecode() { +// let bytecode = script_bytecode(); +// let serialized = hex::encode(bytecode); +// insta::assert_snapshot!(serialized); +// } +// } diff --git a/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_predicate_bytecode.snap b/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_predicate_bytecode.snap index 01a1a92b..70640a13 100644 --- a/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_predicate_bytecode.snap +++ b/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_predicate_bytecode.snap @@ -3,4 +3,4 @@ source: packages/message-predicates/contract-message-predicate/src/lib.rs assertion_line: 52 expression: serialized --- -1a40500091000020614400096148000342411480504cc04c72580020295134165b501012615c000572680002595d7001616172005b61a010616572455b6400125b5c100b2404000024000000a77be53b9781aa004910c2a06a35b03b6b6909c64937c42a49d1e8185085c86f +1a40500091000020614400096148000342411480504cc04c72580020295134165b501012615c000572680002595d7001616172005b61a010616572455b6400125b5c100b240400002400000059c9f9bacd44c394f08f8279531909080d8cfb7d2a40441f1ddb3a8bbb244422 diff --git a/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_script_bytecode.snap b/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_script_bytecode.snap index 40e3f219..54d44a61 100644 --- a/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_script_bytecode.snap +++ b/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_script_bytecode.snap @@ -3,4 +3,4 @@ source: packages/message-predicates/contract-message-predicate/src/lib.rs assertion_line: 60 expression: serialized --- -1a40500091000050504500205049102461540242614c02485050c02c60453020604940042d45540a24000000b93e6a3d +1a40500091000050504500205049102461540242614c02485050c02c60453020604940042d45540a24000000000000000000000f70726f636573735f6d657373616765 diff --git a/packages/message-predicates/contract-message-predicate/tests/harness.rs b/packages/message-predicates/contract-message-predicate/tests/harness.rs index 594af128..d31150b0 100644 --- a/packages/message-predicates/contract-message-predicate/tests/harness.rs +++ b/packages/message-predicates/contract-message-predicate/tests/harness.rs @@ -39,7 +39,7 @@ mod success { let (wallet, test_contract, contract_input, _, message_inputs) = env::setup_environment(vec![coin], vec![message]).await; - let _receipts = env::relay_message_to_contract( + let tx_id = env::relay_message_to_contract( &wallet, message_inputs[0].clone(), vec![contract_input.clone()], @@ -47,6 +47,10 @@ mod success { ) .await; + let receipts = wallet.provider().unwrap().tx_status(&tx_id).await.unwrap().take_receipts(); + + dbg!(receipts); + // Verify test contract received the message with the correct data let test_contract_id: ContractId = test_contract.contract_id().into(); let methods = test_contract.methods(); From 964c8848faa51343819501d43e18586c1d4cf27f Mon Sep 17 00:00:00 2001 From: DefiCake Date: Thu, 9 May 2024 04:41:57 +0200 Subject: [PATCH 10/28] feat: add wip, predicate script --- .../contract-message-predicate/Cargo.toml | 1 + .../contract-message-predicate/script_asm.rs | 108 +++++++++++----- .../src/contract_message_test.sw | 116 ++++++++++++++---- .../tests/harness.rs | 42 +++++-- .../tests/utils/builder.rs | 2 +- 5 files changed, 204 insertions(+), 65 deletions(-) diff --git a/packages/message-predicates/contract-message-predicate/Cargo.toml b/packages/message-predicates/contract-message-predicate/Cargo.toml index f5e4ba9c..bb352287 100644 --- a/packages/message-predicates/contract-message-predicate/Cargo.toml +++ b/packages/message-predicates/contract-message-predicate/Cargo.toml @@ -26,6 +26,7 @@ tokio = { workspace = true } [build-dependencies] sha2 = "0.10.6" fuels = { workspace = true, features = ["fuel-core-lib"] } +hex = { workspace = true } # Dependencies from the `fuel-vm` repository: fuel-asm = { workspace = true } diff --git a/packages/message-predicates/contract-message-predicate/script_asm.rs b/packages/message-predicates/contract-message-predicate/script_asm.rs index ab2012ad..3ededf54 100644 --- a/packages/message-predicates/contract-message-predicate/script_asm.rs +++ b/packages/message-predicates/contract-message-predicate/script_asm.rs @@ -6,21 +6,21 @@ const BYTES_PER_INSTR: u16 = 4; // Gets the bytecode for the message-to-contract script pub fn bytecode() -> Vec { - let mut fn_selector_bytes = fuels::core::codec::encode_fn_selector(PROCESS_MESSAGE_FUNCTION_SIGNATURE); + let mut fn_selector_bytes = fuels::core::codec::encode_fn_selector("process_message"); const FN_SEL_BYTES_LEN: u16 = 23; // new encoding: len of the function signature as u64 (8 bytes) + 15 bytes of function signature ("process_message" has 15 characters) assert_eq!(fn_selector_bytes.len() as u16, FN_SEL_BYTES_LEN); - //register names - const REG_MEMORY_START_PTR: u8 = 0x10; - const REG_ASSET_PTR: u8 = REG_MEMORY_START_PTR; - const REG_DATA_PTR: u8 = 0x11; - const REG_DATA_FN_SEL_PTR: u8 = 0x12; - const REG_CONTRACT_ADDR_PTR: u8 = 0x13; - const REG_FN_SELECTOR_PTR: u8 = 0x14; - const REG_MSG_AMOUNT: u8 = 0x15; + // //register names + // const REG_MEMORY_START_PTR: u8 = 0x10; + // const REG_ASSET_PTR: u8 = REG_MEMORY_START_PTR; + // const REG_DATA_PTR: u8 = 0x11; + // const REG_DATA_FN_SEL_PTR: u8 = 0x12; + // const REG_CONTRACT_ADDR_PTR: u8 = 0x13; + // const REG_FN_SELECTOR_PTR: u8 = 0x14; + // const REG_MSG_AMOUNT: u8 = 0x15; - //referenced data start pointer - const REF_DATA_START_PTR: u16 = 11 * BYTES_PER_INSTR; + // //referenced data start pointer + // const REF_DATA_START_PTR: u16 = 11 * BYTES_PER_INSTR; /* The following assembly code is intended to do the following: * - Call the function `process_message` on the contract with ID that matches @@ -29,36 +29,82 @@ pub fn bytecode() -> Vec { * * note: this code makes the assumption that all memory at VM initialization is set to 0 */ + // let mut script: Vec = vec![ + // //extend stack for contract call data + // op::move_(REG_MEMORY_START_PTR, RegId::SP), //REG_MEMORY_START_PTR = stack pointer + // op::cfei(32 + 32 + 23 + 8), //extends current call frame stack by 32+32+23+8 bytes [base asset id, contract id, fn_selector, param2] + // op::addi(REG_DATA_PTR, REG_MEMORY_START_PTR, 32), //REG_DATA_PTR = REG_MEMORY_START_PTR + 32bytes [memory start pointer + 32] + // op::addi(REG_DATA_FN_SEL_PTR, REG_DATA_PTR, 32), //REG_DATA_FN_SEL_PTR = REG_DATA_PTR + 32bytes [call data start pointer + 32] + // //prep call parameters + // op::gtf( + // REG_MSG_AMOUNT, + // RegId::ZERO, + // GTFArgs::InputMessageAmount.into(), + // ), //REG_MSG_AMOUNT = amount value of message from input[0] + // op::gtf( + // REG_CONTRACT_ADDR_PTR, + // RegId::ZERO, + // GTFArgs::InputMessageData.into(), + // ), //REG_CONTRACT_ADDR_PTR = memory location of the message data from input[0] + // op::addi(REG_FN_SELECTOR_PTR, RegId::IS, REF_DATA_START_PTR), //REG_FN_SELECTOR_PTR = function selector at end of program + // op::mcpi(REG_DATA_PTR, REG_CONTRACT_ADDR_PTR, 32), //32 bytes at REG_DATA_PTR = the 32 bytes at REG_CONTRACT_ADDR_PTR + // op::mcpi(REG_DATA_FN_SEL_PTR, REG_FN_SELECTOR_PTR, FN_SEL_BYTES_LEN), //23 bytes at REG_DATA_FN_SEL_PTR = the 23 bytes at REG_FN_SELECTOR_PTR + // //make contract call + // op::call(REG_DATA_PTR, REG_MSG_AMOUNT, REG_ASSET_PTR, RegId::CGAS), + // op::ret(RegId::ZERO), + // //referenced data (function selector) + // //00000000 + // ] + // .into_iter() + // .collect(); + + // //add referenced data (function selector) + // script.append(&mut fn_selector_bytes); + // script + + //register names + const REG_MEMORY_START_PTR: u8 = 0x10; + const REG_DATA_PTR: u8 = 0x11; + const REG_CONTRACT_ADDR_PTR: u8 = 0x12; + const REG_FN_SELECTOR_PTR: u8 = 0x13; + const REG_DATA_CONTRACT_PTR: u8 = 0x14; + const REG_DATA_FN_SELECTOR_PTR: u8 = 0x15; + const REG_DATA_CALLDATA_PTR: u8 = 0x16; + const REG_CALLDATA_PTR: u8 = 0x17; + + //referenced data start pointer + const REF_DATA_START_PTR: u16 = 14 * BYTES_PER_INSTR; + let mut script: Vec = vec![ - //extend stack for contract call data op::move_(REG_MEMORY_START_PTR, RegId::SP), //REG_MEMORY_START_PTR = stack pointer - op::cfei(32 + 32 + 23 + 8), //extends current call frame stack by 32+32+23+8 bytes [base asset id, contract id, fn_selector, param2] - op::addi(REG_DATA_PTR, REG_MEMORY_START_PTR, 32), //REG_DATA_PTR = REG_MEMORY_START_PTR + 32bytes [memory start pointer + 32] - op::addi(REG_DATA_FN_SEL_PTR, REG_DATA_PTR, 32), //REG_DATA_FN_SEL_PTR = REG_DATA_PTR + 32bytes [call data start pointer + 32] - //prep call parameters - op::gtf( - REG_MSG_AMOUNT, - RegId::ZERO, - GTFArgs::InputMessageAmount.into(), - ), //REG_MSG_AMOUNT = amount value of message from input[0] + op::cfei(320), + op::addi(REG_DATA_PTR, REG_MEMORY_START_PTR, 32), + op::gtf( REG_CONTRACT_ADDR_PTR, RegId::ZERO, GTFArgs::InputMessageData.into(), ), //REG_CONTRACT_ADDR_PTR = memory location of the message data from input[0] - op::addi(REG_FN_SELECTOR_PTR, RegId::IS, REF_DATA_START_PTR), //REG_FN_SELECTOR_PTR = function selector at end of program - op::mcpi(REG_DATA_PTR, REG_CONTRACT_ADDR_PTR, 32), //32 bytes at REG_DATA_PTR = the 32 bytes at REG_CONTRACT_ADDR_PTR - op::mcpi(REG_DATA_FN_SEL_PTR, REG_FN_SELECTOR_PTR, FN_SEL_BYTES_LEN), //23 bytes at REG_DATA_FN_SEL_PTR = the 23 bytes at REG_FN_SELECTOR_PTR - //make contract call - op::call(REG_DATA_PTR, REG_MSG_AMOUNT, REG_ASSET_PTR, RegId::CGAS), + op::addi(REG_DATA_CONTRACT_PTR, REG_DATA_PTR, 8), + op::mcpi(REG_DATA_PTR, REG_CONTRACT_ADDR_PTR, 32), + + op::addi(REG_FN_SELECTOR_PTR, RegId::IS, REF_DATA_START_PTR), + op::addi(REG_DATA_FN_SELECTOR_PTR, REG_DATA_PTR, 32), + op::sw(REG_DATA_FN_SELECTOR_PTR, REG_FN_SELECTOR_PTR, 0), + + op::addi(REG_CALLDATA_PTR, RegId::IS, REF_DATA_START_PTR + 23), + op::addi(REG_DATA_CALLDATA_PTR, REG_DATA_PTR, 40), + op::sw(REG_DATA_CALLDATA_PTR, REG_CALLDATA_PTR, 0), + + op::call(REG_DATA_PTR, RegId::ZERO, RegId::ZERO, RegId::CGAS), op::ret(RegId::ZERO), - //referenced data (function selector) - //00000000 ] - .into_iter() - .collect(); + .into_iter() + .collect(); - //add referenced data (function selector) script.append(&mut fn_selector_bytes); + script.append(&mut 0u64.to_be_bytes().to_vec()); + + script } diff --git a/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw b/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw index 22785160..27dacc17 100644 --- a/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw +++ b/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw @@ -4,6 +4,7 @@ use contract_message_receiver::MessageReceiver; use std::bytes::Bytes; use std::constants::ZERO_B256; use std::inputs::{input_message_data, input_message_data_length}; +use std::call_frames::{first_param, second_param, called_method}; storage { counter: u64 = 0, @@ -27,6 +28,57 @@ abi VerifyMessageData { fn test_data4() -> Address; } +abi MyCallerContract { + #[storage(read,write)] + fn call_low_level_call( + target: ContractId, + function_selector: Bytes, + calldata: Bytes, + ); +} + +impl MyCallerContract for Contract { + + #[storage(read,write)] + fn call_low_level_call( + target: ContractId, + function_selector: Bytes, + calldata: Bytes, + ) { + let payload = create_payload(target, function_selector, calldata); + + log(function_selector); + log(calldata); + log(payload); + + } + +} + +fn create_payload( + target: ContractId, + function_selector: Bytes, + call_data: Bytes, +) -> Bytes { + /* + packs args according to spec (https://github.com/FuelLabs/fuel-specs/blob/master/src/vm/instruction_set.md#call-call-contract) : + + bytes type value description + 32 byte[32] to Contract ID to call. + 8 byte[8] param1 First parameter (function selector pointer) + 8 byte[8] param2 Second parameter (encoded arguments pointer) + */ + Bytes::from(encode(( + target, + asm(a: function_selector.ptr()) { + a: u64 + }, + asm(a: call_data.ptr()) { + a: u64 + }, + ))) +} + // Converts a Bytes type to u64 // TODO: remove once an [into(self) -> u64] is added for the Bytes type fn into_u64(b: Bytes) -> u64 { @@ -41,33 +93,28 @@ impl MessageReceiver for Contract { #[storage(read, write)] #[payable] fn process_message(msg_idx: u64) { + log(msg_idx); + storage.counter.write(0); // Temporary fix for: https://github.com/FuelLabs/sway/issues/4634 + storage.counter.write(storage.counter.read() + 1); - log(255); - log(255); - log(255); - log(255); - - // storage.counter.write(0); // Temporary fix for: https://github.com/FuelLabs/sway/issues/4634 - // storage.counter.write(storage.counter.read() + 1); - - // // Parse the message data - // let data_length = input_message_data_length(msg_idx); - // if (data_length >= 32u16) { - // let contract_id: b256 = input_message_data(msg_idx, 0).into(); - // storage.data1.write(ContractId::from(contract_id)); - // } - // if (data_length >= 32u16 + 8u16) { - // let num: u64 = into_u64(input_message_data(msg_idx, 32)); - // storage.data2.write(num); - // } - // if (data_length >= 32u16 + 8u16 + 32u16) { - // let big_num: b256 = input_message_data(msg_idx, 32 + 8).into(); - // storage.data3.write(big_num); - // } - // if (data_length >= 32u16 + 8u16 + 32u16 + 32u16) { - // let address: b256 = input_message_data(msg_idx, 32 + 8 + 32).into(); - // storage.data4.write(Address::from(address)); - // } + // Parse the message data + let data_length = input_message_data_length(msg_idx); + if (data_length >= 32u16) { + let contract_id: b256 = input_message_data(msg_idx, 0).into(); + storage.data1.write(ContractId::from(contract_id)); + } + if (data_length >= 32u16 + 8u16) { + let num: u64 = into_u64(input_message_data(msg_idx, 32)); + storage.data2.write(num); + } + if (data_length >= 32u16 + 8u16 + 32u16) { + let big_num: b256 = input_message_data(msg_idx, 32 + 8).into(); + storage.data3.write(big_num); + } + if (data_length >= 32u16 + 8u16 + 32u16 + 32u16) { + let address: b256 = input_message_data(msg_idx, 32 + 8 + 32).into(); + storage.data4.write(Address::from(address)); + } } } @@ -98,3 +145,20 @@ impl VerifyMessageData for Contract { storage.data4.read() } } + +#[fallback, storage(read)] +fn fallback() { + log(255u64); + log(254u64); + log(253u64); + + let first_param = first_param(); + log(first_param); + + let second_param = second_param(); + log(second_param); + + let called_method = called_method(); + + log(called_method); +} \ No newline at end of file diff --git a/packages/message-predicates/contract-message-predicate/tests/harness.rs b/packages/message-predicates/contract-message-predicate/tests/harness.rs index d31150b0..a9df77db 100644 --- a/packages/message-predicates/contract-message-predicate/tests/harness.rs +++ b/packages/message-predicates/contract-message-predicate/tests/harness.rs @@ -6,14 +6,12 @@ mod utils { // Test that input messages can be relayed to a contract // and that the contract can successfully parse the message data mod success { - use std::str::FromStr; + use std::{str::FromStr, u64}; use crate::utils::{builder, environment as env}; - use fuel_tx::Bytes32; + use fuel_tx::{Bytes32, Receipt}; use fuels::{ - prelude::{Address, AssetId, ContractId}, - test_helpers::DEFAULT_COIN_AMOUNT, - types::Bits256, + core::codec::calldata, prelude::{Address, AssetId, ContractId}, programs::call_response::FuelCallResponse, test_helpers::DEFAULT_COIN_AMOUNT, types::{transaction_builders::{BuildableTransaction, ScriptTransactionBuilder, TransactionBuilder}, Bits256, Bytes} }; pub const RANDOM_WORD: u64 = 54321u64; @@ -47,12 +45,42 @@ mod success { ) .await; + // let call_handler = test_contract.methods().process_message(u64::MAX); + // let mut tb: ScriptTransactionBuilder = call_handler.transaction_builder().await.unwrap(); + + // dbg!(hex::encode(tb.script)); + // dbg!(hex::encode(tb.script_data)); + + // let fn_selector_bytes = fuels::core::codec::encode_fn_selector("process_message"); + // dbg!(hex::encode(fn_selector_bytes.clone())); + + let receipts = wallet.provider().unwrap().tx_status(&tx_id).await.unwrap().take_receipts(); - dbg!(receipts); + for receipt in receipts.clone() { + if let Receipt::LogData{data, ..} = receipt { + dbg!(hex::encode(data.unwrap())); + } + } + dbg!(&receipts); // Verify test contract received the message with the correct data let test_contract_id: ContractId = test_contract.contract_id().into(); + // dbg!(hex::encode(test_contract_id.clone())); + + // let low_level_call_receipts = test_contract.methods().call_low_level_call( + // test_contract_id, + // Bytes(fn_selector_bytes), + // Bytes(calldata!(u64::MAX).unwrap()) + // ).call().await.unwrap().receipts; + + // for receipt in low_level_call_receipts.clone() { + // if let Receipt::LogData{data, ..} = receipt { + // dbg!(hex::encode(data.unwrap())); + // } + // } + // // dbg!(&low_level_call_receipts); + let methods = test_contract.methods(); let test_contract_counter = methods.test_counter().call().await.unwrap().value; let test_contract_data1 = methods.test_data1().call().await.unwrap().value; @@ -71,7 +99,7 @@ mod success { .get_contract_asset_balance(test_contract.contract_id(), AssetId::default()) .await .unwrap(); - assert_eq!(test_contract_balance, 100); + assert_eq!(test_contract_balance, 0); } #[tokio::test] diff --git a/packages/message-predicates/contract-message-predicate/tests/utils/builder.rs b/packages/message-predicates/contract-message-predicate/tests/utils/builder.rs index 88f192f2..c0f81016 100644 --- a/packages/message-predicates/contract-message-predicate/tests/utils/builder.rs +++ b/packages/message-predicates/contract-message-predicate/tests/utils/builder.rs @@ -86,7 +86,7 @@ pub async fn build_contract_message_tx( asset_id: AssetId::default(), }); - let tx_policies = TxPolicies::new(Some(0), None, None, None, Some(30_000)); + let tx_policies = TxPolicies::new(Some(0), None, None, None, Some(300_000)); let mut builder = ScriptTransactionBuilder::default() .with_inputs(tx_inputs.clone()) From 1ccba7b26f193f48d3167a8141be88e4fd69ebef Mon Sep 17 00:00:00 2001 From: DefiCake Date: Mon, 13 May 2024 20:52:42 +0200 Subject: [PATCH 11/28] chore: cleanup and document script --- .../contract-message-predicate/script_asm.rs | 85 ++++--------------- .../tests/harness.rs | 69 ++++----------- 2 files changed, 33 insertions(+), 121 deletions(-) diff --git a/packages/message-predicates/contract-message-predicate/script_asm.rs b/packages/message-predicates/contract-message-predicate/script_asm.rs index 3ededf54..ab93c09e 100644 --- a/packages/message-predicates/contract-message-predicate/script_asm.rs +++ b/packages/message-predicates/contract-message-predicate/script_asm.rs @@ -6,95 +6,41 @@ const BYTES_PER_INSTR: u16 = 4; // Gets the bytecode for the message-to-contract script pub fn bytecode() -> Vec { - let mut fn_selector_bytes = fuels::core::codec::encode_fn_selector("process_message"); + let mut fn_selector_bytes = fuels::core::codec::encode_fn_selector(PROCESS_MESSAGE_FUNCTION_SIGNATURE); const FN_SEL_BYTES_LEN: u16 = 23; // new encoding: len of the function signature as u64 (8 bytes) + 15 bytes of function signature ("process_message" has 15 characters) assert_eq!(fn_selector_bytes.len() as u16, FN_SEL_BYTES_LEN); - // //register names - // const REG_MEMORY_START_PTR: u8 = 0x10; - // const REG_ASSET_PTR: u8 = REG_MEMORY_START_PTR; - // const REG_DATA_PTR: u8 = 0x11; - // const REG_DATA_FN_SEL_PTR: u8 = 0x12; - // const REG_CONTRACT_ADDR_PTR: u8 = 0x13; - // const REG_FN_SELECTOR_PTR: u8 = 0x14; - // const REG_MSG_AMOUNT: u8 = 0x15; - - // //referenced data start pointer - // const REF_DATA_START_PTR: u16 = 11 * BYTES_PER_INSTR; - - /* The following assembly code is intended to do the following: - * - Call the function `process_message` on the contract with ID that matches - * the first 32 bytes in the message data field, while forwarding the exact - * amount of base asset specified in the `InputMessage` `amount` field - * - * note: this code makes the assumption that all memory at VM initialization is set to 0 - */ - // let mut script: Vec = vec![ - // //extend stack for contract call data - // op::move_(REG_MEMORY_START_PTR, RegId::SP), //REG_MEMORY_START_PTR = stack pointer - // op::cfei(32 + 32 + 23 + 8), //extends current call frame stack by 32+32+23+8 bytes [base asset id, contract id, fn_selector, param2] - // op::addi(REG_DATA_PTR, REG_MEMORY_START_PTR, 32), //REG_DATA_PTR = REG_MEMORY_START_PTR + 32bytes [memory start pointer + 32] - // op::addi(REG_DATA_FN_SEL_PTR, REG_DATA_PTR, 32), //REG_DATA_FN_SEL_PTR = REG_DATA_PTR + 32bytes [call data start pointer + 32] - // //prep call parameters - // op::gtf( - // REG_MSG_AMOUNT, - // RegId::ZERO, - // GTFArgs::InputMessageAmount.into(), - // ), //REG_MSG_AMOUNT = amount value of message from input[0] - // op::gtf( - // REG_CONTRACT_ADDR_PTR, - // RegId::ZERO, - // GTFArgs::InputMessageData.into(), - // ), //REG_CONTRACT_ADDR_PTR = memory location of the message data from input[0] - // op::addi(REG_FN_SELECTOR_PTR, RegId::IS, REF_DATA_START_PTR), //REG_FN_SELECTOR_PTR = function selector at end of program - // op::mcpi(REG_DATA_PTR, REG_CONTRACT_ADDR_PTR, 32), //32 bytes at REG_DATA_PTR = the 32 bytes at REG_CONTRACT_ADDR_PTR - // op::mcpi(REG_DATA_FN_SEL_PTR, REG_FN_SELECTOR_PTR, FN_SEL_BYTES_LEN), //23 bytes at REG_DATA_FN_SEL_PTR = the 23 bytes at REG_FN_SELECTOR_PTR - // //make contract call - // op::call(REG_DATA_PTR, REG_MSG_AMOUNT, REG_ASSET_PTR, RegId::CGAS), - // op::ret(RegId::ZERO), - // //referenced data (function selector) - // //00000000 - // ] - // .into_iter() - // .collect(); - - // //add referenced data (function selector) - // script.append(&mut fn_selector_bytes); - // script - //register names const REG_MEMORY_START_PTR: u8 = 0x10; const REG_DATA_PTR: u8 = 0x11; const REG_CONTRACT_ADDR_PTR: u8 = 0x12; const REG_FN_SELECTOR_PTR: u8 = 0x13; - const REG_DATA_CONTRACT_PTR: u8 = 0x14; - const REG_DATA_FN_SELECTOR_PTR: u8 = 0x15; - const REG_DATA_CALLDATA_PTR: u8 = 0x16; - const REG_CALLDATA_PTR: u8 = 0x17; + const REG_DATA_FN_SELECTOR_PTR: u8 = 0x14; + const REG_DATA_CALLDATA_PTR: u8 = 0x15; + const REG_CALLDATA_PTR: u8 = 0x16; //referenced data start pointer - const REF_DATA_START_PTR: u16 = 14 * BYTES_PER_INSTR; + const REF_DATA_START_PTR: u16 = 13 * BYTES_PER_INSTR; let mut script: Vec = vec![ op::move_(REG_MEMORY_START_PTR, RegId::SP), //REG_MEMORY_START_PTR = stack pointer - op::cfei(320), - op::addi(REG_DATA_PTR, REG_MEMORY_START_PTR, 32), + op::cfei(32 + 32 + 8 + 8), //extends current call frame stack by 32+32+8+8 bytes [base asset id, contract id, param1, param2] + op::addi(REG_DATA_PTR, REG_MEMORY_START_PTR, 32), //REG_DATA_PTR = REG_MEMORY_START_PTR + 32bytes [memory start pointer + 32] op::gtf( REG_CONTRACT_ADDR_PTR, RegId::ZERO, GTFArgs::InputMessageData.into(), ), //REG_CONTRACT_ADDR_PTR = memory location of the message data from input[0] - op::addi(REG_DATA_CONTRACT_PTR, REG_DATA_PTR, 8), - op::mcpi(REG_DATA_PTR, REG_CONTRACT_ADDR_PTR, 32), + op::mcpi(REG_DATA_PTR, REG_CONTRACT_ADDR_PTR, 32), // REG_DATA[0..31] = REG_CONTRACT_ADDR_PTR[0..32] op::addi(REG_FN_SELECTOR_PTR, RegId::IS, REF_DATA_START_PTR), - op::addi(REG_DATA_FN_SELECTOR_PTR, REG_DATA_PTR, 32), - op::sw(REG_DATA_FN_SELECTOR_PTR, REG_FN_SELECTOR_PTR, 0), + op::addi(REG_DATA_FN_SELECTOR_PTR, REG_DATA_PTR, 32), // REG_DATA_FN_SELECTOR_PTR = REG_DATA_PTR + 32 + op::sw(REG_DATA_FN_SELECTOR_PTR, REG_FN_SELECTOR_PTR, 0), // REG_DATA[32..39] = (End of IS)[0..7] = (len of "process_message") - op::addi(REG_CALLDATA_PTR, RegId::IS, REF_DATA_START_PTR + 23), - op::addi(REG_DATA_CALLDATA_PTR, REG_DATA_PTR, 40), - op::sw(REG_DATA_CALLDATA_PTR, REG_CALLDATA_PTR, 0), + op::addi(REG_CALLDATA_PTR, RegId::IS, REF_DATA_START_PTR + 23), // REG_DATA_FN_SELECTOR_PTR = REG_DATA_PTR + 32 + 23 + op::addi(REG_DATA_CALLDATA_PTR, REG_DATA_PTR, 40), // REG_DATA_FN_SELECTOR_PTR = REG_DATA_PTR + 40 + op::sw(REG_DATA_CALLDATA_PTR, REG_CALLDATA_PTR, 0), // REG_DATA[40..47] = (End of IS)[23..30] = msg_idx = 0 op::call(REG_DATA_PTR, RegId::ZERO, RegId::ZERO, RegId::CGAS), op::ret(RegId::ZERO), @@ -102,8 +48,9 @@ pub fn bytecode() -> Vec { .into_iter() .collect(); - script.append(&mut fn_selector_bytes); - script.append(&mut 0u64.to_be_bytes().to_vec()); + // At the tail of the script, after the return statement, embed: + script.append(&mut fn_selector_bytes); // 23 bytes for function selector + script.append(&mut 0u64.to_be_bytes().to_vec()); // 8 bytes of msg_idx script diff --git a/packages/message-predicates/contract-message-predicate/tests/harness.rs b/packages/message-predicates/contract-message-predicate/tests/harness.rs index a9df77db..a993f53a 100644 --- a/packages/message-predicates/contract-message-predicate/tests/harness.rs +++ b/packages/message-predicates/contract-message-predicate/tests/harness.rs @@ -9,9 +9,9 @@ mod success { use std::{str::FromStr, u64}; use crate::utils::{builder, environment as env}; - use fuel_tx::{Bytes32, Receipt}; + use fuel_tx::Bytes32; use fuels::{ - core::codec::calldata, prelude::{Address, AssetId, ContractId}, programs::call_response::FuelCallResponse, test_helpers::DEFAULT_COIN_AMOUNT, types::{transaction_builders::{BuildableTransaction, ScriptTransactionBuilder, TransactionBuilder}, Bits256, Bytes} + prelude::{Address, AssetId, ContractId}, test_helpers::DEFAULT_COIN_AMOUNT, types::Bits256 }; pub const RANDOM_WORD: u64 = 54321u64; @@ -37,7 +37,12 @@ mod success { let (wallet, test_contract, contract_input, _, message_inputs) = env::setup_environment(vec![coin], vec![message]).await; - let tx_id = env::relay_message_to_contract( + let test_contract_id: ContractId = test_contract.contract_id().into(); + let methods = test_contract.methods(); + + let prev_counter = methods.test_counter().simulate().await.unwrap().value; + + let _tx_id = env::relay_message_to_contract( &wallet, message_inputs[0].clone(), vec![contract_input.clone()], @@ -45,43 +50,7 @@ mod success { ) .await; - // let call_handler = test_contract.methods().process_message(u64::MAX); - // let mut tb: ScriptTransactionBuilder = call_handler.transaction_builder().await.unwrap(); - - // dbg!(hex::encode(tb.script)); - // dbg!(hex::encode(tb.script_data)); - - // let fn_selector_bytes = fuels::core::codec::encode_fn_selector("process_message"); - // dbg!(hex::encode(fn_selector_bytes.clone())); - - - let receipts = wallet.provider().unwrap().tx_status(&tx_id).await.unwrap().take_receipts(); - - for receipt in receipts.clone() { - if let Receipt::LogData{data, ..} = receipt { - dbg!(hex::encode(data.unwrap())); - } - } - dbg!(&receipts); - // Verify test contract received the message with the correct data - let test_contract_id: ContractId = test_contract.contract_id().into(); - // dbg!(hex::encode(test_contract_id.clone())); - - // let low_level_call_receipts = test_contract.methods().call_low_level_call( - // test_contract_id, - // Bytes(fn_selector_bytes), - // Bytes(calldata!(u64::MAX).unwrap()) - // ).call().await.unwrap().receipts; - - // for receipt in low_level_call_receipts.clone() { - // if let Receipt::LogData{data, ..} = receipt { - // dbg!(hex::encode(data.unwrap())); - // } - // } - // // dbg!(&low_level_call_receipts); - - let methods = test_contract.methods(); let test_contract_counter = methods.test_counter().call().await.unwrap().value; let test_contract_data1 = methods.test_data1().call().await.unwrap().value; let test_contract_data2 = methods.test_data2().call().await.unwrap().value; @@ -94,12 +63,8 @@ mod success { assert_eq!(test_contract_data4, data_address); // Verify the message value was received by the test contract - let provider = wallet.provider().unwrap(); - let test_contract_balance = provider - .get_contract_asset_balance(test_contract.contract_id(), AssetId::default()) - .await - .unwrap(); - assert_eq!(test_contract_balance, 0); + let counter = methods.test_counter().simulate().await.unwrap().value; + assert_eq!(counter, prev_counter + 1); } #[tokio::test] @@ -116,6 +81,11 @@ mod success { env::setup_environment(vec![coin], vec![message1, message2]).await; let provider = wallet.provider().unwrap(); + let test_contract_id: ContractId = test_contract.contract_id().into(); + let methods = test_contract.methods(); + + let prev_counter = methods.test_counter().simulate().await.unwrap().value; + let tx = builder::build_contract_message_tx( message_inputs[0].clone(), &[message_inputs[1].clone(), contract_input.clone()], @@ -130,8 +100,6 @@ mod success { .expect("Transaction failed"); // Verify test contract received the message with the correct data - let test_contract_id: ContractId = test_contract.contract_id().into(); - let methods = test_contract.methods(); let test_contract_counter = methods.test_counter().call().await.unwrap().value; let test_contract_data1 = methods.test_data1().call().await.unwrap().value; let test_contract_data2 = methods.test_data2().call().await.unwrap().value; @@ -144,11 +112,8 @@ mod success { assert_eq!(test_contract_data4, data_address); // Verify the message values were received by the test contract - let test_contract_balance = provider - .get_contract_asset_balance(test_contract.contract_id(), AssetId::default()) - .await - .unwrap(); - assert_eq!(test_contract_balance, 100); + let counter = methods.test_counter().simulate().await.unwrap().value; + assert_eq!(counter, prev_counter + 1); } } From 5e3b74d08f245e89339fac50586628baae8e314f Mon Sep 17 00:00:00 2001 From: DefiCake Date: Mon, 13 May 2024 20:57:36 +0200 Subject: [PATCH 12/28] test: remove base asset check from test --- .../bridge-fungible-token/tests/functions/bridge/mod.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/fungible-token/bridge-fungible-token/tests/functions/bridge/mod.rs b/packages/fungible-token/bridge-fungible-token/tests/functions/bridge/mod.rs index bd09d2ae..6b855836 100644 --- a/packages/fungible-token/bridge-fungible-token/tests/functions/bridge/mod.rs +++ b/packages/fungible-token/bridge-fungible-token/tests/functions/bridge/mod.rs @@ -64,8 +64,6 @@ mod success { ) .await; - let provider = wallet.provider().expect("Needs provider"); - // Relay the test message to the bridge contract let tx_id = relay_message_to_contract( &wallet, @@ -87,14 +85,9 @@ mod success { .decode_logs_with_type::(&receipts) .unwrap(); - let asset_balance = - contract_balance(provider, bridge.contract_id(), AssetId::default()).await; let balance = wallet_balance(&wallet, &get_asset_id(bridge.contract_id(), &token_address)).await; - // Verify the message value was received by the bridge contract - assert_eq!(asset_balance, MESSAGE_AMOUNT); - // Verify that no tokens were minted for message.data.to assert_eq!(balance, 0); From d171ef721e51415111cdc87f58ed3f58aa2b81e2 Mon Sep 17 00:00:00 2001 From: DefiCake Date: Mon, 13 May 2024 21:08:21 +0200 Subject: [PATCH 13/28] test: remove asset balance check on sway bridge unit tests --- .../tests/functions/bridge/mod.rs | 11 ++----- .../tests/functions/message_receiver/mod.rs | 31 ++----------------- 2 files changed, 4 insertions(+), 38 deletions(-) diff --git a/packages/fungible-token/bridge-fungible-token/tests/functions/bridge/mod.rs b/packages/fungible-token/bridge-fungible-token/tests/functions/bridge/mod.rs index 6b855836..067f3c04 100644 --- a/packages/fungible-token/bridge-fungible-token/tests/functions/bridge/mod.rs +++ b/packages/fungible-token/bridge-fungible-token/tests/functions/bridge/mod.rs @@ -1,11 +1,11 @@ use crate::utils::{ constants::{ - BRIDGED_TOKEN, BRIDGED_TOKEN_DECIMALS, BRIDGED_TOKEN_ID, FROM, MESSAGE_AMOUNT, + BRIDGED_TOKEN, BRIDGED_TOKEN_DECIMALS, BRIDGED_TOKEN_ID, FROM, PROXY_TOKEN_DECIMALS, }, interface::bridge::withdraw, setup::{ - contract_balance, create_deposit_message, create_token, create_wallet, decode_hex, + create_deposit_message, create_token, create_wallet, decode_hex, encode_hex, parse_output_message_data, relay_message_to_contract, setup_environment, wallet_balance, BridgeFungibleTokenContractConfigurables, BridgingConfig, }, @@ -338,8 +338,6 @@ mod success { ) .await; - let provider = wallet.provider().expect("Needs provider"); - // Relay the test message to the bridge contract let tx_id = relay_message_to_contract( &wallet, @@ -364,14 +362,9 @@ mod success { } } - let asset_balance = - contract_balance(provider, bridge.contract_id(), AssetId::default()).await; let balance = wallet_balance(&wallet, &get_asset_id(bridge.contract_id(), BRIDGED_TOKEN)).await; - // Verify the message value was received by the bridge contract - assert_eq!(asset_balance, MESSAGE_AMOUNT); - // Check that wallet now has bridged coins assert_eq!(balance, amount); diff --git a/packages/fungible-token/bridge-fungible-token/tests/functions/message_receiver/mod.rs b/packages/fungible-token/bridge-fungible-token/tests/functions/message_receiver/mod.rs index 4a6ec707..20df855a 100644 --- a/packages/fungible-token/bridge-fungible-token/tests/functions/message_receiver/mod.rs +++ b/packages/fungible-token/bridge-fungible-token/tests/functions/message_receiver/mod.rs @@ -13,20 +13,18 @@ use std::str::FromStr; mod success { use super::*; use crate::utils::interface::src20::total_supply; - use crate::utils::{ - constants::MESSAGE_AMOUNT, + use crate::utils:: setup::{ contract_balance, create_metadata_message, create_recipient_contract, encode_hex, get_asset_id, precalculate_deposit_id, wallet_balance, MetadataEvent, RefundRegisteredEvent, - }, + }; use fuel_core_types::fuel_types::canonical::Deserialize; use fuels::types::bech32::{Bech32Address, FUEL_BECH32_HRP}; use fuels::types::{Bytes32, U256}; use fuels::{ - prelude::AssetId, programs::contract::SettableContract, types::{tx_status::TxStatus, Bits256}, }; @@ -88,17 +86,12 @@ mod success { let tx_status = wallet.provider().unwrap().tx_status(&_tx_id).await.unwrap(); assert!(matches!(tx_status, TxStatus::Success { .. })); - let eth_balance = - contract_balance(provider, bridge.contract_id(), AssetId::default()).await; let asset_id = get_asset_id(bridge.contract_id(), token_address); let asset_balance = provider .get_asset_balance(&recipient_bech32, asset_id) .await .unwrap(); - // Verify the message value was received by the bridge - assert_eq!(eth_balance, MESSAGE_AMOUNT); - // Check that wallet now has bridged coins assert_eq!(asset_balance, amount); @@ -160,8 +153,6 @@ mod success { ) .await; - let provider = wallet.provider().expect("Needs provider"); - let asset_id = get_asset_id(bridge.contract_id(), BRIDGED_TOKEN); // Get the balance for the deposit contract before @@ -179,13 +170,8 @@ mod success { ) .await; - let asset_balance = - contract_balance(provider, bridge.contract_id(), AssetId::default()).await; let balance = wallet_balance(&wallet, &asset_id).await; - // Verify the message value was received by the bridge - assert_eq!(asset_balance, MESSAGE_AMOUNT); - // Check that wallet now has bridged coins assert_eq!(balance, deposit_amount); @@ -268,8 +254,6 @@ mod success { ) .await; - let provider = wallet.provider().expect("Needs provider"); - let asset_id = get_asset_id(bridge.contract_id(), BRIDGED_TOKEN); // Get the balance for the deposit contract before @@ -287,13 +271,8 @@ mod success { ) .await; - let asset_balance = - contract_balance(provider, bridge.contract_id(), AssetId::default()).await; let balance = wallet_balance(&wallet, &asset_id).await; - // Verify the message value was received by the bridge - assert_eq!(asset_balance, MESSAGE_AMOUNT); - // Check that wallet now has bridged coins assert_eq!(balance, max_deposit_amount); @@ -885,8 +864,6 @@ mod success { ) .await; - let provider = wallet.provider().expect("Needs provider"); - // Relay the test message to the bridge contract let tx_id = relay_message_to_contract( &wallet, @@ -895,13 +872,9 @@ mod success { ) .await; - let eth_balance = - contract_balance(provider, bridge.contract_id(), AssetId::default()).await; let asset_id = get_asset_id(bridge.contract_id(), BRIDGED_TOKEN); let asset_balance = wallet_balance(&wallet, &asset_id).await; - // Verify the message value was received by the bridge - assert_eq!(eth_balance, MESSAGE_AMOUNT); assert_eq!(asset_balance, 0); let receipts = wallet From afd8c4a3d9f0f149bafb4c26b8937db9b21c194c Mon Sep 17 00:00:00 2001 From: DefiCake Date: Mon, 13 May 2024 21:08:30 +0200 Subject: [PATCH 14/28] chore: upgrade to forc 0.56.1 --- fuel-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuel-toolchain.toml b/fuel-toolchain.toml index 620f44d2..566ccbf0 100644 --- a/fuel-toolchain.toml +++ b/fuel-toolchain.toml @@ -3,4 +3,4 @@ channel = "latest-2023-11-30" [components] fuel-core = "0.26.0" -forc = "0.56.0" +forc = "0.56.1" From e339b0d35fe53870eca88502898f9310d79836f6 Mon Sep 17 00:00:00 2001 From: DefiCake Date: Mon, 13 May 2024 21:14:03 +0200 Subject: [PATCH 15/28] chore: upgrade fuel-ts to 0.85 --- Forc.lock | 4 +- packages/esbuild-bin-loader/package.json | 2 +- packages/integration-tests/package.json | 2 +- packages/test-utils/package.json | 2 +- .../fuels/getOrDeployFuelTokenContract.ts | 6 +- pnpm-lock.yaml | 311 +++++++++--------- 6 files changed, 164 insertions(+), 163 deletions(-) diff --git a/Forc.lock b/Forc.lock index 1342601c..452437ab 100644 --- a/Forc.lock +++ b/Forc.lock @@ -23,7 +23,7 @@ dependencies = [ [[package]] name = "core" -source = "path+from-root-03A6E3005278C326" +source = "path+from-root-EE4FC085C06BAAEB" [[package]] name = "src_20" @@ -37,7 +37,7 @@ dependencies = ["std"] [[package]] name = "std" -source = "git+https://github.com/fuellabs/sway?tag=v0.56.0#b495d0df6956524fd68dab7e062df04d2e581ac3" +source = "git+https://github.com/fuellabs/sway?tag=v0.56.1#4a63b41de136ab68bdf396c6720708fbf4dca83e" dependencies = ["core"] [[package]] diff --git a/packages/esbuild-bin-loader/package.json b/packages/esbuild-bin-loader/package.json index c49c825a..67f42e3b 100644 --- a/packages/esbuild-bin-loader/package.json +++ b/packages/esbuild-bin-loader/package.json @@ -10,6 +10,6 @@ "build": "tsup" }, "dependencies": { - "fuels": "0.84.0" + "fuels": "0.85.0" } } \ No newline at end of file diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index a6c51967..a276607c 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -24,7 +24,7 @@ "dotenv": "^16.0.3", "ethereum-waffle": "^4.0.2", "ethers": "6.11.0", - "fuels": "0.84.0", + "fuels": "0.85.0", "mocha": "^10.0.0", "ts-node": "^10.9.1", "typescript": "^5.1.6" diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index da830d74..2509bc55 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -16,7 +16,7 @@ "build:watch": "tsup --watch" }, "peerDependencies": { - "fuels": "0.84.0", + "fuels": "0.85.0", "ethers": "6.11.0" }, "devDependencies": { diff --git a/packages/test-utils/src/utils/fuels/getOrDeployFuelTokenContract.ts b/packages/test-utils/src/utils/fuels/getOrDeployFuelTokenContract.ts index d3882f71..8e2df52c 100644 --- a/packages/test-utils/src/utils/fuels/getOrDeployFuelTokenContract.ts +++ b/packages/test-utils/src/utils/fuels/getOrDeployFuelTokenContract.ts @@ -70,12 +70,12 @@ export async function getOrDeployFuelTokenContract( storageSlots: [], } ); - const { maxFee, requiredQuantities } = - await fuelAcct.provider.getTransactionCost(transactionRequest); + const { requiredQuantities } = await fuelAcct.provider.getTransactionCost( + transactionRequest + ); await fuelAcct.fund(transactionRequest, { requiredQuantities, - maxFee, estimatedPredicates: [], addedSignatures: 0, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 24c65d9b..d589e77a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -46,8 +46,8 @@ importers: packages/esbuild-bin-loader: dependencies: fuels: - specifier: 0.84.0 - version: 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + specifier: 0.85.0 + version: 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) packages/fungible-token: devDependencies: @@ -91,8 +91,8 @@ importers: specifier: 6.11.0 version: 6.11.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) fuels: - specifier: 0.84.0 - version: 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + specifier: 0.85.0 + version: 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) mocha: specifier: ^10.0.0 version: 10.4.0 @@ -241,8 +241,8 @@ importers: specifier: 6.11.0 version: 6.11.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) fuels: - specifier: 0.84.0 - version: 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + specifier: 0.85.0 + version: 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) devDependencies: '@fuel-bridge/fungible-token': specifier: workspace:* @@ -817,60 +817,60 @@ packages: '@fuel-contracts/merkle-sol@0.1.4': resolution: {integrity: sha512-r2jLlVPb/n3vALQ1EissdiW96kPcAGg4Yu/hsGHe+ZEgu8kEYSLWqPAV0shU72q//Ofxfh7xznmUMf7lkzNLRQ==} - '@fuel-ts/abi-coder@0.84.0': - resolution: {integrity: sha512-j76kuHASFhN7ibPLSQC631f40+dIL7PkmR+EgfZIujOesfsj4emMc/jRdGhdGklikyiE6RvVvKCJNpcrvIKeYA==} + '@fuel-ts/abi-coder@0.85.0': + resolution: {integrity: sha512-BQsjtD2aGDQir4twaCqqPH7oIjg0/mX59FCf/hT5rXRhwBXTPi60vSXniNyQUGuMRYcmRMvr+6GAEmD6w9kFXw==} engines: {node: ^18.18.2 || ^20.0.0} - '@fuel-ts/abi-typegen@0.84.0': - resolution: {integrity: sha512-w95A1x8DaCc6O+AaTB/ifpZtDE3opGs0gBCZIVHSvFhhYR7Z5Up8t73Va0+sYiu1jyvCrsHQrCXKvK1zq3FwRQ==} + '@fuel-ts/abi-typegen@0.85.0': + resolution: {integrity: sha512-AL+suFj+sooNMNkIUNbEoLlw/fp51cVTojVQSB6QKPNB4FA4JtOyyZ/v2faPnoXgy2B39D3xwGjS94RibeFiRw==} engines: {node: ^18.18.2 || ^20.0.0} hasBin: true - '@fuel-ts/account@0.84.0': - resolution: {integrity: sha512-RvO6/j16M2Y1SymQz3S/Xmc9klXpHWnoHuZedYmNKArRSm4QDk6DhiKflfkG9U8NyjvtnDk2RYm8fpAODzhn4A==} + '@fuel-ts/account@0.85.0': + resolution: {integrity: sha512-EjtWMYitqmT54xyceDsU1162yT3jibHPAgbiAQd9YRQIYotiiLQB9QJDcVw24RaCs0jwi5OhdvCwKeYbd+qS6g==} engines: {node: ^18.18.2 || ^20.0.0} - '@fuel-ts/address@0.84.0': - resolution: {integrity: sha512-kryoGabW5Y+dRTdBt7dhO1RYa0sAf98LxUaQQBVyVz1Yjv6SFJY6cXvEQ+GYxAe+CJS//cRvrvaot7jt/vGMDw==} + '@fuel-ts/address@0.85.0': + resolution: {integrity: sha512-9+Ud5roDYwTbttTSgUec1HzxqOVNRmDEvxwUbaKR007VprfRkGUWfiiKmZlSI9uf7niKnoBvq/MMvKHpB4SMEQ==} engines: {node: ^18.18.2 || ^20.0.0} - '@fuel-ts/contract@0.84.0': - resolution: {integrity: sha512-zZjbJS9dSnJt3PKqYja2KJmk7rrQyrXrJ3haulXSTJfMNDH0XFfuaWMJjqu8z15uX+vPn9DgW6UFse+Oohhoqw==} + '@fuel-ts/contract@0.85.0': + resolution: {integrity: sha512-HYGE3hxil6q5/GD8qpUjer+QqqhDV/nshqCUd7vmYeD+JwZSIuSIjBYgt0ly100+xwwNk8bO1ihzqJ3SORt7WQ==} engines: {node: ^18.18.2 || ^20.0.0} - '@fuel-ts/crypto@0.84.0': - resolution: {integrity: sha512-UEB8tY25hLHgF+e884MVqR0/n9YG3qpJi+XZ+D/bSxyN9AyoiOtcaju6NaF0bXufLqrKI9sDCKVVuHKoj+dUjw==} + '@fuel-ts/crypto@0.85.0': + resolution: {integrity: sha512-wEJWl0jwtiTnokGU9fCUzpol/6vmFZZAZ3Oz3aCTIh9NLND7kAAvYRwvFma55mku/ScSPnlnl29I3nGuawCIoQ==} engines: {node: ^18.18.2 || ^20.0.0} - '@fuel-ts/errors@0.84.0': - resolution: {integrity: sha512-bK7dzyl4/u8Vk8WNq7M63pikuNoV6HL25DJudBxlAGwC0M/Ckg61kVp4fi6eAmvoqEn7tiXzvH6P3F9+IV5Jcw==} + '@fuel-ts/errors@0.85.0': + resolution: {integrity: sha512-U312G/5i9Gqm5tAYiCrutp693d8Jdqr+BtVsbfcUMYpU+YRkbGX/kVZrYh78SytHbR4zcPi6CEe3wbe2fFnpfg==} engines: {node: ^18.18.2 || ^20.0.0} '@fuel-ts/forc@0.73.0': resolution: {integrity: sha512-Dpli/ch7axvJ2nptzVnYgpQQHUM4NwuSXkIRrhEKdcSGy6q1kClngL5NaeenUHLzsQfZPrMJ69fExF6BpOHNhg==} hasBin: true - '@fuel-ts/forc@0.84.0': - resolution: {integrity: sha512-gl1/l4ix2WY8lavqWQ8eoNC+7x1ZHaHMqVSfMa7X8K9tPdiUf2fGhASpAPEbdbIGvSxoMsgCR9GaHrNYd07isg==} + '@fuel-ts/forc@0.85.0': + resolution: {integrity: sha512-3g6EmTBhZv6qjAAAICadbla48InXnKt3mhPx6AhTHUIvP32vzW02CrINUNuCJ+/zr9twbZ4PNMcjXk1Io2WCgA==} hasBin: true - '@fuel-ts/fuel-core@0.84.0': - resolution: {integrity: sha512-gHinTW8HTLVvJRY5PqyTjWhN7B2++9aXjsnfVrdHoISljdzMbMsUfPxywbHRwmMpcth1KPO9RCfCjdKy99wonQ==} + '@fuel-ts/fuel-core@0.85.0': + resolution: {integrity: sha512-NQiVTX+J2nNaqojbbi4sGpo08x+XWMMZuCgxYiirNOQrFkxs+rUWEhMEPrX+v+6Hrt6qBNoX2R5RRxNMsN3t5w==} hasBin: true - '@fuel-ts/hasher@0.84.0': - resolution: {integrity: sha512-9VKNQ8F4+vSUKhnz3/0MSS8vUDLZjqQK3jiHJZkBZvuVOrqENuHoVhVMbk3E3Nz+W83fFmKBCIKD+UXu4lCMiQ==} + '@fuel-ts/hasher@0.85.0': + resolution: {integrity: sha512-R1VNEl9amGHvaEWzt5Oja9R83IRJfDgajtbUI5Wj28Z8ONlxJ6Yy7Koe41COV4fojeN/u+pouqllXvVlWAJGyA==} engines: {node: ^18.18.2 || ^20.0.0} - '@fuel-ts/interfaces@0.84.0': - resolution: {integrity: sha512-xjEawF6uMotd+yvfPmOH4lbotlMR3Xfp5R6ioUV0dUby1OoD6NGB2U/3lDbYWETMCL9TwCG728acb9TYBTq75Q==} + '@fuel-ts/interfaces@0.85.0': + resolution: {integrity: sha512-hj5A8Lg2ts1L+/iQ8sDwlGdBLIl1wPPwTuWv5/Mf5OoFXeP2X6iZ3OSRqd8/bvLWI/8fsunuut/Y9aCFLlcc/w==} engines: {node: ^18.18.2 || ^20.0.0} '@fuel-ts/math@0.21.2': resolution: {integrity: sha512-5Nt7R2z4hoxAJc/xvMgTlZeB6QQO7uEX/8Ehx6C0xlMcb/jhwSoVbSweX67avXDtLkKkDenJfSwQGl/FeKcGwQ==} - '@fuel-ts/math@0.84.0': - resolution: {integrity: sha512-tqhKIX2MscKPMJ3GS+YmtAW53IPhN4WwYBTqOAxlsnDT7/lQLuYxHazJ/WFxUrcqx2+ziV5QCbLgwIg4WSx1QQ==} + '@fuel-ts/math@0.85.0': + resolution: {integrity: sha512-Hfx4MJoqid9d4GKtpXSvZeJ21DeOprUS3QwdBffbDt6DYmLAqCRZVvP29cc+4QHFH5I/zOknXmgXK0lqPKYp7g==} engines: {node: ^18.18.2 || ^20.0.0} '@fuel-ts/merkle-shared@0.21.2': @@ -879,28 +879,28 @@ packages: '@fuel-ts/merkle@0.21.2': resolution: {integrity: sha512-0S7JuZO13uStSEx4MHzbykMP4Tdv5m/HNQdngVJSfd+F2O6PRQwZSKYE4cGZBbYc1ABH9q+K0NUuyiLtsmGmxg==} - '@fuel-ts/merkle@0.84.0': - resolution: {integrity: sha512-TgiSg8ZsIrKYd1cPaynEMfeu/Qak5HjeNCJEiszDUSsaBbvfnNFNOp9bhPab5EtBYEFxGU1Gcbbecv2wtbgmng==} + '@fuel-ts/merkle@0.85.0': + resolution: {integrity: sha512-+xvIuZzQSjbm6g6qoCwFLZVBO9yfP7ipznEwwvT1EgfeC1IA4cHhEx6JKjVshkgs1oMKxvKcAkxgBA+r8YFHZQ==} engines: {node: ^18.18.2 || ^20.0.0} - '@fuel-ts/program@0.84.0': - resolution: {integrity: sha512-QOYu3Z34vDRx+FtSFl9bJtuR/xchVWcALcKwZkkAF/BJCPByUzuvJds2iajUu9TKn/S4WdYRczd6x28RdhKDqw==} + '@fuel-ts/program@0.85.0': + resolution: {integrity: sha512-cN4Y7nF0HnRikKTaetw0T55lLjY3cfISWwNLIHkbjMJ99UIegOzt3A9hOT1TZQz6F7FaFQL8FQrrzwBrJUgqUA==} engines: {node: ^18.18.2 || ^20.0.0} - '@fuel-ts/script@0.84.0': - resolution: {integrity: sha512-P2pMQtKriYuTelem8J5fEDUbN3VYQLHpL9wklpbpX+1aBjSe9LF6Ns++tNSveYN1yjobqZDh0gZ1AeoiwIT5oQ==} + '@fuel-ts/script@0.85.0': + resolution: {integrity: sha512-UriUDFh9ouN5u8teBsYJxSu4WHSjiADJEcq4WZes4HJ72S85aZthnrZvKUCgemPsSTDGHQ44w1QUkcObkzKV3A==} engines: {node: ^18.18.2 || ^20.0.0} - '@fuel-ts/transactions@0.84.0': - resolution: {integrity: sha512-hsCa0kpHuefkImcvE13eagG1U1XjkBmfv09SjVDB7auCOCmSO1m1QnBPZ+dRwsfrAY631YwTaba+3F23n50vtw==} + '@fuel-ts/transactions@0.85.0': + resolution: {integrity: sha512-Dgy3Z17idsgIGnrF79iYUH8cccmrI8GOQSoXAh/PzFVKAayN4hr6orgw03KlZCNI7Gao5jcFbywPzDPFw2VWMw==} engines: {node: ^18.18.2 || ^20.0.0} - '@fuel-ts/utils@0.84.0': - resolution: {integrity: sha512-Wsz+LOexqQ+dUKc1foeu4bui4EUPG+HILKd3V5xGEazR4qxIO4fYpT7AxvykGZJDJb8bC7bXeSCzxwJ6bABujA==} + '@fuel-ts/utils@0.85.0': + resolution: {integrity: sha512-Yd30zqKrhOdxmj0WeafdnHFYpSdEg64qBjMOEF3JtIknr9mx69u40hNTDm2KMrXkk1ao2wyWjv4+ckVm5ZZrcw==} engines: {node: ^18.18.2 || ^20.0.0} - '@fuel-ts/versions@0.84.0': - resolution: {integrity: sha512-rWxwKA7SEcE6qeAWlc/nj7oBsDK+9aW6sgkAEgVbethcKOQ8cRaGGc+H/Gd/ortw2kZ96isUVA9qfnVLnx5TEg==} + '@fuel-ts/versions@0.85.0': + resolution: {integrity: sha512-oMFkqsT7a8XTLpBXwtfmlX/3zkVgz3ReO6WBGMfiIP7WJiI5i2+9PFk6y+ywO4I7s35v8oHITTvawzFcr0k5Ew==} engines: {node: ^18.18.2 || ^20.0.0} hasBin: true @@ -2984,8 +2984,8 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - fuels@0.84.0: - resolution: {integrity: sha512-aegKUzVxs410a/cH2NAfcEFY+4o+4/qstJCv4JDgOjzamjc7tsh28fANTmaA5bybuGRWXSEkey94rne/QF06Eg==} + fuels@0.85.0: + resolution: {integrity: sha512-awYjcHiE7SEVm8JuZXWTQPkRlrBjPmgdSJ4ypheTmyMh4CTtgNDIyAirOpXyzcfFKQOikMv/DSlbTEBYKiS+aw==} engines: {node: ^18.18.2 || ^20.0.0} hasBin: true @@ -6280,26 +6280,26 @@ snapshots: ganache-cli: 6.12.2 mocha: 10.4.0 - '@fuel-ts/abi-coder@0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': + '@fuel-ts/abi-coder@0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': dependencies: - '@fuel-ts/crypto': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/errors': 0.84.0 - '@fuel-ts/hasher': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/interfaces': 0.84.0 - '@fuel-ts/math': 0.84.0 - '@fuel-ts/utils': 0.84.0 + '@fuel-ts/crypto': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/errors': 0.85.0 + '@fuel-ts/hasher': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/interfaces': 0.85.0 + '@fuel-ts/math': 0.85.0 + '@fuel-ts/utils': 0.85.0 ethers: 6.11.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) type-fest: 3.13.1 transitivePeerDependencies: - bufferutil - utf-8-validate - '@fuel-ts/abi-typegen@0.84.0': + '@fuel-ts/abi-typegen@0.85.0': dependencies: - '@fuel-ts/errors': 0.84.0 - '@fuel-ts/interfaces': 0.84.0 - '@fuel-ts/utils': 0.84.0 - '@fuel-ts/versions': 0.84.0 + '@fuel-ts/errors': 0.85.0 + '@fuel-ts/interfaces': 0.85.0 + '@fuel-ts/utils': 0.85.0 + '@fuel-ts/versions': 0.85.0 commander: 9.5.0 glob: 10.3.12 handlebars: 4.7.8 @@ -6307,19 +6307,19 @@ snapshots: ramda: 0.29.1 rimraf: 3.0.2 - '@fuel-ts/account@0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': - dependencies: - '@fuel-ts/abi-coder': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/address': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/crypto': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/errors': 0.84.0 - '@fuel-ts/hasher': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/interfaces': 0.84.0 - '@fuel-ts/math': 0.84.0 - '@fuel-ts/merkle': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/transactions': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/utils': 0.84.0 - '@fuel-ts/versions': 0.84.0 + '@fuel-ts/account@0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': + dependencies: + '@fuel-ts/abi-coder': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/address': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/crypto': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/errors': 0.85.0 + '@fuel-ts/hasher': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/interfaces': 0.85.0 + '@fuel-ts/math': 0.85.0 + '@fuel-ts/merkle': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/transactions': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/utils': 0.85.0 + '@fuel-ts/versions': 0.85.0 '@fuels/vm-asm': 0.49.0 '@noble/curves': 1.4.0 ethers: 6.11.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) @@ -6337,49 +6337,49 @@ snapshots: - supports-color - utf-8-validate - '@fuel-ts/address@0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': + '@fuel-ts/address@0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': dependencies: - '@fuel-ts/crypto': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/errors': 0.84.0 - '@fuel-ts/interfaces': 0.84.0 - '@fuel-ts/utils': 0.84.0 + '@fuel-ts/crypto': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/errors': 0.85.0 + '@fuel-ts/interfaces': 0.85.0 + '@fuel-ts/utils': 0.85.0 '@noble/hashes': 1.4.0 bech32: 2.0.0 transitivePeerDependencies: - bufferutil - utf-8-validate - '@fuel-ts/contract@0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': - dependencies: - '@fuel-ts/abi-coder': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/account': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/crypto': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/errors': 0.84.0 - '@fuel-ts/hasher': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/interfaces': 0.84.0 - '@fuel-ts/merkle': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/program': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/transactions': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/utils': 0.84.0 + '@fuel-ts/contract@0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': + dependencies: + '@fuel-ts/abi-coder': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/account': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/crypto': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/errors': 0.85.0 + '@fuel-ts/hasher': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/interfaces': 0.85.0 + '@fuel-ts/merkle': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/program': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/transactions': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/utils': 0.85.0 transitivePeerDependencies: - bufferutil - encoding - supports-color - utf-8-validate - '@fuel-ts/crypto@0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': + '@fuel-ts/crypto@0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': dependencies: - '@fuel-ts/errors': 0.84.0 - '@fuel-ts/utils': 0.84.0 + '@fuel-ts/errors': 0.85.0 + '@fuel-ts/utils': 0.85.0 '@noble/hashes': 1.4.0 ethers: 6.11.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) transitivePeerDependencies: - bufferutil - utf-8-validate - '@fuel-ts/errors@0.84.0': + '@fuel-ts/errors@0.85.0': dependencies: - '@fuel-ts/versions': 0.84.0 + '@fuel-ts/versions': 0.85.0 '@fuel-ts/forc@0.73.0': dependencies: @@ -6387,38 +6387,38 @@ snapshots: transitivePeerDependencies: - encoding - '@fuel-ts/forc@0.84.0': + '@fuel-ts/forc@0.85.0': dependencies: node-fetch: 2.7.0 transitivePeerDependencies: - encoding - '@fuel-ts/fuel-core@0.84.0': + '@fuel-ts/fuel-core@0.85.0': dependencies: node-fetch: 2.7.0 transitivePeerDependencies: - encoding - '@fuel-ts/hasher@0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': + '@fuel-ts/hasher@0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': dependencies: - '@fuel-ts/crypto': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/interfaces': 0.84.0 - '@fuel-ts/utils': 0.84.0 + '@fuel-ts/crypto': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/interfaces': 0.85.0 + '@fuel-ts/utils': 0.85.0 '@noble/hashes': 1.4.0 transitivePeerDependencies: - bufferutil - utf-8-validate - '@fuel-ts/interfaces@0.84.0': {} + '@fuel-ts/interfaces@0.85.0': {} '@fuel-ts/math@0.21.2': dependencies: '@types/bn.js': 5.1.5 bn.js: 5.2.1 - '@fuel-ts/math@0.84.0': + '@fuel-ts/math@0.85.0': dependencies: - '@fuel-ts/errors': 0.84.0 + '@fuel-ts/errors': 0.85.0 '@types/bn.js': 5.1.5 bn.js: 5.2.1 @@ -6432,67 +6432,68 @@ snapshots: '@fuel-ts/math': 0.21.2 '@fuel-ts/merkle-shared': 0.21.2 - '@fuel-ts/merkle@0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': + '@fuel-ts/merkle@0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': dependencies: - '@fuel-ts/hasher': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/math': 0.84.0 + '@fuel-ts/hasher': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/math': 0.85.0 transitivePeerDependencies: - bufferutil - utf-8-validate - '@fuel-ts/program@0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': + '@fuel-ts/program@0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': dependencies: - '@fuel-ts/abi-coder': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/account': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/address': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/errors': 0.84.0 - '@fuel-ts/interfaces': 0.84.0 - '@fuel-ts/math': 0.84.0 - '@fuel-ts/transactions': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/utils': 0.84.0 + '@fuel-ts/abi-coder': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/account': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/address': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/errors': 0.85.0 + '@fuel-ts/interfaces': 0.85.0 + '@fuel-ts/math': 0.85.0 + '@fuel-ts/transactions': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/utils': 0.85.0 '@fuels/vm-asm': 0.49.0 + ramda: 0.29.1 transitivePeerDependencies: - bufferutil - encoding - supports-color - utf-8-validate - '@fuel-ts/script@0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': - dependencies: - '@fuel-ts/abi-coder': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/account': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/address': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/errors': 0.84.0 - '@fuel-ts/interfaces': 0.84.0 - '@fuel-ts/math': 0.84.0 - '@fuel-ts/program': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/transactions': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/utils': 0.84.0 + '@fuel-ts/script@0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': + dependencies: + '@fuel-ts/abi-coder': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/account': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/address': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/errors': 0.85.0 + '@fuel-ts/interfaces': 0.85.0 + '@fuel-ts/math': 0.85.0 + '@fuel-ts/program': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/transactions': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/utils': 0.85.0 transitivePeerDependencies: - bufferutil - encoding - supports-color - utf-8-validate - '@fuel-ts/transactions@0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': + '@fuel-ts/transactions@0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7)': dependencies: - '@fuel-ts/abi-coder': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/address': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/errors': 0.84.0 - '@fuel-ts/hasher': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/interfaces': 0.84.0 - '@fuel-ts/math': 0.84.0 - '@fuel-ts/utils': 0.84.0 + '@fuel-ts/abi-coder': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/address': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/errors': 0.85.0 + '@fuel-ts/hasher': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/interfaces': 0.85.0 + '@fuel-ts/math': 0.85.0 + '@fuel-ts/utils': 0.85.0 transitivePeerDependencies: - bufferutil - utf-8-validate - '@fuel-ts/utils@0.84.0': + '@fuel-ts/utils@0.85.0': dependencies: - '@fuel-ts/errors': 0.84.0 - '@fuel-ts/interfaces': 0.84.0 + '@fuel-ts/errors': 0.85.0 + '@fuel-ts/interfaces': 0.85.0 - '@fuel-ts/versions@0.84.0': + '@fuel-ts/versions@0.85.0': dependencies: chalk: 4.1.2 cli-table: 0.3.11 @@ -9193,26 +9194,26 @@ snapshots: fsevents@2.3.3: optional: true - fuels@0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7): - dependencies: - '@fuel-ts/abi-coder': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/abi-typegen': 0.84.0 - '@fuel-ts/account': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/address': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/contract': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/crypto': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/errors': 0.84.0 - '@fuel-ts/forc': 0.84.0 - '@fuel-ts/fuel-core': 0.84.0 - '@fuel-ts/hasher': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/interfaces': 0.84.0 - '@fuel-ts/math': 0.84.0 - '@fuel-ts/merkle': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/program': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/script': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/transactions': 0.84.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) - '@fuel-ts/utils': 0.84.0 - '@fuel-ts/versions': 0.84.0 + fuels@0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7): + dependencies: + '@fuel-ts/abi-coder': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/abi-typegen': 0.85.0 + '@fuel-ts/account': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/address': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/contract': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/crypto': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/errors': 0.85.0 + '@fuel-ts/forc': 0.85.0 + '@fuel-ts/fuel-core': 0.85.0 + '@fuel-ts/hasher': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/interfaces': 0.85.0 + '@fuel-ts/math': 0.85.0 + '@fuel-ts/merkle': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/program': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/script': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/transactions': 0.85.0(bufferutil@4.0.5)(utf-8-validate@5.0.7) + '@fuel-ts/utils': 0.85.0 + '@fuel-ts/versions': 0.85.0 bundle-require: 4.0.2(esbuild@0.19.12) chalk: 4.1.2 chokidar: 3.6.0 From 47f17b6d8319383da6336407fd957b576b83609a Mon Sep 17 00:00:00 2001 From: DefiCake Date: Mon, 13 May 2024 21:14:44 +0200 Subject: [PATCH 16/28] chore: remove unused code --- .../src/contract_message_test.sw | 51 ------------------- 1 file changed, 51 deletions(-) diff --git a/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw b/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw index 27dacc17..bc16e36d 100644 --- a/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw +++ b/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw @@ -28,57 +28,6 @@ abi VerifyMessageData { fn test_data4() -> Address; } -abi MyCallerContract { - #[storage(read,write)] - fn call_low_level_call( - target: ContractId, - function_selector: Bytes, - calldata: Bytes, - ); -} - -impl MyCallerContract for Contract { - - #[storage(read,write)] - fn call_low_level_call( - target: ContractId, - function_selector: Bytes, - calldata: Bytes, - ) { - let payload = create_payload(target, function_selector, calldata); - - log(function_selector); - log(calldata); - log(payload); - - } - -} - -fn create_payload( - target: ContractId, - function_selector: Bytes, - call_data: Bytes, -) -> Bytes { - /* - packs args according to spec (https://github.com/FuelLabs/fuel-specs/blob/master/src/vm/instruction_set.md#call-call-contract) : - - bytes type value description - 32 byte[32] to Contract ID to call. - 8 byte[8] param1 First parameter (function selector pointer) - 8 byte[8] param2 Second parameter (encoded arguments pointer) - */ - Bytes::from(encode(( - target, - asm(a: function_selector.ptr()) { - a: u64 - }, - asm(a: call_data.ptr()) { - a: u64 - }, - ))) -} - // Converts a Bytes type to u64 // TODO: remove once an [into(self) -> u64] is added for the Bytes type fn into_u64(b: Bytes) -> u64 { From bdf9d83e30f401a5fcba9989eff01b63eeaf2565 Mon Sep 17 00:00:00 2001 From: DefiCake Date: Mon, 13 May 2024 21:18:51 +0200 Subject: [PATCH 17/28] chore: remove unused code --- .../src/contract_message_test.sw | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw b/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw index bc16e36d..2091cc94 100644 --- a/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw +++ b/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw @@ -4,7 +4,6 @@ use contract_message_receiver::MessageReceiver; use std::bytes::Bytes; use std::constants::ZERO_B256; use std::inputs::{input_message_data, input_message_data_length}; -use std::call_frames::{first_param, second_param, called_method}; storage { counter: u64 = 0, @@ -42,7 +41,6 @@ impl MessageReceiver for Contract { #[storage(read, write)] #[payable] fn process_message(msg_idx: u64) { - log(msg_idx); storage.counter.write(0); // Temporary fix for: https://github.com/FuelLabs/sway/issues/4634 storage.counter.write(storage.counter.read() + 1); @@ -93,21 +91,4 @@ impl VerifyMessageData for Contract { fn test_data4() -> Address { storage.data4.read() } -} - -#[fallback, storage(read)] -fn fallback() { - log(255u64); - log(254u64); - log(253u64); - - let first_param = first_param(); - log(first_param); - - let second_param = second_param(); - log(second_param); - - let called_method = called_method(); - - log(called_method); } \ No newline at end of file From 7f3b727c4c6ea70f3a66b43ec9a5b872d891a484 Mon Sep 17 00:00:00 2001 From: DefiCake Date: Mon, 13 May 2024 21:19:47 +0200 Subject: [PATCH 18/28] chore: apply forc fmt --- packages/fungible-token/bridge-fungible-token/Forc.toml | 2 +- .../contract-message-predicate/src/contract_message_test.sw | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/fungible-token/bridge-fungible-token/Forc.toml b/packages/fungible-token/bridge-fungible-token/Forc.toml index ffa25361..f4f669be 100644 --- a/packages/fungible-token/bridge-fungible-token/Forc.toml +++ b/packages/fungible-token/bridge-fungible-token/Forc.toml @@ -6,5 +6,5 @@ name = "bridge_fungible_token" [dependencies] contract_message_receiver = { path = "../../message-predicates/contract-message-receiver" } -sway_libs = { git = "https://github.com/FuelLabs/sway-libs", tag = "v0.21.0" } src_20 = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.2.2" } +sway_libs = { git = "https://github.com/FuelLabs/sway-libs", tag = "v0.21.0" } diff --git a/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw b/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw index 2091cc94..8ca9dc47 100644 --- a/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw +++ b/packages/message-predicates/contract-message-predicate/src/contract_message_test.sw @@ -91,4 +91,4 @@ impl VerifyMessageData for Contract { fn test_data4() -> Address { storage.data4.read() } -} \ No newline at end of file +} From 70e1c3469ad17430106aa4f15ef03f0ee2d4f2f6 Mon Sep 17 00:00:00 2001 From: DefiCake Date: Mon, 13 May 2024 21:55:05 +0200 Subject: [PATCH 19/28] feat: update predicate root on contracts --- .../contracts/lib/CommonPredicates.sol | 2 +- packages/test-utils/src/utils/constants.ts | 9 +++++---- .../test-utils/src/utils/fuels/relayCommonMessage.ts | 7 +++++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/solidity-contracts/contracts/lib/CommonPredicates.sol b/packages/solidity-contracts/contracts/lib/CommonPredicates.sol index c6ff561d..af9e48fd 100644 --- a/packages/solidity-contracts/contracts/lib/CommonPredicates.sol +++ b/packages/solidity-contracts/contracts/lib/CommonPredicates.sol @@ -5,5 +5,5 @@ pragma solidity 0.8.9; /// @notice Common predicates for Fuel inputs library CommonPredicates { bytes32 public constant CONTRACT_MESSAGE_PREDICATE = - 0xb12658c759d8bae2cdc523ebd7aa8637912f32b1763d242ad3618448057b79cd; + 0xe821b978bcce9abbf40c3e50ea30143e68c65fa95b9da8907fef59c02d954cec; } diff --git a/packages/test-utils/src/utils/constants.ts b/packages/test-utils/src/utils/constants.ts index b6ac07e1..55d1ec59 100644 --- a/packages/test-utils/src/utils/constants.ts +++ b/packages/test-utils/src/utils/constants.ts @@ -1,3 +1,4 @@ +import type { TxParams } from 'fuels'; import { bn } from 'fuels'; // Constants @@ -6,13 +7,13 @@ export const FUEL_ETH_DECIMALS = 9n; export const FUEL_MESSAGE_POLL_MS: number = 300; export const MAX_GAS_PER_TX = bn(100_000_000); export const FUEL_GAS_LIMIT = 500_000_000; -export const FUEL_GAS_PRICE = 1; -export const FUEL_TX_PARAMS = { +export const FUEL_MAX_FEE = 1; +export const FUEL_TX_PARAMS: TxParams = { gasLimit: process.env.FUEL_GAS_LIMIT || FUEL_GAS_LIMIT, - gasPrice: process.env.FUEL_GAS_PRICE || FUEL_GAS_PRICE, + maxFee: process.env.FUEL_MAX_FEE || FUEL_MAX_FEE, }; export const FUEL_CALL_TX_PARAMS = { gasLimit: bn(64_933), - gasPrice: FUEL_TX_PARAMS.gasPrice, + maxFee: FUEL_TX_PARAMS.maxFee, }; export const FUEL_MESSAGE_TIMEOUT_MS = 1_000_000; diff --git a/packages/test-utils/src/utils/fuels/relayCommonMessage.ts b/packages/test-utils/src/utils/fuels/relayCommonMessage.ts index dbe35c44..a1b4a1cb 100644 --- a/packages/test-utils/src/utils/fuels/relayCommonMessage.ts +++ b/packages/test-utils/src/utils/fuels/relayCommonMessage.ts @@ -102,7 +102,7 @@ function getCommonRelayableMessages(provider: Provider) { transaction.gasLimit = bn(1_000_000); - transaction.maxFee = bn(0); + transaction.maxFee = bn(1); debug( '-------------------------------------------------------------------' @@ -141,7 +141,10 @@ type CommonMessageDetails = { export async function relayCommonMessage( relayer: FuelWallet, message: Message, - txParams?: Pick + txParams?: Pick< + ScriptTransactionRequestLike, + 'gasLimit' | 'maturity' | 'maxFee' + > ): Promise { // find the relay details for the specified message let messageRelayDetails: CommonMessageDetails = null; From 2da18ff0d9442ae1f7d06f2c5feb46c6b33eaafe Mon Sep 17 00:00:00 2001 From: DefiCake Date: Mon, 13 May 2024 21:56:42 +0200 Subject: [PATCH 20/28] chore: add changeset --- .changeset/olive-tigers-hunt.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changeset/olive-tigers-hunt.md diff --git a/.changeset/olive-tigers-hunt.md b/.changeset/olive-tigers-hunt.md new file mode 100644 index 00000000..bba38b7d --- /dev/null +++ b/.changeset/olive-tigers-hunt.md @@ -0,0 +1,8 @@ +--- +'@fuel-bridge/message-predicates': minor +'@fuel-bridge/solidity-contracts': minor +'@fuel-bridge/fungible-token': minor +'@fuel-bridge/test-utils': minor +--- + +Bump all packages to adhere to fuel-core 0.26, forc 0.56, fuel-rs 0.60, fuel-ts 0.85 From cffc1a912966edf5d5162f2c3240161560cc1882 Mon Sep 17 00:00:00 2001 From: DefiCake Date: Mon, 13 May 2024 21:57:05 +0200 Subject: [PATCH 21/28] chore: apply cargo fmt --- .../tests/functions/bridge/mod.rs | 9 ++++----- .../tests/functions/message_receiver/mod.rs | 10 ++++------ .../contract-message-predicate/script_asm.rs | 15 +++++---------- .../contract-message-predicate/tests/harness.rs | 4 +++- 4 files changed, 16 insertions(+), 22 deletions(-) diff --git a/packages/fungible-token/bridge-fungible-token/tests/functions/bridge/mod.rs b/packages/fungible-token/bridge-fungible-token/tests/functions/bridge/mod.rs index 067f3c04..14e57296 100644 --- a/packages/fungible-token/bridge-fungible-token/tests/functions/bridge/mod.rs +++ b/packages/fungible-token/bridge-fungible-token/tests/functions/bridge/mod.rs @@ -1,13 +1,12 @@ use crate::utils::{ constants::{ - BRIDGED_TOKEN, BRIDGED_TOKEN_DECIMALS, BRIDGED_TOKEN_ID, FROM, - PROXY_TOKEN_DECIMALS, + BRIDGED_TOKEN, BRIDGED_TOKEN_DECIMALS, BRIDGED_TOKEN_ID, FROM, PROXY_TOKEN_DECIMALS, }, interface::bridge::withdraw, setup::{ - create_deposit_message, create_token, create_wallet, decode_hex, - encode_hex, parse_output_message_data, relay_message_to_contract, setup_environment, - wallet_balance, BridgeFungibleTokenContractConfigurables, BridgingConfig, + create_deposit_message, create_token, create_wallet, decode_hex, encode_hex, + parse_output_message_data, relay_message_to_contract, setup_environment, wallet_balance, + BridgeFungibleTokenContractConfigurables, BridgingConfig, }, }; use fuels::{prelude::AssetId, types::Bits256}; diff --git a/packages/fungible-token/bridge-fungible-token/tests/functions/message_receiver/mod.rs b/packages/fungible-token/bridge-fungible-token/tests/functions/message_receiver/mod.rs index 20df855a..0da5eb35 100644 --- a/packages/fungible-token/bridge-fungible-token/tests/functions/message_receiver/mod.rs +++ b/packages/fungible-token/bridge-fungible-token/tests/functions/message_receiver/mod.rs @@ -13,12 +13,10 @@ use std::str::FromStr; mod success { use super::*; use crate::utils::interface::src20::total_supply; - use crate::utils:: - setup::{ - contract_balance, create_metadata_message, create_recipient_contract, encode_hex, - get_asset_id, precalculate_deposit_id, wallet_balance, MetadataEvent, - RefundRegisteredEvent, - + use crate::utils::setup::{ + contract_balance, create_metadata_message, create_recipient_contract, encode_hex, + get_asset_id, precalculate_deposit_id, wallet_balance, MetadataEvent, + RefundRegisteredEvent, }; use fuel_core_types::fuel_types::canonical::Deserialize; diff --git a/packages/message-predicates/contract-message-predicate/script_asm.rs b/packages/message-predicates/contract-message-predicate/script_asm.rs index ab93c09e..e380e2f5 100644 --- a/packages/message-predicates/contract-message-predicate/script_asm.rs +++ b/packages/message-predicates/contract-message-predicate/script_asm.rs @@ -1,4 +1,3 @@ - use fuel_asm::{op, GTFArgs, RegId}; const PROCESS_MESSAGE_FUNCTION_SIGNATURE: &str = "process_message"; @@ -6,7 +5,8 @@ const BYTES_PER_INSTR: u16 = 4; // Gets the bytecode for the message-to-contract script pub fn bytecode() -> Vec { - let mut fn_selector_bytes = fuels::core::codec::encode_fn_selector(PROCESS_MESSAGE_FUNCTION_SIGNATURE); + let mut fn_selector_bytes = + fuels::core::codec::encode_fn_selector(PROCESS_MESSAGE_FUNCTION_SIGNATURE); const FN_SEL_BYTES_LEN: u16 = 23; // new encoding: len of the function signature as u64 (8 bytes) + 15 bytes of function signature ("process_message" has 15 characters) assert_eq!(fn_selector_bytes.len() as u16, FN_SEL_BYTES_LEN); @@ -18,7 +18,7 @@ pub fn bytecode() -> Vec { const REG_DATA_FN_SELECTOR_PTR: u8 = 0x14; const REG_DATA_CALLDATA_PTR: u8 = 0x15; const REG_CALLDATA_PTR: u8 = 0x16; - + //referenced data start pointer const REF_DATA_START_PTR: u16 = 13 * BYTES_PER_INSTR; @@ -26,32 +26,27 @@ pub fn bytecode() -> Vec { op::move_(REG_MEMORY_START_PTR, RegId::SP), //REG_MEMORY_START_PTR = stack pointer op::cfei(32 + 32 + 8 + 8), //extends current call frame stack by 32+32+8+8 bytes [base asset id, contract id, param1, param2] op::addi(REG_DATA_PTR, REG_MEMORY_START_PTR, 32), //REG_DATA_PTR = REG_MEMORY_START_PTR + 32bytes [memory start pointer + 32] - op::gtf( REG_CONTRACT_ADDR_PTR, RegId::ZERO, GTFArgs::InputMessageData.into(), ), //REG_CONTRACT_ADDR_PTR = memory location of the message data from input[0] op::mcpi(REG_DATA_PTR, REG_CONTRACT_ADDR_PTR, 32), // REG_DATA[0..31] = REG_CONTRACT_ADDR_PTR[0..32] - op::addi(REG_FN_SELECTOR_PTR, RegId::IS, REF_DATA_START_PTR), op::addi(REG_DATA_FN_SELECTOR_PTR, REG_DATA_PTR, 32), // REG_DATA_FN_SELECTOR_PTR = REG_DATA_PTR + 32 op::sw(REG_DATA_FN_SELECTOR_PTR, REG_FN_SELECTOR_PTR, 0), // REG_DATA[32..39] = (End of IS)[0..7] = (len of "process_message") - op::addi(REG_CALLDATA_PTR, RegId::IS, REF_DATA_START_PTR + 23), // REG_DATA_FN_SELECTOR_PTR = REG_DATA_PTR + 32 + 23 op::addi(REG_DATA_CALLDATA_PTR, REG_DATA_PTR, 40), // REG_DATA_FN_SELECTOR_PTR = REG_DATA_PTR + 40 op::sw(REG_DATA_CALLDATA_PTR, REG_CALLDATA_PTR, 0), // REG_DATA[40..47] = (End of IS)[23..30] = msg_idx = 0 - op::call(REG_DATA_PTR, RegId::ZERO, RegId::ZERO, RegId::CGAS), op::ret(RegId::ZERO), ] - .into_iter() - .collect(); + .into_iter() + .collect(); // At the tail of the script, after the return statement, embed: script.append(&mut fn_selector_bytes); // 23 bytes for function selector script.append(&mut 0u64.to_be_bytes().to_vec()); // 8 bytes of msg_idx - script } diff --git a/packages/message-predicates/contract-message-predicate/tests/harness.rs b/packages/message-predicates/contract-message-predicate/tests/harness.rs index a993f53a..a494e809 100644 --- a/packages/message-predicates/contract-message-predicate/tests/harness.rs +++ b/packages/message-predicates/contract-message-predicate/tests/harness.rs @@ -11,7 +11,9 @@ mod success { use crate::utils::{builder, environment as env}; use fuel_tx::Bytes32; use fuels::{ - prelude::{Address, AssetId, ContractId}, test_helpers::DEFAULT_COIN_AMOUNT, types::Bits256 + prelude::{Address, AssetId, ContractId}, + test_helpers::DEFAULT_COIN_AMOUNT, + types::Bits256, }; pub const RANDOM_WORD: u64 = 54321u64; From 0fcb68f84a22c5a65e170731aaf84e7c913f8250 Mon Sep 17 00:00:00 2001 From: DefiCake Date: Tue, 14 May 2024 16:41:18 +0200 Subject: [PATCH 22/28] test: fix predicate in solidity unit tests --- packages/solidity-contracts/protocol/constants.ts | 2 +- packages/solidity-contracts/test/erc721Gateway.test.ts | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/solidity-contracts/protocol/constants.ts b/packages/solidity-contracts/protocol/constants.ts index 76d1c421..3259ad57 100644 --- a/packages/solidity-contracts/protocol/constants.ts +++ b/packages/solidity-contracts/protocol/constants.ts @@ -5,7 +5,7 @@ export const ZERO = '0x0000000000000000000000000000000000000000000000000000000000000000'; export const CONTRACT_MESSAGE_PREDICATE = - '0xb12658c759d8bae2cdc523ebd7aa8637912f32b1763d242ad3618448057b79cd'; + '0xe821b978bcce9abbf40c3e50ea30143e68c65fa95b9da8907fef59c02d954cec'; // From application header: https://github.com/FuelLabs/fuel-specs/blob/master/src/protocol/block-header.md export const CONSENSUS_PARAMETERS_VERSION = 0n; diff --git a/packages/solidity-contracts/test/erc721Gateway.test.ts b/packages/solidity-contracts/test/erc721Gateway.test.ts index 0bb1ec4d..f3031a4d 100644 --- a/packages/solidity-contracts/test/erc721Gateway.test.ts +++ b/packages/solidity-contracts/test/erc721Gateway.test.ts @@ -11,6 +11,7 @@ import { computeBlockId, generateBlockHeaderLite, } from '../protocol/blockHeader'; +import { CONTRACT_MESSAGE_PREDICATE } from '../protocol/constants'; import type { HarnessObject } from '../protocol/harness'; import Message, { computeMessageId } from '../protocol/message'; import { @@ -28,9 +29,6 @@ import type { import { createBlock } from './utils/createBlock'; -const CONTRACT_MESSAGE_PREDICATE = - '0xb12658c759d8bae2cdc523ebd7aa8637912f32b1763d242ad3618448057b79cd'; - const { expect } = chai; // Merkle tree node structure From 2a8d77e47dd685e7b1abacb03491e89404a91ed0 Mon Sep 17 00:00:00 2001 From: DefiCake Date: Tue, 14 May 2024 18:25:04 +0200 Subject: [PATCH 23/28] chore: apply fmt --- packages/solidity-contracts/deployments/devnet/Token.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solidity-contracts/deployments/devnet/Token.json b/packages/solidity-contracts/deployments/devnet/Token.json index d4dea8d9..84fc3cc0 100644 --- a/packages/solidity-contracts/deployments/devnet/Token.json +++ b/packages/solidity-contracts/deployments/devnet/Token.json @@ -472,4 +472,4 @@ } } } -} \ No newline at end of file +} From 90eb4e48465dec33d43470c2e9346aeb3b9f0add Mon Sep 17 00:00:00 2001 From: DefiCake Date: Tue, 14 May 2024 19:31:41 +0200 Subject: [PATCH 24/28] test: update predicate snapshots --- .../contract-message-predicate/src/lib.rs | 40 +++++++++---------- ...e__tests__snapshot_predicate_bytecode.snap | 2 +- ...cate__tests__snapshot_script_bytecode.snap | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/message-predicates/contract-message-predicate/src/lib.rs b/packages/message-predicates/contract-message-predicate/src/lib.rs index 9daf5fb6..9cdfc42b 100644 --- a/packages/message-predicates/contract-message-predicate/src/lib.rs +++ b/packages/message-predicates/contract-message-predicate/src/lib.rs @@ -40,23 +40,23 @@ pub fn predicate_root() -> [u8; 32] { root.into() } -// #[cfg(test)] -// mod tests { -// use super::*; - -// // Ensure the predicate bytecode doesn't change -// #[test] -// fn snapshot_predicate_bytecode() { -// let bytecode = predicate_bytecode(); -// let serialized = hex::encode(bytecode); -// insta::assert_snapshot!(serialized); -// } - -// // Ensure the script bytecode doesn't change -// #[test] -// fn snapshot_script_bytecode() { -// let bytecode = script_bytecode(); -// let serialized = hex::encode(bytecode); -// insta::assert_snapshot!(serialized); -// } -// } +#[cfg(test)] +mod tests { + use super::*; + + // Ensure the predicate bytecode doesn't change + #[test] + fn snapshot_predicate_bytecode() { + let bytecode = predicate_bytecode(); + let serialized = hex::encode(bytecode); + insta::assert_snapshot!(serialized); + } + + // Ensure the script bytecode doesn't change + #[test] + fn snapshot_script_bytecode() { + let bytecode = script_bytecode(); + let serialized = hex::encode(bytecode); + insta::assert_snapshot!(serialized); + } +} diff --git a/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_predicate_bytecode.snap b/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_predicate_bytecode.snap index 70640a13..35a2039d 100644 --- a/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_predicate_bytecode.snap +++ b/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_predicate_bytecode.snap @@ -3,4 +3,4 @@ source: packages/message-predicates/contract-message-predicate/src/lib.rs assertion_line: 52 expression: serialized --- -1a40500091000020614400096148000342411480504cc04c72580020295134165b501012615c000572680002595d7001616172005b61a010616572455b6400125b5c100b240400002400000059c9f9bacd44c394f08f8279531909080d8cfb7d2a40441f1ddb3a8bbb244422 +1a40500091000020614400096148000342411480504cc04c72580020295134165b501012615c000572680002595d7001616172005b61a010616572455b6400125b5c100b24040000240000007cc480c6385fe2c31dc95cc830e4ffb75da5532558ef938b8368da930bf60722 diff --git a/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_script_bytecode.snap b/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_script_bytecode.snap index 54d44a61..879c6e6c 100644 --- a/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_script_bytecode.snap +++ b/packages/message-predicates/contract-message-predicate/src/snapshots/fuel_contract_message_predicate__tests__snapshot_script_bytecode.snap @@ -3,4 +3,4 @@ source: packages/message-predicates/contract-message-predicate/src/lib.rs assertion_line: 60 expression: serialized --- -1a40500091000050504500205049102461540242614c02485050c02c60453020604940042d45540a24000000000000000000000f70726f636573735f6d657373616765 +1a40500091000050504500206148024860452020504cc034505110205f5130005058c04b505510285f5560002d44000a24000000000000000000000f70726f636573735f6d6573736167650000000000000000 From 81a8cd85302804002fd36aa169bd4a6614bc8ccb Mon Sep 17 00:00:00 2001 From: DefiCake Date: Thu, 16 May 2024 11:40:10 +0200 Subject: [PATCH 25/28] doc: update script_asm explanation --- .../contract-message-predicate/script_asm.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/message-predicates/contract-message-predicate/script_asm.rs b/packages/message-predicates/contract-message-predicate/script_asm.rs index e380e2f5..7c5c9567 100644 --- a/packages/message-predicates/contract-message-predicate/script_asm.rs +++ b/packages/message-predicates/contract-message-predicate/script_asm.rs @@ -21,7 +21,13 @@ pub fn bytecode() -> Vec { //referenced data start pointer const REF_DATA_START_PTR: u16 = 13 * BYTES_PER_INSTR; - + + /* The following assembly code is intended to + * Call the function `process_message` on the contract with ID that matches + * the first 32 bytes in the message data field. It won't forward the possible value + * stored in the message. L1 entities sending messages here MUST NOT attach + * a base asset amount, or it will be permanently lost. + */ let mut script: Vec = vec![ op::move_(REG_MEMORY_START_PTR, RegId::SP), //REG_MEMORY_START_PTR = stack pointer op::cfei(32 + 32 + 8 + 8), //extends current call frame stack by 32+32+8+8 bytes [base asset id, contract id, param1, param2] From caebaf43267a2c2facab2a87eeeb1d350ac5e80a Mon Sep 17 00:00:00 2001 From: Mad <46090742+DefiCake@users.noreply.github.com> Date: Fri, 17 May 2024 11:27:02 +0200 Subject: [PATCH 26/28] Update packages/message-predicates/contract-message-predicate/script_asm.rs Co-authored-by: K1-R1 <77465250+K1-R1@users.noreply.github.com> --- .../message-predicates/contract-message-predicate/script_asm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/message-predicates/contract-message-predicate/script_asm.rs b/packages/message-predicates/contract-message-predicate/script_asm.rs index 7c5c9567..72c6e29a 100644 --- a/packages/message-predicates/contract-message-predicate/script_asm.rs +++ b/packages/message-predicates/contract-message-predicate/script_asm.rs @@ -22,7 +22,7 @@ pub fn bytecode() -> Vec { //referenced data start pointer const REF_DATA_START_PTR: u16 = 13 * BYTES_PER_INSTR; - /* The following assembly code is intended to + /* The following assembly code is intended to: * Call the function `process_message` on the contract with ID that matches * the first 32 bytes in the message data field. It won't forward the possible value * stored in the message. L1 entities sending messages here MUST NOT attach From f00dcc6eca75211217863fb95893aebb29918ab4 Mon Sep 17 00:00:00 2001 From: DefiCake Date: Fri, 17 May 2024 11:28:58 +0200 Subject: [PATCH 27/28] refactor: use constant at script_asm.rs --- .../message-predicates/contract-message-predicate/script_asm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/message-predicates/contract-message-predicate/script_asm.rs b/packages/message-predicates/contract-message-predicate/script_asm.rs index 72c6e29a..445b2bc0 100644 --- a/packages/message-predicates/contract-message-predicate/script_asm.rs +++ b/packages/message-predicates/contract-message-predicate/script_asm.rs @@ -41,7 +41,7 @@ pub fn bytecode() -> Vec { op::addi(REG_FN_SELECTOR_PTR, RegId::IS, REF_DATA_START_PTR), op::addi(REG_DATA_FN_SELECTOR_PTR, REG_DATA_PTR, 32), // REG_DATA_FN_SELECTOR_PTR = REG_DATA_PTR + 32 op::sw(REG_DATA_FN_SELECTOR_PTR, REG_FN_SELECTOR_PTR, 0), // REG_DATA[32..39] = (End of IS)[0..7] = (len of "process_message") - op::addi(REG_CALLDATA_PTR, RegId::IS, REF_DATA_START_PTR + 23), // REG_DATA_FN_SELECTOR_PTR = REG_DATA_PTR + 32 + 23 + op::addi(REG_CALLDATA_PTR, RegId::IS, REF_DATA_START_PTR + FN_SEL_BYTES_LEN), // REG_DATA_FN_SELECTOR_PTR = REG_DATA_PTR + 32 + 23 op::addi(REG_DATA_CALLDATA_PTR, REG_DATA_PTR, 40), // REG_DATA_FN_SELECTOR_PTR = REG_DATA_PTR + 40 op::sw(REG_DATA_CALLDATA_PTR, REG_CALLDATA_PTR, 0), // REG_DATA[40..47] = (End of IS)[23..30] = msg_idx = 0 op::call(REG_DATA_PTR, RegId::ZERO, RegId::ZERO, RegId::CGAS), From f13adac341cc39efa79f0a1fec3e04b85ee0e4cc Mon Sep 17 00:00:00 2001 From: DefiCake Date: Fri, 17 May 2024 13:18:08 +0200 Subject: [PATCH 28/28] docs: fix typo --- .../message-predicates/contract-message-predicate/script_asm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/message-predicates/contract-message-predicate/script_asm.rs b/packages/message-predicates/contract-message-predicate/script_asm.rs index 445b2bc0..51af58fb 100644 --- a/packages/message-predicates/contract-message-predicate/script_asm.rs +++ b/packages/message-predicates/contract-message-predicate/script_asm.rs @@ -37,7 +37,7 @@ pub fn bytecode() -> Vec { RegId::ZERO, GTFArgs::InputMessageData.into(), ), //REG_CONTRACT_ADDR_PTR = memory location of the message data from input[0] - op::mcpi(REG_DATA_PTR, REG_CONTRACT_ADDR_PTR, 32), // REG_DATA[0..31] = REG_CONTRACT_ADDR_PTR[0..32] + op::mcpi(REG_DATA_PTR, REG_CONTRACT_ADDR_PTR, 32), // REG_DATA[0..31] = REG_CONTRACT_ADDR_PTR[0..31] op::addi(REG_FN_SELECTOR_PTR, RegId::IS, REF_DATA_START_PTR), op::addi(REG_DATA_FN_SELECTOR_PTR, REG_DATA_PTR, 32), // REG_DATA_FN_SELECTOR_PTR = REG_DATA_PTR + 32 op::sw(REG_DATA_FN_SELECTOR_PTR, REG_FN_SELECTOR_PTR, 0), // REG_DATA[32..39] = (End of IS)[0..7] = (len of "process_message")