diff --git a/.gitmodules b/.gitmodules index e29ed65..f8bd6c4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "lib/forge-std"] path = lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "lib/xeon-testnet"] + path = lib/xeon-testnet + url = https://github.com/xeon-protocol/xeon-testnet \ No newline at end of file diff --git a/abi/MockERC20Factory.abi.json b/abi/MockERC20Factory.abi.json deleted file mode 100644 index 1f958c9..0000000 --- a/abi/MockERC20Factory.abi.json +++ /dev/null @@ -1,528 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AccessControlBadConfirmation", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "neededRole", - "type": "bytes32" - } - ], - "name": "AccessControlUnauthorizedAccount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "symbol", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "initialSupply", - "type": "uint256" - } - ], - "name": "NewTokenDeployed", - "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" - }, - { - "inputs": [], - "name": "ADMIN_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": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "addAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "admins", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "symbol", - "type": "string" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "initialSupply", - "type": "uint256" - } - ], - "name": "deploy", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialSupply", - "type": "uint256" - } - ], - "name": "deployMockWETH", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAdmins", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getDeployedTokens", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "tokenAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "symbol", - "type": "string" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "totalSupply", - "type": "uint256" - } - ], - "internalType": "struct MockERC20Factory.TokenInfo[]", - "name": "", - "type": "tuple[]" - } - ], - "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": "address", - "name": "tokenAddress", - "type": "address" - } - ], - "name": "getTokenHolders", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "tokenAddress", - "type": "address" - } - ], - "name": "getTotalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantMinterRole", - "outputs": [], - "stateMutability": "nonpayable", - "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": "address", - "name": "admin", - "type": "address" - } - ], - "name": "removeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "callerConfirmation", - "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": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "tokens", - "outputs": [ - { - "internalType": "address", - "name": "tokenAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "symbol", - "type": "string" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "totalSupply", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/abi/OnboardingUtils.abi.json b/abi/OnboardingUtils.abi.json deleted file mode 100644 index 5504c0d..0000000 --- a/abi/OnboardingUtils.abi.json +++ /dev/null @@ -1,516 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract MockERC20Factory", - "name": "_tokenFactory", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { "inputs": [], "name": "AccessControlBadConfirmation", "type": "error" }, - { - "inputs": [ - { "internalType": "address", "name": "account", "type": "address" }, - { "internalType": "bytes32", "name": "neededRole", "type": "bytes32" } - ], - "name": "AccessControlUnauthorizedAccount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "AdminAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "AdminRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "InitialTokensClaimed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "referrer", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "referralBonus", - "type": "uint256" - } - ], - "name": "InitialTokensClaimedWithReferral", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "oldFactory", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newFactory", - "type": "address" - } - ], - "name": "MockERC20FactoryUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "referrer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "referee", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ReferralReward", - "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": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "TokensAirdropped", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "TokensClaimed", - "type": "event" - }, - { - "inputs": [], - "name": "ADMIN_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": [ - { "internalType": "address", "name": "admin", "type": "address" } - ], - "name": "addAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "user", "type": "address" }, - { "internalType": "address", "name": "token", "type": "address" }, - { "internalType": "uint256", "name": "amount", "type": "uint256" } - ], - "name": "airdropTokens", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "claimAmount", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "token", "type": "address" } - ], - "name": "claimInitial", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "token", "type": "address" }, - { "internalType": "address", "name": "referredBy", "type": "address" } - ], - "name": "claimInitialWithReferral", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "token", "type": "address" } - ], - "name": "claimTokens", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "user", "type": "address" } - ], - "name": "getReferralCount", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "user", "type": "address" } - ], - "name": "getReferralsBy", - "outputs": [ - { "internalType": "address[]", "name": "", "type": "address[]" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "user", "type": "address" } - ], - "name": "getReferrerOf", - "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": "address", "name": "", "type": "address" }], - "name": "hasClaimedInitial", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "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": "address", "name": "user", "type": "address" } - ], - "name": "hasUserClaimedInitial", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialClaimAmount", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [{ "internalType": "address", "name": "", "type": "address" }], - "name": "lastClaimTime", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [{ "internalType": "address", "name": "", "type": "address" }], - "name": "referralCount", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "", "type": "address" }, - { "internalType": "uint256", "name": "", "type": "uint256" } - ], - "name": "referrals", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [{ "internalType": "address", "name": "", "type": "address" }], - "name": "referrerOf", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "admin", "type": "address" } - ], - "name": "removeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, - { - "internalType": "address", - "name": "callerConfirmation", - "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": "contract MockERC20Factory", - "name": "_tokenFactory", - "type": "address" - } - ], - "name": "setTokenFactory", - "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": "tokenFactory", - "outputs": [ - { - "internalType": "contract MockERC20Factory", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/script/Onboarding.s.sol b/script/Onboarding.s.sol deleted file mode 100644 index 64e6dcc..0000000 --- a/script/Onboarding.s.sol +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.20; - -import {Script, console2} from "@forge-std/Script.sol"; -import {MockERC20, MockERC20Factory, MockWETH} from "../src/testnet/MockERC20Factory.sol"; -import {OnboardingUtils} from "../src/testnet/OnboardingUtils.sol"; - - -contract OnboardingScript is Script { - address public deployer = 0x56557c3266d11541c2D939BF6C05BFD29e881e55; - - address[] public admin = [ - 0xFc09CA87a0E58C8d9e01bC3060CBEB60Ad434cd4, - 0x212dB369d8C032c3D319e2136eA85F34742Ea399, - 0x5Fb8EfD425C3eBB85C0773CE33820abC28d1b858 - ]; - - // base sepolia - // simulate: forge script script/Onboarding.s.sol:OnboardingScript --rpc-url $BASE_SEPOLIA_RPC_URL --chain-id 84532 -vvvv - // broadcast: forge script script/Onboarding.s.sol:OnboardingScript --rpc-url $BASE_SEPOLIA_RPC_URL --chain-id 84532 -vv --broadcast --verify - - function setUp() public {} - - function run() public { - vm.startBroadcast(vm.envUint("DEPLOYER_PRIVATE_KEY")); - - console2.log("deploying MockERC20Factory contract..."); - MockERC20Factory tokenFactory = new MockERC20Factory(); - - console2.log("deploying OnboardingUtils contract..."); - address wethAddress = tokenFactory.deployMockWETH(0); - OnboardingUtils onboardingUtils = new OnboardingUtils(tokenFactory, wethAddress); - - console2.log("adding admin accounts to token factory..."); - for (uint256 i = 0; i < admin.length; i++) { - tokenFactory.addAdmin(admin[i]); - } - - console2.log("adding admin accounts to onboarding utils..."); - for (uint256 i = 0; i < admin.length; i++) { - onboardingUtils.addAdmin(admin[i]); - } - - deployToken(tokenFactory, onboardingUtils, "Vela Exchange", "oVELA"); - deployToken(tokenFactory, onboardingUtils, "Pepe", "oPEPE"); - deployToken(tokenFactory, onboardingUtils, "Degen", "oDEGEN"); - deployToken(tokenFactory, onboardingUtils, "Higher", "oHIGHER"); - deployToken(tokenFactory, onboardingUtils, "Rorschach", "oROR"); - - logDeployedTokens(tokenFactory); - - vm.stopBroadcast(); - } - - function deployToken( - MockERC20Factory tokenFactory, - OnboardingUtils onboardingUtils, - string memory name, - string memory symbol - ) internal { - console2.log(string(abi.encodePacked("deploying token: ", name, " (", symbol, ")"))); - address tokenAddress = tokenFactory.deploy(name, symbol, 18, 0); - MockERC20 token = MockERC20(tokenAddress); - token.grantRole(token.MINTER_ROLE(), address(onboardingUtils)); - } - - function logDeployedTokens(MockERC20Factory tokenFactory) internal view { - MockERC20Factory.TokenInfo[] memory tokens = tokenFactory.getDeployedTokens(); - for (uint256 i = 0; i < tokens.length; i++) { - console2.log("Token Name:", tokens[i].name); - console2.log("Token Symbol:", tokens[i].symbol); - console2.log("Token Address:", tokens[i].tokenAddress); - } - } -} diff --git a/script/SetOnboardingAdmin.s.sol b/script/SetOnboardingAdmin.s.sol deleted file mode 100644 index ff5820f..0000000 --- a/script/SetOnboardingAdmin.s.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.20; - -import {Script, console2} from "@forge-std/Script.sol"; -import {MockERC20, MockERC20Factory, MockWETH} from "../src/testnet/MockERC20Factory.sol"; -import {OnboardingUtils} from "../src/testnet/OnboardingUtils.sol"; - -/** - * @dev give OnboardingUtils MINTER_ROLE to all MockERC20 tokens - * @notice this script is intended for testnet use only - * @notice used if minting roles were not granted on deployment - */ -contract SetOnboardingAdminScript is Script { - address public deployer = 0x56557c3266d11541c2D939BF6C05BFD29e881e55; - address public onboardingUtilsAddress = 0x88232810891E015161D3e57C1E5A5DA2376407d5; - address public tokenFactoryAddress = 0x5A0d5390c45b49505C43A56DA4A4f89b93023F11; - address public wethAddress = 0x395cB7753B02A15ed1C099DFc36bF00171F18218; - - address[] public admin = [ - 0xFc09CA87a0E58C8d9e01bC3060CBEB60Ad434cd4, - 0x212dB369d8C032c3D319e2136eA85F34742Ea399, - 0x5Fb8EfD425C3eBB85C0773CE33820abC28d1b858 - ]; - - // uncomment this if only one token is being updated - //address public tokenAddress = 0xEb2DCAFFFf1b0d5BA76F14Fe6bB8348126339FcB; - - // comment this if only one token is being updated - address[] public tokenAddresses = [ - 0xb7E16D46f26B1615Dcc501931F28F07fD4b0D7F4, // oVELA - 0x7dC9ecE25dcCA41D8a627cb47ded4a9322f7722b, // oPEPE - 0x9B9852A943a570685c3704d70C4F1ebD5EdE109B, // oDEGEN - 0x9855d38b7E6270B9f22F283A0C62330b16Ac909C, // oHIGHER - 0xEb2DCAFFFf1b0d5BA76F14Fe6bB8348126339FcB // oROR - ]; - - // base sepolia - // simulate: forge script script/SetOnboardingAdmin.s.sol:SetOnboardingAdminScript --rpc-url $BASE_SEPOLIA_RPC_URL --chain-id 84532 -vvvv - // broadcast: forge script script/SetOnboardingAdmin.s.sol:SetOnboardingAdminScript --rpc-url $BASE_SEPOLIA_RPC_URL --chain-id 84532 -vv --broadcast --verify - - function setUp() public {} - - function run() public { - vm.startBroadcast(vm.envUint("DEPLOYER_PRIVATE_KEY")); - - console2.log("Granting MINTER_ROLE to OnboardingUtils for WETH..."); - grantMinterRole(wethAddress); - - // uncomment this if only one token is being updated - // console2.log("Granting MINTER_ROLE to OnboardingUtils for token:", tokenAddress); - // grantMinterRole(tokenAddress); - - // comment this if only one token is being updated - for (uint256 i = 0; i < tokenAddresses.length; i++) { - console2.log("Granting MINTER_ROLE to OnboardingUtils for token:", tokenAddresses[i]); - grantMinterRole(tokenAddresses[i]); - } - - vm.stopBroadcast(); - } - - function grantMinterRole(address tokenAddress) internal { - MockERC20 token = MockERC20(tokenAddress); - token.grantRole(token.MINTER_ROLE(), onboardingUtilsAddress); - } -} diff --git a/src/testnet/MockERC20Factory.sol b/src/testnet/MockERC20Factory.sol deleted file mode 100644 index b91a97e..0000000 --- a/src/testnet/MockERC20Factory.sol +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.20; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "@openzeppelin/contracts/access/AccessControl.sol"; - -contract MockERC20 is ERC20, AccessControl { - uint8 private _decimals; - bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - mapping(address => bool) private _holders; - address[] private _allHolders; - - constructor(string memory name, string memory symbol, uint8 decimals_, uint256 initialSupply, address admin) - ERC20(name, symbol) - { - _decimals = decimals_; - _mint(admin, initialSupply); - _grantRole(DEFAULT_ADMIN_ROLE, admin); - _grantRole(MINTER_ROLE, admin); - _addHolder(admin); - } - - function mint(address to, uint256 amount) external { - require(hasRole(MINTER_ROLE, msg.sender), "MockERC20: must have minter role to mint"); - _mint(to, amount); - _addHolder(to); - } - - function decimals() public view virtual override returns (uint8) { - return _decimals; - } - - function transfer(address recipient, uint256 amount) public override returns (bool) { - _addHolder(recipient); - return super.transfer(recipient, amount); - } - - function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) { - _addHolder(recipient); - return super.transferFrom(sender, recipient, amount); - } - - function getAllHolders() external view returns (address[] memory) { - return _allHolders; - } - - function _addHolder(address holder) internal { - if (!_holders[holder]) { - _holders[holder] = true; - _allHolders.push(holder); - } - } -} - -contract MockWETH is MockERC20 { - constructor(uint256 initialSupply, address admin) MockERC20("Wrapped Ether", "WETH", 18, initialSupply, admin) {} -} - -contract MockERC20Factory is AccessControl { - bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); - address[] public admins; - TokenInfo[] public tokens; - - struct TokenInfo { - address tokenAddress; - string name; - string symbol; - uint8 decimals; - uint256 totalSupply; - } - - event NewTokenDeployed(address indexed token, string name, string symbol, uint8 decimals, uint256 initialSupply); - - constructor() { - _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); - _grantRole(ADMIN_ROLE, msg.sender); - admins.push(msg.sender); - } - - function addAdmin(address admin) external { - require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "MockERC20Factory: must have default admin role to add admin"); - grantRole(ADMIN_ROLE, admin); - admins.push(admin); - } - - function removeAdmin(address admin) external { - require( - hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "MockERC20Factory: must have default admin role to remove admin" - ); - revokeRole(ADMIN_ROLE, admin); - for (uint256 i = 0; i < admins.length; i++) { - if (admins[i] == admin) { - admins[i] = admins[admins.length - 1]; - admins.pop(); - break; - } - } - } - - function deploy(string memory name, string memory symbol, uint8 decimals, uint256 initialSupply) - external - returns (address) - { - require(hasRole(ADMIN_ROLE, msg.sender), "MockERC20Factory: must have admin role to deploy token"); - MockERC20 token = new MockERC20(name, symbol, decimals, initialSupply, msg.sender); - tokens.push( - TokenInfo({ - tokenAddress: address(token), - name: name, - symbol: symbol, - decimals: decimals, - totalSupply: initialSupply - }) - ); - emit NewTokenDeployed(address(token), name, symbol, decimals, initialSupply); - return address(token); - } - - function deployMockWETH(uint256 initialSupply) external returns (address) { - require(hasRole(ADMIN_ROLE, msg.sender), "MockERC20Factory: must have admin role to deploy token"); - MockWETH token = new MockWETH(initialSupply, msg.sender); - tokens.push( - TokenInfo({ - tokenAddress: address(token), - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - totalSupply: initialSupply - }) - ); - emit NewTokenDeployed(address(token), "Wrapped Ether", "WETH", 18, initialSupply); - return address(token); - } - - function grantMinterRole(address token, address account) external { - require(hasRole(ADMIN_ROLE, msg.sender), "MockERC20Factory: must have admin role to grant minter role"); - MockERC20(token).grantRole(MockERC20(token).MINTER_ROLE(), account); - } - - function getAdmins() external view returns (address[] memory) { - return admins; - } - - function getDeployedTokens() external view returns (TokenInfo[] memory) { - return tokens; - } - - function getTotalSupply(address tokenAddress) external view returns (uint256) { - for (uint256 i = 0; i < tokens.length; i++) { - if (tokens[i].tokenAddress == tokenAddress) { - return ERC20(tokenAddress).totalSupply(); - } - } - revert("Token not found"); - } - - function getTokenHolders(address tokenAddress) external view returns (address[] memory) { - return MockERC20(tokenAddress).getAllHolders(); - } -} diff --git a/src/testnet/OnboardingUtils.sol b/src/testnet/OnboardingUtils.sol deleted file mode 100644 index 89f6088..0000000 --- a/src/testnet/OnboardingUtils.sol +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.20; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/access/AccessControl.sol"; -import "./MockERC20Factory.sol"; - -contract OnboardingUtils is AccessControl { - /* ============ State Variables ============ */ - - bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); - MockERC20Factory public tokenFactory; - address public weth; - uint256 public initialClaimAmount = 100_000 * 10 ** 18; - uint256 public claimAmount = 10_000 * 10 ** 18; - uint256 public wethClaimAmount = 1 * 10 ** 18; - mapping(address => bool) public hasClaimedInitial; - mapping(address => uint256) public referralCount; - mapping(address => uint256) public lastClaimTime; - mapping(address => address[]) public referrals; - mapping(address => address) public referrerOf; - - /* ============ Events ============ */ - - event TokensAirdropped(address indexed user, address indexed token, uint256 amount); - event TokensClaimed(address indexed user, address indexed token, uint256 amount); - event InitialTokensClaimed(address indexed user, uint256 amount); - event InitialTokensClaimedWithReferral( - address indexed user, address indexed referrer, uint256 amount, uint256 referralBonus - ); - event ReferralReward(address indexed referrer, address indexed referee, uint256 amount); - event MockERC20FactoryUpdated(address indexed oldFactory, address indexed newFactory); - event AdminAdded(address indexed admin); - event AdminRemoved(address indexed admin); - event WETHUpdated(address indexed oldWETH, address indexed newWETH); - - /* ============ Constructor ============ */ - constructor(MockERC20Factory _tokenFactory, address _weth) { - tokenFactory = _tokenFactory; - weth = _weth; - _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); - _grantRole(ADMIN_ROLE, msg.sender); - } - - /* ============ External Functions ============ */ - function addAdmin(address admin) external onlyRole(ADMIN_ROLE) { - grantRole(ADMIN_ROLE, admin); - emit AdminAdded(admin); - } - - function removeAdmin(address admin) external onlyRole(ADMIN_ROLE) { - revokeRole(ADMIN_ROLE, admin); - emit AdminRemoved(admin); - } - - function setTokenFactory(MockERC20Factory _tokenFactory) external onlyRole(ADMIN_ROLE) { - address oldFactory = address(tokenFactory); - tokenFactory = _tokenFactory; - emit MockERC20FactoryUpdated(oldFactory, address(tokenFactory)); - } - - function setWETH(address _weth) external onlyRole(ADMIN_ROLE) { - address oldWETH = weth; - weth = _weth; - emit WETHUpdated(oldWETH, weth); - } - - /** - * @dev claim initial tokens for testnet onboarding, allowed once - * @notice initial claim can only be performed once - * @notice user receives 1 WETH + 100k tokens - * @param token address of the token to claim - */ - function claimInitial(address token) external { - require(!hasClaimedInitial[msg.sender], "OnboardingUtils: Already claimed initial tokens"); - - MockERC20(token).mint(msg.sender, initialClaimAmount); - MockERC20(weth).mint(msg.sender, wethClaimAmount); - - hasClaimedInitial[msg.sender] = true; - lastClaimTime[msg.sender] = block.timestamp; - - emit InitialTokensClaimed(msg.sender, initialClaimAmount); - } - - /** - * @dev claim initial tokens for testnet onboarding with referral - * @notice initial claim can only be performed once - * @notice referral bonus is +10% of claim amount to both accounts - * @param token address of the token to claim - * @param referredBy address of the referee - */ - function claimInitialWithReferral(address token, address referredBy) external { - require(!hasClaimedInitial[msg.sender], "OnboardingUtils: Already claimed initial tokens"); - require(referredBy != msg.sender, "OnboardingUtils: Cannot refer yourself"); - - uint256 referralBonus = initialClaimAmount / 10; // 10% bonus - - MockERC20(token).mint(msg.sender, initialClaimAmount + referralBonus); - MockERC20(token).mint(referredBy, referralBonus); - MockERC20(weth).mint(msg.sender, wethClaimAmount); - - referrals[referredBy].push(msg.sender); - referrerOf[msg.sender] = referredBy; - referralCount[referredBy]++; - - hasClaimedInitial[msg.sender] = true; - lastClaimTime[msg.sender] = block.timestamp; - - emit InitialTokensClaimedWithReferral(msg.sender, referredBy, initialClaimAmount, referralBonus); - } - - /** - * @dev weekly token claim - * @notice user receives 10k tokens - * @param token address of the token to claim - */ - function claimTokens(address token) external { - require(hasClaimedInitial[msg.sender], "OnboardingUtils: Must perform initial claim first"); - require( - block.timestamp >= lastClaimTime[msg.sender] + 1 weeks, "OnboardingUtils: Claim only allowed once per week" - ); - - lastClaimTime[msg.sender] = block.timestamp; - - MockERC20(token).mint(msg.sender, claimAmount); - - emit TokensClaimed(msg.sender, token, claimAmount); - } - - /** - * @dev allow admins to airdrop tokens to users - * @param user address of the user - * @param token address of the token to claim - * @param amount amount of tokens to airdrop - */ - function airdropTokens(address user, address token, uint256 amount) external onlyRole(ADMIN_ROLE) { - MockERC20(token).mint(user, amount); - - emit TokensAirdropped(user, token, amount); - } - - /* ============ Getters ============ */ - function hasUserClaimedInitial(address user) external view returns (bool) { - return hasClaimedInitial[user]; - } - - function getReferralCount(address user) external view returns (uint256) { - return referralCount[user]; - } - - function getReferralsBy(address user) external view returns (address[] memory) { - return referrals[user]; - } - - function getReferrerOf(address user) external view returns (address) { - return referrerOf[user]; - } -} diff --git a/src/utils/MockERC20Factory.sol b/src/utils/MockERC20Factory.sol deleted file mode 100644 index b91a97e..0000000 --- a/src/utils/MockERC20Factory.sol +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.20; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "@openzeppelin/contracts/access/AccessControl.sol"; - -contract MockERC20 is ERC20, AccessControl { - uint8 private _decimals; - bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - mapping(address => bool) private _holders; - address[] private _allHolders; - - constructor(string memory name, string memory symbol, uint8 decimals_, uint256 initialSupply, address admin) - ERC20(name, symbol) - { - _decimals = decimals_; - _mint(admin, initialSupply); - _grantRole(DEFAULT_ADMIN_ROLE, admin); - _grantRole(MINTER_ROLE, admin); - _addHolder(admin); - } - - function mint(address to, uint256 amount) external { - require(hasRole(MINTER_ROLE, msg.sender), "MockERC20: must have minter role to mint"); - _mint(to, amount); - _addHolder(to); - } - - function decimals() public view virtual override returns (uint8) { - return _decimals; - } - - function transfer(address recipient, uint256 amount) public override returns (bool) { - _addHolder(recipient); - return super.transfer(recipient, amount); - } - - function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) { - _addHolder(recipient); - return super.transferFrom(sender, recipient, amount); - } - - function getAllHolders() external view returns (address[] memory) { - return _allHolders; - } - - function _addHolder(address holder) internal { - if (!_holders[holder]) { - _holders[holder] = true; - _allHolders.push(holder); - } - } -} - -contract MockWETH is MockERC20 { - constructor(uint256 initialSupply, address admin) MockERC20("Wrapped Ether", "WETH", 18, initialSupply, admin) {} -} - -contract MockERC20Factory is AccessControl { - bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); - address[] public admins; - TokenInfo[] public tokens; - - struct TokenInfo { - address tokenAddress; - string name; - string symbol; - uint8 decimals; - uint256 totalSupply; - } - - event NewTokenDeployed(address indexed token, string name, string symbol, uint8 decimals, uint256 initialSupply); - - constructor() { - _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); - _grantRole(ADMIN_ROLE, msg.sender); - admins.push(msg.sender); - } - - function addAdmin(address admin) external { - require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "MockERC20Factory: must have default admin role to add admin"); - grantRole(ADMIN_ROLE, admin); - admins.push(admin); - } - - function removeAdmin(address admin) external { - require( - hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "MockERC20Factory: must have default admin role to remove admin" - ); - revokeRole(ADMIN_ROLE, admin); - for (uint256 i = 0; i < admins.length; i++) { - if (admins[i] == admin) { - admins[i] = admins[admins.length - 1]; - admins.pop(); - break; - } - } - } - - function deploy(string memory name, string memory symbol, uint8 decimals, uint256 initialSupply) - external - returns (address) - { - require(hasRole(ADMIN_ROLE, msg.sender), "MockERC20Factory: must have admin role to deploy token"); - MockERC20 token = new MockERC20(name, symbol, decimals, initialSupply, msg.sender); - tokens.push( - TokenInfo({ - tokenAddress: address(token), - name: name, - symbol: symbol, - decimals: decimals, - totalSupply: initialSupply - }) - ); - emit NewTokenDeployed(address(token), name, symbol, decimals, initialSupply); - return address(token); - } - - function deployMockWETH(uint256 initialSupply) external returns (address) { - require(hasRole(ADMIN_ROLE, msg.sender), "MockERC20Factory: must have admin role to deploy token"); - MockWETH token = new MockWETH(initialSupply, msg.sender); - tokens.push( - TokenInfo({ - tokenAddress: address(token), - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - totalSupply: initialSupply - }) - ); - emit NewTokenDeployed(address(token), "Wrapped Ether", "WETH", 18, initialSupply); - return address(token); - } - - function grantMinterRole(address token, address account) external { - require(hasRole(ADMIN_ROLE, msg.sender), "MockERC20Factory: must have admin role to grant minter role"); - MockERC20(token).grantRole(MockERC20(token).MINTER_ROLE(), account); - } - - function getAdmins() external view returns (address[] memory) { - return admins; - } - - function getDeployedTokens() external view returns (TokenInfo[] memory) { - return tokens; - } - - function getTotalSupply(address tokenAddress) external view returns (uint256) { - for (uint256 i = 0; i < tokens.length; i++) { - if (tokens[i].tokenAddress == tokenAddress) { - return ERC20(tokenAddress).totalSupply(); - } - } - revert("Token not found"); - } - - function getTokenHolders(address tokenAddress) external view returns (address[] memory) { - return MockERC20(tokenAddress).getAllHolders(); - } -} diff --git a/src/utils/OnboardingUtils.sol b/src/utils/OnboardingUtils.sol deleted file mode 100644 index 89f6088..0000000 --- a/src/utils/OnboardingUtils.sol +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.20; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/access/AccessControl.sol"; -import "./MockERC20Factory.sol"; - -contract OnboardingUtils is AccessControl { - /* ============ State Variables ============ */ - - bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); - MockERC20Factory public tokenFactory; - address public weth; - uint256 public initialClaimAmount = 100_000 * 10 ** 18; - uint256 public claimAmount = 10_000 * 10 ** 18; - uint256 public wethClaimAmount = 1 * 10 ** 18; - mapping(address => bool) public hasClaimedInitial; - mapping(address => uint256) public referralCount; - mapping(address => uint256) public lastClaimTime; - mapping(address => address[]) public referrals; - mapping(address => address) public referrerOf; - - /* ============ Events ============ */ - - event TokensAirdropped(address indexed user, address indexed token, uint256 amount); - event TokensClaimed(address indexed user, address indexed token, uint256 amount); - event InitialTokensClaimed(address indexed user, uint256 amount); - event InitialTokensClaimedWithReferral( - address indexed user, address indexed referrer, uint256 amount, uint256 referralBonus - ); - event ReferralReward(address indexed referrer, address indexed referee, uint256 amount); - event MockERC20FactoryUpdated(address indexed oldFactory, address indexed newFactory); - event AdminAdded(address indexed admin); - event AdminRemoved(address indexed admin); - event WETHUpdated(address indexed oldWETH, address indexed newWETH); - - /* ============ Constructor ============ */ - constructor(MockERC20Factory _tokenFactory, address _weth) { - tokenFactory = _tokenFactory; - weth = _weth; - _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); - _grantRole(ADMIN_ROLE, msg.sender); - } - - /* ============ External Functions ============ */ - function addAdmin(address admin) external onlyRole(ADMIN_ROLE) { - grantRole(ADMIN_ROLE, admin); - emit AdminAdded(admin); - } - - function removeAdmin(address admin) external onlyRole(ADMIN_ROLE) { - revokeRole(ADMIN_ROLE, admin); - emit AdminRemoved(admin); - } - - function setTokenFactory(MockERC20Factory _tokenFactory) external onlyRole(ADMIN_ROLE) { - address oldFactory = address(tokenFactory); - tokenFactory = _tokenFactory; - emit MockERC20FactoryUpdated(oldFactory, address(tokenFactory)); - } - - function setWETH(address _weth) external onlyRole(ADMIN_ROLE) { - address oldWETH = weth; - weth = _weth; - emit WETHUpdated(oldWETH, weth); - } - - /** - * @dev claim initial tokens for testnet onboarding, allowed once - * @notice initial claim can only be performed once - * @notice user receives 1 WETH + 100k tokens - * @param token address of the token to claim - */ - function claimInitial(address token) external { - require(!hasClaimedInitial[msg.sender], "OnboardingUtils: Already claimed initial tokens"); - - MockERC20(token).mint(msg.sender, initialClaimAmount); - MockERC20(weth).mint(msg.sender, wethClaimAmount); - - hasClaimedInitial[msg.sender] = true; - lastClaimTime[msg.sender] = block.timestamp; - - emit InitialTokensClaimed(msg.sender, initialClaimAmount); - } - - /** - * @dev claim initial tokens for testnet onboarding with referral - * @notice initial claim can only be performed once - * @notice referral bonus is +10% of claim amount to both accounts - * @param token address of the token to claim - * @param referredBy address of the referee - */ - function claimInitialWithReferral(address token, address referredBy) external { - require(!hasClaimedInitial[msg.sender], "OnboardingUtils: Already claimed initial tokens"); - require(referredBy != msg.sender, "OnboardingUtils: Cannot refer yourself"); - - uint256 referralBonus = initialClaimAmount / 10; // 10% bonus - - MockERC20(token).mint(msg.sender, initialClaimAmount + referralBonus); - MockERC20(token).mint(referredBy, referralBonus); - MockERC20(weth).mint(msg.sender, wethClaimAmount); - - referrals[referredBy].push(msg.sender); - referrerOf[msg.sender] = referredBy; - referralCount[referredBy]++; - - hasClaimedInitial[msg.sender] = true; - lastClaimTime[msg.sender] = block.timestamp; - - emit InitialTokensClaimedWithReferral(msg.sender, referredBy, initialClaimAmount, referralBonus); - } - - /** - * @dev weekly token claim - * @notice user receives 10k tokens - * @param token address of the token to claim - */ - function claimTokens(address token) external { - require(hasClaimedInitial[msg.sender], "OnboardingUtils: Must perform initial claim first"); - require( - block.timestamp >= lastClaimTime[msg.sender] + 1 weeks, "OnboardingUtils: Claim only allowed once per week" - ); - - lastClaimTime[msg.sender] = block.timestamp; - - MockERC20(token).mint(msg.sender, claimAmount); - - emit TokensClaimed(msg.sender, token, claimAmount); - } - - /** - * @dev allow admins to airdrop tokens to users - * @param user address of the user - * @param token address of the token to claim - * @param amount amount of tokens to airdrop - */ - function airdropTokens(address user, address token, uint256 amount) external onlyRole(ADMIN_ROLE) { - MockERC20(token).mint(user, amount); - - emit TokensAirdropped(user, token, amount); - } - - /* ============ Getters ============ */ - function hasUserClaimedInitial(address user) external view returns (bool) { - return hasClaimedInitial[user]; - } - - function getReferralCount(address user) external view returns (uint256) { - return referralCount[user]; - } - - function getReferralsBy(address user) external view returns (address[] memory) { - return referrals[user]; - } - - function getReferrerOf(address user) external view returns (address) { - return referrerOf[user]; - } -} diff --git a/test/Onboarding.t.sol b/test/Onboarding.t.sol deleted file mode 100644 index 0883b0a..0000000 --- a/test/Onboarding.t.sol +++ /dev/null @@ -1,262 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.20; - -import {Test} from "@forge-std/Test.sol"; -import {console2} from "@forge-std/console2.sol"; -import {MockERC20, MockERC20Factory, MockWETH} from "../src/testnet/MockERC20Factory.sol"; -import {OnboardingUtils} from "../src/testnet/OnboardingUtils.sol"; - -contract OnboardingTest is Test { - MockERC20Factory public mockERC20Factory; - OnboardingUtils public onboardingUtils; - MockERC20 public mockERC20; - MockWETH public wethToken; - address public deployer = address(this); - address public admin = address(0x1); - address public nonAdmin = address(0x2); - address public user1 = address(0x3); - address public user2 = address(0x4); - - function setUp() public { - console2.log("Setting up the environment..."); - - // Deploy MockERC20Factory contract - mockERC20Factory = new MockERC20Factory(); - console2.log("Deployed MockERC20Factory contract"); - - // Grant deployer default admin role - mockERC20Factory.grantRole(mockERC20Factory.DEFAULT_ADMIN_ROLE(), deployer); - console2.log("Granted DEFAULT_ADMIN_ROLE to deployer"); - - // Deploy WETH token - address wethTokenAddress = mockERC20Factory.deploy("Wrapped Ether", "WETH", 18, 0); - wethToken = MockWETH(wethTokenAddress); - console2.log("Deployed WETH token at:", wethTokenAddress); - - // Deploy OnboardingUtils contract - onboardingUtils = new OnboardingUtils(mockERC20Factory, wethTokenAddress); - console2.log("Initialized OnboardingUtils with MockERC20Factory and WETH address"); - - // Grant admin roles - vm.startPrank(deployer); - mockERC20Factory.addAdmin(admin); - mockERC20Factory.grantRole(mockERC20Factory.DEFAULT_ADMIN_ROLE(), admin); - onboardingUtils.addAdmin(admin); - onboardingUtils.grantRole(onboardingUtils.DEFAULT_ADMIN_ROLE(), admin); - console2.log("Granted roles to admin in both contracts"); - - // Deploy ERC20 token - address tokenAddress = mockERC20Factory.deploy("MockToken", "MTK", 18, 0); - mockERC20 = MockERC20(tokenAddress); - console2.log("Deployed MockERC20 token at:", tokenAddress); - - // Grant minter role to OnboardingUtils for all tokens - mockERC20.grantRole(mockERC20.MINTER_ROLE(), address(onboardingUtils)); - wethToken.grantRole(wethToken.MINTER_ROLE(), address(onboardingUtils)); - console2.log("Granted MINTER_ROLE to OnboardingUtils for MockToken and WETH"); - - vm.stopPrank(); - } - - function test_claimInitial() public { - console2.log("Testing user claiming initial tokens without referral..."); - vm.startPrank(user2); - console2.log("Current account:", user2); - onboardingUtils.claimInitial(address(mockERC20)); - uint256 expectedBalance = 100_000 * 10 ** 18; - uint256 actualBalance = mockERC20.balanceOf(user2); - console2.log("Expected balance:", expectedBalance); - console2.log("Actual balance:", actualBalance); - assertEq(expectedBalance, actualBalance, "User2 balance should be 100_000 MTK after initial claim"); - - uint256 expectedWETHBalance = 1 * 10 ** 18; - uint256 actualWETHBalance = wethToken.balanceOf(user2); - console2.log("Expected WETH balance:", expectedWETHBalance); - console2.log("Actual WETH balance:", actualWETHBalance); - assertEq(expectedWETHBalance, actualWETHBalance, "User2 balance should be 1 WETH after initial claim"); - - vm.stopPrank(); - } - - function test_claimInitialWithReferral() public { - console2.log("Testing user claiming initial tokens with referral..."); - - vm.startPrank(user1); - console2.log("Current account:", user1); - onboardingUtils.claimInitialWithReferral(address(mockERC20), admin); - uint256 expectedUserBalance = 110_000 * 10 ** 18; // 100,000 initial + 10,000 referral bonus - uint256 actualUserBalance = mockERC20.balanceOf(user1); - console2.log("Expected user balance:", expectedUserBalance); - console2.log("Actual user balance:", actualUserBalance); - assertEq( - expectedUserBalance, - actualUserBalance, - "User1 balance should be 110_000 MTK after initial claim with referral" - ); - - uint256 expectedWETHBalance = 1 * 10 ** 18; - uint256 actualWETHBalance = wethToken.balanceOf(user1); - console2.log("Expected WETH balance:", expectedWETHBalance); - console2.log("Actual WETH balance:", actualWETHBalance); - assertEq(expectedWETHBalance, actualWETHBalance, "User1 balance should be 1 WETH after initial claim"); - - vm.stopPrank(); - - vm.startPrank(admin); - console2.log("Current account:", admin); - uint256 expectedAdminBalance = 10_000 * 10 ** 18; // 10,000 referral bonus - uint256 actualAdminBalance = mockERC20.balanceOf(admin); - console2.log("Expected admin balance:", expectedAdminBalance); - console2.log("Actual admin balance:", actualAdminBalance); - assertEq(expectedAdminBalance, actualAdminBalance, "Admin balance should be 10_000 MTK as referral bonus"); - vm.stopPrank(); - } - - function test_claimInitialAlreadyClaimed() public { - console2.log("Testing user trying to claim initial tokens after already claiming..."); - vm.startPrank(user1); - console2.log("Current account:", user1); - onboardingUtils.claimInitial(address(mockERC20)); - vm.expectRevert("OnboardingUtils: Already claimed initial tokens"); - onboardingUtils.claimInitial(address(mockERC20)); - vm.stopPrank(); - } - - function test_claimTokens() public { - address newUser = address(0x5); - console2.log("Testing claiming tokens once per week for a new user..."); - - vm.startPrank(newUser); - console2.log("Current account:", newUser); - vm.expectRevert("OnboardingUtils: Must perform initial claim first"); - onboardingUtils.claimTokens(address(mockERC20)); - vm.stopPrank(); - - vm.startPrank(newUser); - console2.log("Performing initial claim for newUser"); - onboardingUtils.claimInitial(address(mockERC20)); - vm.stopPrank(); - - vm.warp(block.timestamp + 7 days); - - vm.startPrank(newUser); - console2.log("Claiming tokens after initial claim for newUser"); - onboardingUtils.claimTokens(address(mockERC20)); - uint256 expectedBalance = 110_000 * 10 ** 18; - uint256 actualBalance = mockERC20.balanceOf(newUser); - console2.log("Expected balance:", expectedBalance); - console2.log("Actual balance:", actualBalance); - assertEq(expectedBalance, actualBalance, "newUser balance should be 110_000 MTK after claiming tokens"); - vm.stopPrank(); - - vm.startPrank(newUser); - console2.log("Attempting to claim again immediately, expecting a revert"); - vm.expectRevert("OnboardingUtils: Claim only allowed once per week"); - onboardingUtils.claimTokens(address(mockERC20)); - vm.stopPrank(); - - vm.warp(block.timestamp + 7 days); - - vm.startPrank(newUser); - console2.log("Claiming tokens again after one week for newUser"); - onboardingUtils.claimTokens(address(mockERC20)); - uint256 newExpectedBalance = 120_000 * 10 ** 18; - uint256 newActualBalance = mockERC20.balanceOf(newUser); - console2.log("New expected balance:", newExpectedBalance); - console2.log("New actual balance:", newActualBalance); - assertEq( - newExpectedBalance, newActualBalance, "newUser balance should be 120_000 MTK after claiming tokens again" - ); - vm.stopPrank(); - } - - /** - * @notice test getting tokens - */ - function test_getTokens() public { - console2.log("Testing get tokens..."); - vm.startPrank(admin); - console2.log("Current account:", admin); - - // Deploy one additional token - address tokenAddress1 = mockERC20Factory.deploy("TestToken1", "TTK1", 18, 1_000_000 * 10 ** 18); - console2.log("Token1 deployed at:", tokenAddress1); - - // Get all deployed tokens - MockERC20Factory.TokenInfo[] memory tokens = mockERC20Factory.getDeployedTokens(); - console2.log("Number of tokens:", tokens.length); - assertEq(tokens.length, 3, "There should be 3 tokens"); - - // Assertions for the WETH token - console2.log("Token 1 address:", tokens[0].tokenAddress); - console2.log("Token 1 name:", tokens[0].name); - console2.log("Token 1 symbol:", tokens[0].symbol); - console2.log("Token 1 decimals:", tokens[0].decimals); - console2.log("Token 1 total supply:", tokens[0].totalSupply); - assertEq(tokens[0].tokenAddress, address(wethToken), "First token address should match the WETH token"); - assertEq(tokens[0].name, "Wrapped Ether", "First token name should be 'Wrapped Ether'"); - assertEq(tokens[0].symbol, "WETH", "First token symbol should be 'WETH'"); - assertEq(tokens[0].decimals, 18, "First token decimals should be 18"); - assertEq(tokens[0].totalSupply, 0, "First token total supply should be 0"); - - // Assertions for the setup token - console2.log("Token 2 address:", tokens[1].tokenAddress); - console2.log("Token 2 name:", tokens[1].name); - console2.log("Token 2 symbol:", tokens[1].symbol); - console2.log("Token 2 decimals:", tokens[1].decimals); - console2.log("Token 2 total supply:", tokens[1].totalSupply); - assertEq(tokens[1].tokenAddress, address(mockERC20), "Second token address should match the setup token"); - assertEq(tokens[1].name, "MockToken", "Second token name should be 'MockToken'"); - assertEq(tokens[1].symbol, "MTK", "Second token symbol should be 'MTK'"); - assertEq(tokens[1].decimals, 18, "Second token decimals should be 18"); - assertEq(tokens[1].totalSupply, 0, "Second token total supply should be 0"); - - // Assertions for the newly deployed token - console2.log("Token 3 address:", tokens[2].tokenAddress); - console2.log("Token 3 name:", tokens[2].name); - console2.log("Token 3 symbol:", tokens[2].symbol); - console2.log("Token 3 decimals:", tokens[2].decimals); - console2.log("Token 3 total supply:", tokens[2].totalSupply); - assertEq(tokens[2].tokenAddress, tokenAddress1, "Third token address should match"); - assertEq(tokens[2].name, "TestToken1", "Third token name should be 'TestToken1'"); - assertEq(tokens[2].symbol, "TTK1", "Third token symbol should be 'TTK1'"); - assertEq(tokens[2].decimals, 18, "Third token decimals should be 18"); - assertEq(tokens[2].totalSupply, 1_000_000 * 10 ** 18, "Third token total supply should be 1_000_000 TTK1"); - - vm.stopPrank(); - } - - function test_getterMethods() public { - console2.log("Testing getter methods..."); - - vm.startPrank(user1); - onboardingUtils.claimInitialWithReferral(address(mockERC20), admin); - vm.stopPrank(); - - vm.startPrank(user2); - onboardingUtils.claimInitialWithReferral(address(mockERC20), user1); - vm.stopPrank(); - - address[] memory referrals = onboardingUtils.getReferralsBy(user1); - console2.log("Number of referrals by user1:", referrals.length); - assertEq(referrals.length, 1, "User1 should have 1 referral"); - console2.log("User1's referral:", referrals[0]); - assertEq(referrals[0], user2, "User1's referral should be User2"); - - address referrer = onboardingUtils.getReferrerOf(user2); - console2.log("User2's referrer:", referrer); - assertEq(referrer, user1, "User2's referrer should be User1"); - - bool hasClaimed = onboardingUtils.hasUserClaimedInitial(user1); - console2.log("User1 has claimed initial tokens:", hasClaimed); - assertTrue(hasClaimed, "User1 should have claimed initial tokens"); - - hasClaimed = onboardingUtils.hasUserClaimedInitial(user2); - console2.log("User2 has claimed initial tokens:", hasClaimed); - assertTrue(hasClaimed, "User2 should have claimed initial tokens"); - - uint256 referralCount = onboardingUtils.getReferralCount(user1); - console2.log("User1's referral count:", referralCount); - assertEq(referralCount, 1, "User1 should have 1 referral"); - } -}