diff --git a/script/DeployTokenizer.s.sol b/script/DeployTokenizer.s.sol index 99645336..2469ea56 100644 --- a/script/DeployTokenizer.s.sol +++ b/script/DeployTokenizer.s.sol @@ -11,6 +11,7 @@ import { BioPriceFeed } from "../src/BioPriceFeed.sol"; import { IPermissioner, TermsAcceptedPermissioner } from "../src/Permissioner.sol"; import { CrowdSale } from "../src/crowdsale/CrowdSale.sol"; import { StakedLockingCrowdSale } from "../src/crowdsale/StakedLockingCrowdSale.sol"; +import { TimelockedToken } from "../src/TimelockedToken.sol"; contract DeployTokenizerInfrastructure is Script { function run() public { @@ -27,13 +28,16 @@ contract DeployTokenizerInfrastructure is Script { tokenizer.setIPTokenImplementation(initialIpTokenImplementation); CrowdSale crowdSale = new CrowdSale(); - StakedLockingCrowdSale stakedLockingCrowdSale = new StakedLockingCrowdSale(); + //this allows the default TimelockedToken implementation to be verified on chain explorers + TimelockedToken timelockedTokenImplementation = new TimelockedToken(); + StakedLockingCrowdSale stakedLockingCrowdSale = new StakedLockingCrowdSale(timelockedTokenImplementation); vm.stopBroadcast(); console.log("TERMS_ACCEPTED_PERMISSIONER_ADDRESS=%s", address(permissioner)); console.log("TOKENIZER_ADDRESS=%s", address(tokenizer)); console.log("CROWDSALE_ADDRESS=%s", address(crowdSale)); console.log("STAKED_LOCKING_CROWDSALE_ADDRESS=%s", address(stakedLockingCrowdSale)); + console.log("timelocked token implementation=%s", address(timelockedTokenImplementation)); console.log("initial IP Token implementation=%s", address(initialIpTokenImplementation)); } } diff --git a/script/dev/CrowdSale.s.sol b/script/dev/CrowdSale.s.sol index 4a88b13e..622b1618 100644 --- a/script/dev/CrowdSale.s.sol +++ b/script/dev/CrowdSale.s.sol @@ -31,16 +31,13 @@ contract DeployCrowdSale is CommonScript { } } -/** - * @title deploy crowdSale - * @author - */ contract DeployStakedCrowdSale is CommonScript { function run() public { prepareAddresses(); vm.startBroadcast(deployer); - StakedLockingCrowdSale stakedLockingCrowdSale = new StakedLockingCrowdSale(); - + TimelockedToken lockingCrowdsaleImplementation = new TimelockedToken(); + StakedLockingCrowdSale stakedLockingCrowdSale = new StakedLockingCrowdSale(lockingCrowdsaleImplementation); + TokenVesting vestedDaoToken = TokenVesting(vm.envAddress("VDAO_TOKEN_ADDRESS")); vestedDaoToken.grantRole(vestedDaoToken.ROLE_CREATE_SCHEDULE(), address(stakedLockingCrowdSale)); stakedLockingCrowdSale.trustVestingContract(vestedDaoToken); diff --git a/script/prod/RolloutV23Sale.sol b/script/prod/RolloutV25Sale.sol similarity index 76% rename from script/prod/RolloutV23Sale.sol rename to script/prod/RolloutV25Sale.sol index 8e4b4403..3da957e3 100644 --- a/script/prod/RolloutV23Sale.sol +++ b/script/prod/RolloutV25Sale.sol @@ -7,17 +7,20 @@ import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy import { IPNFT } from "../../src/IPNFT.sol"; import { IPermissioner, TermsAcceptedPermissioner } from "../../src/Permissioner.sol"; import { StakedLockingCrowdSale } from "../../src/crowdsale/StakedLockingCrowdSale.sol"; +import { TimelockedToken } from "../../src/TimelockedToken.sol"; -contract RolloutV23Sale is Script { +contract RolloutV25Sale is Script { function run() public { address moleculeDevMultisig = 0xCfA0F84660fB33bFd07C369E5491Ab02C449f71B; vm.startBroadcast(); - StakedLockingCrowdSale stakedLockingCrowdSale = new StakedLockingCrowdSale(); + TimelockedToken timelockedTokenImplementation = new TimelockedToken(); + StakedLockingCrowdSale stakedLockingCrowdSale = new StakedLockingCrowdSale(timelockedTokenImplementation); stakedLockingCrowdSale.transferOwnership(moleculeDevMultisig); vm.stopBroadcast(); console.log("STAKED_LOCKING_CROWDSALE_ADDRESS=%s", address(stakedLockingCrowdSale)); + console.log("timelocked token implementation=%s", address(timelockedTokenImplementation)); // 0x7c36c64DA1c3a2065074caa9C48e7648FB733aAB // vestedDaoToken.grantRole(vestedDaoToken.ROLE_CREATE_SCHEDULE(), address(stakedLockingCrowdSale)); // stakedLockingCrowdSale.trustVestingContract(vestedDaoToken); diff --git a/test/CrowdSaleLockedStakedTest.t.sol b/test/CrowdSaleLockedStakedTest.t.sol index 250128c8..e53fc6f4 100644 --- a/test/CrowdSaleLockedStakedTest.t.sol +++ b/test/CrowdSaleLockedStakedTest.t.sol @@ -55,8 +55,9 @@ contract CrowdSaleLockedStakedTest is Test { // // 1=1 is the trivial case // priceFeed.signal(address(biddingToken), address(daoToken), 1e18); - crowdSale = new StakedLockingCrowdSale(); - + TimelockedToken timelockedTokenImplementation = new TimelockedToken(); + crowdSale = new StakedLockingCrowdSale(timelockedTokenImplementation); + vestedDao = new TokenVesting( daoToken, string(abi.encodePacked("Vested ", daoToken.name())), @@ -92,13 +93,13 @@ contract CrowdSaleLockedStakedTest is Test { auctionToken.approve(address(crowdSale), 400_000 ether); vm.expectRevert(); //cannot call .decimals() on 0x0 - crowdSale.startSale(_sale, IERC20Metadata(address(0)), TokenVesting(address(0)), 0, 60 days); + crowdSale.startSale(_sale, IERC20Metadata(address(0)), TokenVesting(address(0)), 0, 3 days, 7 days); vm.expectRevert(); //need to bring a stake vesting contract - crowdSale.startSale(_sale, daoToken, TokenVesting(address(0)), 0, 60 days); + crowdSale.startSale(_sale, daoToken, TokenVesting(address(0)), 0, 3 days, 7 days); vm.expectRevert(UnsupportedVestingContract.selector); - crowdSale.startSale(_sale, daoToken, wrongStakeVestingContract, 0, 60 days); + crowdSale.startSale(_sale, daoToken, wrongStakeVestingContract, 0, 3 days, 7 days); vm.stopPrank(); vm.startPrank(deployer); @@ -111,12 +112,15 @@ contract CrowdSaleLockedStakedTest is Test { vm.startPrank(emitter); vm.expectRevert(IncompatibleVestingContract.selector); - crowdSale.startSale(_sale, daoToken, wrongStakeVestingContract, 0, 60 days); + crowdSale.startSale(_sale, daoToken, wrongStakeVestingContract, 0, 3 days, 7 days); vm.expectRevert(BadPrice.selector); - crowdSale.startSale(_sale, daoToken, vestedDao, 0, 60 days); + crowdSale.startSale(_sale, daoToken, vestedDao, 0, 3 days, 7 days); - crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 60 days); + vm.expectRevert(InvalidDuration.selector); + crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 3 days, 6 days); + + crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 3 days, 7 days); } function testCannotSetupCrowdSaleWithParentFunctions() public { @@ -137,7 +141,7 @@ contract CrowdSaleLockedStakedTest is Test { Sale memory _sale = CrowdSaleHelpers.makeSale(emitter, auctionToken, biddingToken); auctionToken.approve(address(crowdSale), 400_000 ether); - uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 60 days); + uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 60 days, 60 days); vm.stopPrank(); @@ -174,7 +178,7 @@ contract CrowdSaleLockedStakedTest is Test { vm.startPrank(emitter); Sale memory _sale = CrowdSaleHelpers.makeSale(emitter, auctionToken, biddingToken); auctionToken.approve(address(crowdSale), 400_000 ether); - uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 60 days); + uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 60 days, 60 days); vm.stopPrank(); @@ -287,7 +291,7 @@ contract CrowdSaleLockedStakedTest is Test { Sale memory _sale = CrowdSaleHelpers.makeSale(emitter, auctionToken, biddingToken); auctionToken.approve(address(crowdSale), 400_000 ether); // 1 DAO = 4 $ - uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 25e16, 60 days); + uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 25e16, 60 days, 60 days); vm.stopPrank(); @@ -348,7 +352,7 @@ contract CrowdSaleLockedStakedTest is Test { Sale memory _sale = CrowdSaleHelpers.makeSale(emitter, auctionToken, biddingToken); auctionToken.approve(address(crowdSale), 400_000 ether); - uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 25e16, 60 days); + uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 25e16, 60 days, 60 days); vm.stopPrank(); vm.startPrank(bidder); @@ -393,7 +397,11 @@ contract CrowdSaleLockedStakedTest is Test { Sale memory _sale = CrowdSaleHelpers.makeSale(emitter, auctionToken, biddingToken); _sale.closingTime = uint64(block.timestamp + 3 days); auctionToken.approve(address(crowdSale), 400_000 ether); - uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 3 days); + + vm.expectRevert(InvalidDuration.selector); + uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 3 days, 3 days); + + saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 3 days, 7 days); vm.stopPrank(); diff --git a/test/CrowdSaleLockedTest.t.sol b/test/CrowdSaleLockedTest.t.sol index 0207ea9f..59db14ec 100644 --- a/test/CrowdSaleLockedTest.t.sol +++ b/test/CrowdSaleLockedTest.t.sol @@ -25,7 +25,9 @@ contract CrowdSaleLockedTest is Test { LockingCrowdSale internal crowdSale; function setUp() public { - crowdSale = new LockingCrowdSale(); + TimelockedToken timelockedTokenImplementation = new TimelockedToken(); + crowdSale = new LockingCrowdSale(timelockedTokenImplementation); + auctionToken = new FakeERC20("IPTOKENS","IPT"); biddingToken = new FakeERC20("USD token", "USDC"); diff --git a/test/CrowdSalePermissioned.t.sol b/test/CrowdSalePermissioned.t.sol index 86fb14b0..84c2ac6e 100644 --- a/test/CrowdSalePermissioned.t.sol +++ b/test/CrowdSalePermissioned.t.sol @@ -66,7 +66,8 @@ contract CrowdSalePermissionedTest is Test { biddingToken = new FakeERC20("USD token", "USDC"); daoToken = new FakeERC20("DAO token", "DAO"); - crowdSale = new StakedLockingCrowdSale(); + TimelockedToken timelockedTokenImplementation = new TimelockedToken(); + crowdSale = new StakedLockingCrowdSale(timelockedTokenImplementation); vestedDao = new TokenVesting(daoToken, string(abi.encodePacked("Vested ", daoToken.name())), string(abi.encodePacked("v", daoToken.symbol()))); vestedDao.grantRole(vestedDao.ROLE_CREATE_SCHEDULE(), address(crowdSale)); @@ -103,7 +104,7 @@ contract CrowdSalePermissionedTest is Test { _sale.permissioner = permissioner; auctionToken.approve(address(crowdSale), 400_000 ether); - uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 60 days); + uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 60 days, 60 days); vm.stopPrank(); string memory terms = permissioner.specificTermsV1(auctionToken); diff --git a/test/CrowdSaleWithNonStandardERC20Test.t.sol b/test/CrowdSaleWithNonStandardERC20Test.t.sol index 0d6873dd..331297fe 100644 --- a/test/CrowdSaleWithNonStandardERC20Test.t.sol +++ b/test/CrowdSaleWithNonStandardERC20Test.t.sol @@ -50,7 +50,8 @@ contract CrowdSaleWithNonStandardERC20Test is Test { // // 1=1 is the trivial case // priceFeed.signal(address(biddingToken), address(daoToken), 1e18); - crowdSale = new StakedLockingCrowdSale(); + TimelockedToken timelockedTokenImplementation = new TimelockedToken(); + crowdSale = new StakedLockingCrowdSale(timelockedTokenImplementation); auctionToken.mint(emitter, 500_000 ether); @@ -83,7 +84,7 @@ contract CrowdSaleWithNonStandardERC20Test is Test { Sale memory _sale = CrowdSaleHelpers.makeSale(emitter, auctionToken, biddingToken); _sale.fundingGoal = 200_000e6; auctionToken.approve(address(crowdSale), 400_000 ether); - uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 60 days); + uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 60 days, 60 days); vm.stopPrank(); vm.startPrank(bidder); @@ -121,7 +122,7 @@ contract CrowdSaleWithNonStandardERC20Test is Test { Sale memory _sale = CrowdSaleHelpers.makeSale(emitter, auctionToken, biddingToken); _sale.fundingGoal = 200_000e6; auctionToken.approve(address(crowdSale), 400_000 ether); - uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 60 days); + uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 1e18, 60 days, 60 days); vm.stopPrank(); @@ -179,7 +180,7 @@ contract CrowdSaleWithNonStandardERC20Test is Test { _sale.fundingGoal = 200_000e6; auctionToken.approve(address(crowdSale), 400_000 ether); // 1 DAO = 4 $ <=> 1$ = 0.25 DAO, the price is always expressed as 1e18 decimal - uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 25e16, 60 days); + uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 25e16, 60 days, 60 days); vm.stopPrank(); vm.startPrank(bidder); @@ -241,7 +242,7 @@ contract CrowdSaleWithNonStandardERC20Test is Test { _sale.fundingGoal = 200_000e6; auctionToken.approve(address(crowdSale), 400_000 ether); //0.25 DAO (18dec) / USDC (6dec) - uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 25e16, 60 days); + uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 25e16, 60 days, 60 days); vm.stopPrank(); @@ -306,7 +307,7 @@ contract CrowdSaleWithNonStandardERC20Test is Test { Sale memory _sale = CrowdSaleHelpers.makeSale(emitter, auctionToken, biddingToken); _sale.fundingGoal = 50_000e2; auctionToken.approve(address(crowdSale), 400_000 ether); - uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 4e18, 7 days); + uint256 saleId = crowdSale.startSale(_sale, daoToken, vestedDao, 4e18, 7 days, 7 days); vm.stopPrank(); vm.startPrank(bidder);