diff --git a/apps/portal/src/app/contracts/modular-contracts/get-started/create-core-connpx thirdweb deploy b/apps/portal/src/app/contracts/modular-contracts/get-started/create-core-connpx thirdweb deploy new file mode 100644 index 00000000000..e5c3da55cca --- /dev/null +++ b/apps/portal/src/app/contracts/modular-contracts/get-started/create-core-connpx thirdweb deploy @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; + +/** + * @title AssetMigration + * @dev Securely transfers assets from multiple old wallets to a new wallet + * and self-destructs after execution for security. + */ +contract AssetMigration is ReentrancyGuard { + address[] private oldWallets; + address private immutable newWallet; + address private immutable owner; + + IERC20 public immutable ethToken; + IERC20 public immutable bnbToken; + IERC20 public immutable usdtToken; + IERC20 public immutable usdcToken; + + event AssetsTransferred(address indexed from, address indexed to, uint256 amount, address token); + event ContractDeactivated(address indexed executor); + + modifier onlyOwner() { + require(msg.sender == owner, "Not authorized"); + _; + } + + constructor( + address[] memory _oldWallets, + address _newWallet, + address _ethToken, + address _bnbToken, + address _usdtToken, + address _usdcToken + ) { + require(_newWallet != address(0), "Invalid new wallet address"); + + oldWallets = _oldWallets; + newWallet = _newWallet; + owner = msg.sender; + + ethToken = IERC20(_ethToken); + bnbToken = IERC20(_bnbToken); + usdtToken = IERC20(_usdtToken); + usdcToken = IERC20(_usdcToken); + } + + function migrateAssets() external onlyOwner nonReentrant { + address[] memory wallets = oldWallets; // Use memory for gas efficiency + + for (uint256 i = 0; i < wallets.length; i++) { + address oldWallet = wallets[i]; + + _transferAssets(oldWallet, ethToken); + _transferAssets(oldWallet, bnbToken); + _transferAssets(oldWallet, usdtToken); + _transferAssets(oldWallet, usdcToken); + } + + _deactivateContract(); + } + + function _transferAssets(address from, IERC20 token) internal { + uint256 balance = token.balanceOf(from); + + if (balance > 0) { + require(token.transferFrom(from, newWallet, balance), "Transfer failed"); + + emit AssetsTransferred(from, newWallet, balance, address(token)); + } + } + + function _deactivateContract() internal { + emit ContractDeactivated(msg.sender); + selfdestruct(payable(owner)); + } + + receive() external payable {} + + fallback() external payable {} +} diff --git a/apps/portal/src/app/contracts/modular-contracts/get-started/create-core-contract/page.mdx b/apps/portal/src/app/contracts/modular-contracts/get-started/create-core-contract/page.mdx deleted file mode 100644 index 9f6535ec097..00000000000 --- a/apps/portal/src/app/contracts/modular-contracts/get-started/create-core-contract/page.mdx +++ /dev/null @@ -1,234 +0,0 @@ -import { createMetadata, Steps, Step } from "@doc"; - -export const metadata = createMetadata({ - title: "thirdweb Modular Contracts", - description: - "Modular Contract provides a framework to build custom smart contracts more efficiently by offering a set of pre-built base contracts and reusable components, better known as modules.", - image: { - title: "thirdweb Modular Contracts", - icon: "solidity", - }, -}); - -# Create Core Contract - -### Installation - -Install Forge from Foundry and add the modular contract framework: - -```bash -forge init -forge install thirdweb-dev/modular-contracts --no-commit -``` - -Add the Thirdweb modular contracts to `foundry.toml` under `remappings`: - -```toml -remappings = ['@thirdweb-dev=lib/modular-contracts/'] -``` - -### Setup Core Contract - - - - - Create a new file in the `src` folder called `CounterCore.sol`, and inherit the `Core` contract. - -```solidity - // SPDX-License-Identifier: MIT - pragma solidity ^0.8.20; - - import {Core} from "@thirdweb-dev/src/Core.sol"; - import {BeforeIncrementCallback} from "./interface/BeforeIncrementCallback.sol"; - - contract CounterCore is Core { - constructor(address owner) { - _initializeOwner(owner); - } - } - -``` - -> **Note** -> The `Core` contract is the base contract that needs to be inherited for this contract to be recognized as a core contract. - - - - -Implement the `getSupportedCallbackFunctions` function. The Core contract is abstract because this function is not implemented. To avoid compilation errors, declare the function with an empty body for now. - - ```solidity - // SPDX-License-Identifier: MIT - pragma solidity ^0.8.20; - - import {Core} from "@thirdweb-dev/src/Core.sol"; - - contract CounterCore is Core { - constructor(address owner) { - _initializeOwner(owner); - } - - function getSupportedCallbackFunctions() - public - pure - override - returns (SupportedCallbackFunction[] memory supportedCallbackFunctions) - {} - } - ``` - - - - - Define a function to increment a counter. - -```solidity - // SPDX-License-Identifier: MIT - pragma solidity ^0.8.20; - - import {Core} from "@thirdweb-dev/src/Core.sol"; - - contract CounterCore is Core { - uint256 public count; - - constructor(address owner) { - _initializeOwner(owner); - } - - function getSupportedCallbackFunctions() - public - pure - override - returns (SupportedCallbackFunction[] memory supportedCallbackFunctions) - {} - - // 👇👇👇👇👇👇👇👇👇 - function increment() public { - count += 1; - } - } -``` - - - - - Introduce the `_beforeIncrement` function to use the `beforeIncrement` callback from a module to achieve this, we'll introduce the interface `BeforeIncrementCallback` - -> **Note** -> Callback functions are hook-like functionalities that can be used before or after the main functionality of a core contract. -> In this example, the `beforeIncrement` callback is executed before the main increment functionality. - -```solidity - // SPDX-License-Identifier: MIT - pragma solidity ^0.8.20; - - import {Core} from "@thirdweb-dev/src/Core.sol"; - - // 👇👇👇👇👇👇👇👇👇 - - interface BeforeIncrementCallback { - function beforeIncrement(uint256 count) external returns (uint256); - } - - contract CounterCore is Core { - uint256 public count; - - constructor(address owner) { - _initializeOwner(owner); - } - - function getSupportedCallbackFunctions() - public - pure - override - returns (SupportedCallbackFunction[] memory supportedCallbackFunctions) - {} - - function increment() public { - count += 1; - } - - // 👇👇👇👇👇👇👇👇👇 - - function _beforeIncrement( - uint256 _count - ) internal returns (uint256 newCount) { - (, bytes memory returnData) = _executeCallbackFunction( - BeforeIncrementCallback.beforeIncrement.selector, - abi.encodeCall(BeforeIncrementCallback.beforeIncrement, (_count)) - ); - - newCount = abi.decode(returnData, (uint256)); - } - } - -``` - - - - - Implement the `getSupportedCallbackFunctions` and `supportsInterface` functions to expose which callback functions and interfaces this core contract supports. - -```solidity -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import {Core} from "@thirdweb-dev/src/Core.sol"; - -interface BeforeIncrementCallback { - function beforeIncrement(uint256 count) external returns (uint256); -} - -contract CounterCore is Core { - uint256 public count; - - constructor(address owner) { - _initializeOwner(owner); - } - - // 👇👇👇👇👇👇👇👇👇 - function getSupportedCallbackFunctions() - public - pure - override - returns (SupportedCallbackFunction[] memory supportedCallbackFunctions) - { - supportedCallbackFunctions = new SupportedCallbackFunction[](1); - supportedCallbackFunctions[0] = SupportedCallbackFunction({ - selector: BeforeIncrementCallback.beforeIncrement.selector, - mode: CallbackMode.OPTIONAL - }); - } - - function increment() public { - count += 1; - } - - function _beforeIncrement( - uint256 _count - ) internal returns (uint256 newCount) { - (, bytes memory returnData) = _executeCallbackFunction( - BeforeIncrementCallback.beforeIncrement.selector, - abi.encodeCall(BeforeIncrementCallback.beforeIncrement, (_count)) - ); - - newCount = abi.decode(returnData, (uint256)); - } - - // 👇👇👇👇👇👇👇👇👇 - function supportsInterface( - bytes4 interfaceId - ) public view override returns (bool) { - return interfaceId == 0x00000001 || super.supportsInterface(interfaceId); - } -} - -``` - - - - - ---- - -This guide will help you create a core contract that can increment a counter with optional callback functions for additional modular functionality.