From 181894b9ef9e4bf6b2ae264cbca5fd9a8839e7c2 Mon Sep 17 00:00:00 2001 From: Oleksandr Date: Tue, 26 Nov 2024 11:51:48 +0200 Subject: [PATCH] add deployment scripts --- smart-contracts/IDelegateRegistry.sol | 221 ++++++++++++++++++ .../deploy/1_full_protocol.migration.ts | 2 +- .../deploy/2_change_bid_price.migration.ts | 20 ++ .../deploy/data/config_arbitrum_mainnet.json | 43 ++++ .../deploy/data/config_arbitrum_sepolia.json | 2 +- .../deploy/helpers/config-parser.ts | 3 +- smart-contracts/hardhat.config.ts | 9 + 7 files changed, 297 insertions(+), 3 deletions(-) create mode 100644 smart-contracts/IDelegateRegistry.sol create mode 100644 smart-contracts/deploy/2_change_bid_price.migration.ts create mode 100644 smart-contracts/deploy/data/config_arbitrum_mainnet.json diff --git a/smart-contracts/IDelegateRegistry.sol b/smart-contracts/IDelegateRegistry.sol new file mode 100644 index 00000000..7c9e0015 --- /dev/null +++ b/smart-contracts/IDelegateRegistry.sol @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: CC0-1.0 +pragma solidity ^0.8.24; // Changed from `pragma solidity >=0.8.13;` + +/** + * @title IDelegateRegistry + * @custom:version 2.0 + * @custom:author foobar (0xfoobar) + * @notice A standalone immutable registry storing delegated permissions from one address to another + */ +interface IDelegateRegistry { + /// @notice Delegation type, NONE is used when a delegation does not exist or is revoked + enum DelegationType { + NONE, + ALL, + CONTRACT, + ERC721, + ERC20, + ERC1155 + } + + /// @notice Struct for returning delegations + struct Delegation { + DelegationType type_; + address to; + address from; + bytes32 rights; + address contract_; + uint256 tokenId; + uint256 amount; + } + + /// @notice Emitted when an address delegates or revokes rights for their entire wallet + event DelegateAll(address indexed from, address indexed to, bytes32 rights, bool enable); + + /// @notice Emitted when an address delegates or revokes rights for a contract address + event DelegateContract(address indexed from, address indexed to, address indexed contract_, bytes32 rights, bool enable); + + /// @notice Emitted when an address delegates or revokes rights for an ERC721 tokenId + event DelegateERC721(address indexed from, address indexed to, address indexed contract_, uint256 tokenId, bytes32 rights, bool enable); + + /// @notice Emitted when an address delegates or revokes rights for an amount of ERC20 tokens + event DelegateERC20(address indexed from, address indexed to, address indexed contract_, bytes32 rights, uint256 amount); + + /// @notice Emitted when an address delegates or revokes rights for an amount of an ERC1155 tokenId + event DelegateERC1155(address indexed from, address indexed to, address indexed contract_, uint256 tokenId, bytes32 rights, uint256 amount); + + /// @notice Thrown if multicall calldata is malformed + error MulticallFailed(); + + /** + * ----------- WRITE ----------- + */ + + /** + * @notice Call multiple functions in the current contract and return the data from all of them if they all succeed + * @param data The encoded function data for each of the calls to make to this contract + * @return results The results from each of the calls passed in via data + */ + function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); + + /** + * @notice Allow the delegate to act on behalf of `msg.sender` for all contracts + * @param to The address to act as delegate + * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights + * @param enable Whether to enable or disable this delegation, true delegates and false revokes + * @return delegationHash The unique identifier of the delegation + */ + function delegateAll(address to, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash); + + /** + * @notice Allow the delegate to act on behalf of `msg.sender` for a specific contract + * @param to The address to act as delegate + * @param contract_ The contract whose rights are being delegated + * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights + * @param enable Whether to enable or disable this delegation, true delegates and false revokes + * @return delegationHash The unique identifier of the delegation + */ + function delegateContract(address to, address contract_, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash); + + /** + * @notice Allow the delegate to act on behalf of `msg.sender` for a specific ERC721 token + * @param to The address to act as delegate + * @param contract_ The contract whose rights are being delegated + * @param tokenId The token id to delegate + * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights + * @param enable Whether to enable or disable this delegation, true delegates and false revokes + * @return delegationHash The unique identifier of the delegation + */ + function delegateERC721(address to, address contract_, uint256 tokenId, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash); + + /** + * @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC20 tokens + * @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound) + * @param to The address to act as delegate + * @param contract_ The address for the fungible token contract + * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights + * @param amount The amount to delegate, > 0 delegates and 0 revokes + * @return delegationHash The unique identifier of the delegation + */ + function delegateERC20(address to, address contract_, bytes32 rights, uint256 amount) external payable returns (bytes32 delegationHash); + + /** + * @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC1155 tokens + * @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound) + * @param to The address to act as delegate + * @param contract_ The address of the contract that holds the token + * @param tokenId The token id to delegate + * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights + * @param amount The amount of that token id to delegate, > 0 delegates and 0 revokes + * @return delegationHash The unique identifier of the delegation + */ + function delegateERC1155(address to, address contract_, uint256 tokenId, bytes32 rights, uint256 amount) external payable returns (bytes32 delegationHash); + + /** + * ----------- CHECKS ----------- + */ + + /** + * @notice Check if `to` is a delegate of `from` for the entire wallet + * @param to The potential delegate address + * @param from The potential address who delegated rights + * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only + * @return valid Whether delegate is granted to act on the from's behalf + */ + function checkDelegateForAll(address to, address from, bytes32 rights) external view returns (bool); + + /** + * @notice Check if `to` is a delegate of `from` for the specified `contract_` or the entire wallet + * @param to The delegated address to check + * @param contract_ The specific contract address being checked + * @param from The cold wallet who issued the delegation + * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only + * @return valid Whether delegate is granted to act on from's behalf for entire wallet or that specific contract + */ + function checkDelegateForContract(address to, address from, address contract_, bytes32 rights) external view returns (bool); + + /** + * @notice Check if `to` is a delegate of `from` for the specific `contract` and `tokenId`, the entire `contract_`, or the entire wallet + * @param to The delegated address to check + * @param contract_ The specific contract address being checked + * @param tokenId The token id for the token to delegating + * @param from The wallet that issued the delegation + * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only + * @return valid Whether delegate is granted to act on from's behalf for entire wallet, that contract, or that specific tokenId + */ + function checkDelegateForERC721(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view returns (bool); + + /** + * @notice Returns the amount of ERC20 tokens the delegate is granted rights to act on the behalf of + * @param to The delegated address to check + * @param contract_ The address of the token contract + * @param from The cold wallet who issued the delegation + * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only + * @return balance The delegated balance, which will be 0 if the delegation does not exist + */ + function checkDelegateForERC20(address to, address from, address contract_, bytes32 rights) external view returns (uint256); + + /** + * @notice Returns the amount of a ERC1155 tokens the delegate is granted rights to act on the behalf of + * @param to The delegated address to check + * @param contract_ The address of the token contract + * @param tokenId The token id to check the delegated amount of + * @param from The cold wallet who issued the delegation + * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only + * @return balance The delegated balance, which will be 0 if the delegation does not exist + */ + function checkDelegateForERC1155(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view returns (uint256); + + /** + * ----------- ENUMERATIONS ----------- + */ + + /** + * @notice Returns all enabled delegations a given delegate has received + * @param to The address to retrieve delegations for + * @return delegations Array of Delegation structs + */ + function getIncomingDelegations(address to) external view returns (Delegation[] memory delegations); + + /** + * @notice Returns all enabled delegations an address has given out + * @param from The address to retrieve delegations for + * @return delegations Array of Delegation structs + */ + function getOutgoingDelegations(address from) external view returns (Delegation[] memory delegations); + + /** + * @notice Returns all hashes associated with enabled delegations an address has received + * @param to The address to retrieve incoming delegation hashes for + * @return delegationHashes Array of delegation hashes + */ + function getIncomingDelegationHashes(address to) external view returns (bytes32[] memory delegationHashes); + + /** + * @notice Returns all hashes associated with enabled delegations an address has given out + * @param from The address to retrieve outgoing delegation hashes for + * @return delegationHashes Array of delegation hashes + */ + function getOutgoingDelegationHashes(address from) external view returns (bytes32[] memory delegationHashes); + + /** + * @notice Returns the delegations for a given array of delegation hashes + * @param delegationHashes is an array of hashes that correspond to delegations + * @return delegations Array of Delegation structs, return empty structs for nonexistent or revoked delegations + */ + function getDelegationsFromHashes(bytes32[] calldata delegationHashes) external view returns (Delegation[] memory delegations); + + /** + * ----------- STORAGE ACCESS ----------- + */ + + /** + * @notice Allows external contracts to read arbitrary storage slots + */ + function readSlot(bytes32 location) external view returns (bytes32); + + /** + * @notice Allows external contracts to read an arbitrary array of storage slots + */ + function readSlots(bytes32[] calldata locations) external view returns (bytes32[] memory); +} \ No newline at end of file diff --git a/smart-contracts/deploy/1_full_protocol.migration.ts b/smart-contracts/deploy/1_full_protocol.migration.ts index f7abe4ad..4df39438 100644 --- a/smart-contracts/deploy/1_full_protocol.migration.ts +++ b/smart-contracts/deploy/1_full_protocol.migration.ts @@ -116,7 +116,7 @@ module.exports = async function (deployer: Deployer) { await modelRegistryFacet.modelSetMinStake(config.modelMinStake); await marketplaceFacet.setMarketplaceBidFee(config.marketplaceBidFee); - // TODO: add allowance from the treasury + await lumerinDiamond.transferOwnership(config.owner); Reporter.reportContracts( ['Lumerin Diamond', await lumerinDiamond.getAddress()], diff --git a/smart-contracts/deploy/2_change_bid_price.migration.ts b/smart-contracts/deploy/2_change_bid_price.migration.ts new file mode 100644 index 00000000..98ad21c9 --- /dev/null +++ b/smart-contracts/deploy/2_change_bid_price.migration.ts @@ -0,0 +1,20 @@ +import { Deployer } from '@solarity/hardhat-migrate'; + +import { Marketplace__factory } from '@/generated-types/ethers'; + +module.exports = async function (deployer: Deployer) { + // const marketplaceFacet = await deployer.deployed(Marketplace__factory, '0xb8C55cD613af947E73E262F0d3C54b7211Af16CF'); + const marketplaceFacet = await deployer.deployed(Marketplace__factory, '0xDE819AaEE474626E3f34Ef0263373357e5a6C71b'); + + console.log(await marketplaceFacet.getMinMaxBidPricePerSecond()); + + // await marketplaceFacet.setMinMaxBidPricePerSecond('10000000000', '10000000000000000'); +}; + +// npx hardhat migrate --only 2 + +// npx hardhat migrate --network arbitrum_sepolia --only 2 --verify +// npx hardhat migrate --network arbitrum_sepolia --only 2 --verify --continue + +// npx hardhat migrate --network arbitrum --only 1 --verify +// npx hardhat migrate --network arbitrum --only 1 --verify --continue diff --git a/smart-contracts/deploy/data/config_arbitrum_mainnet.json b/smart-contracts/deploy/data/config_arbitrum_mainnet.json new file mode 100644 index 00000000..f20a0c6a --- /dev/null +++ b/smart-contracts/deploy/data/config_arbitrum_mainnet.json @@ -0,0 +1,43 @@ +{ + "MOR": "0x092baadb7def4c3981454dd9c0a0d7ff07bcfc86", + "fundingAccount": "0x1FE04BC15Cf2c5A2d41a0b3a96725596676eBa1E", + "providerMinStake": "100000000000000000", + "modelMinStake": "100000000000000000", + "marketplaceBidFee": "100000000000000000", + "marketplaceMinBidPricePerSecond": "10000000000000", + "marketplaceMaxBidPricePerSecond": "10000000000000000", + "delegateRegistry": "0x00000000000000447e69651d841bD8D104Bed493", + "owner": "0x1FE04BC15Cf2c5A2d41a0b3a96725596676eBa1E", + "pools": [ + { + "payoutStart": 1707393600, + "decreaseInterval": 86400, + "initialReward": "3456000000000000000000", + "rewardDecrease": "592558728240000000" + }, + { + "payoutStart": 1707393600, + "decreaseInterval": 86400, + "initialReward": "3456000000000000000000", + "rewardDecrease": "592558728240000000" + }, + { + "payoutStart": 1707393600, + "decreaseInterval": 86400, + "initialReward": "3456000000000000000000", + "rewardDecrease": "592558728240000000" + }, + { + "payoutStart": 1707393600, + "decreaseInterval": 86400, + "initialReward": "3456000000000000000000", + "rewardDecrease": "592558728240000000" + }, + { + "payoutStart": 1707393600, + "decreaseInterval": 86400, + "initialReward": "576000000000000000000", + "rewardDecrease": "98759788040000000" + } + ] +} diff --git a/smart-contracts/deploy/data/config_arbitrum_sepolia.json b/smart-contracts/deploy/data/config_arbitrum_sepolia.json index 42edaa04..097fe54d 100644 --- a/smart-contracts/deploy/data/config_arbitrum_sepolia.json +++ b/smart-contracts/deploy/data/config_arbitrum_sepolia.json @@ -7,7 +7,7 @@ "marketplaceMinBidPricePerSecond": "5000000000000000", "marketplaceMaxBidPricePerSecond": "20000000000000000000", "delegateRegistry": "0x00000000000000447e69651d841bD8D104Bed493", - + "owner": "0x1FE04BC15Cf2c5A2d41a0b3a96725596676eBa1E", "pools": [ { "payoutStart": 1707393600, diff --git a/smart-contracts/deploy/helpers/config-parser.ts b/smart-contracts/deploy/helpers/config-parser.ts index 10a3773f..00c27417 100644 --- a/smart-contracts/deploy/helpers/config-parser.ts +++ b/smart-contracts/deploy/helpers/config-parser.ts @@ -12,10 +12,11 @@ export type Config = { marketplaceMinBidPricePerSecond: string; marketplaceMaxBidPricePerSecond: string; delegateRegistry: string; + owner: string; }; export function parseConfig(): Config { - const configPath = `deploy/data/config_arbitrum_sepolia.json`; + const configPath = `deploy/data/config_arbitrum_mainnet.json`; return JSON.parse(readFileSync(configPath, 'utf-8')) as Config; } diff --git a/smart-contracts/hardhat.config.ts b/smart-contracts/hardhat.config.ts index 953250c8..71780988 100644 --- a/smart-contracts/hardhat.config.ts +++ b/smart-contracts/hardhat.config.ts @@ -39,6 +39,9 @@ const config: HardhatUserConfig = { // forking: { // url: `https://arbitrum-sepolia.infura.io/v3/${process.env.INFURA_KEY}`, // }, + forking: { + url: `https://arbitrum-mainnet.infura.io/v3/${process.env.INFURA_KEY}`, + }, }, localhost: { url: 'http://127.0.0.1:8545', @@ -46,6 +49,11 @@ const config: HardhatUserConfig = { gasMultiplier: 1.2, timeout: 1000000000000000, }, + arbitrum: { + url: `https://arbitrum-mainnet.infura.io/v3/${process.env.INFURA_KEY}`, + accounts: privateKey(), + gasMultiplier: 1.1, + }, arbitrum_sepolia: { url: `https://arbitrum-sepolia.infura.io/v3/${process.env.INFURA_KEY}`, accounts: privateKey(), @@ -94,6 +102,7 @@ const config: HardhatUserConfig = { apiKey: { mainnet: `${process.env.ETHERSCAN_API_KEY}`, arbitrumSepolia: `${process.env.ARBITRUM_API_KEY}`, + arbitrumOne: `${process.env.ARBITRUM_API_KEY}`, }, }, };