Skip to content

Commit

Permalink
full mainnet fork test case for new Tokenizer
Browse files Browse the repository at this point in the history
Signed-off-by: stadolf <[email protected]>
  • Loading branch information
elmariachi111 committed Jul 5, 2024
1 parent 16a696b commit 653474a
Showing 1 changed file with 144 additions and 37 deletions.
181 changes: 144 additions & 37 deletions test/Forking/Tokenizer13UpgradeForkTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,16 @@ pragma solidity ^0.8.18;
import "forge-std/Test.sol";
import { console } from "forge-std/console.sol";

//import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";

import { IPNFT } from "../../src/IPNFT.sol";

import { MustOwnIpnft, AlreadyTokenized, Tokenizer } from "../../src/Tokenizer.sol";
import { Tokenizer12 } from "../../src/helpers/test-upgrades/Tokenizer12.sol";
import { IPToken12, OnlyIssuerOrOwner } from "../../src/helpers/test-upgrades/IPToken12.sol";
import { IPToken, TokenCapped, Metadata } from "../../src/IPToken.sol";
import { IPermissioner, BlindPermissioner } from "../../src/Permissioner.sol";

// an error thrown by IPToken before 1.3
//error OnlyIssuerOrOwner();

contract Tokenizer13UpgradeForkTest is Test {
using SafeERC20Upgradeable for IPToken;

Expand All @@ -32,71 +29,93 @@ contract Tokenizer13UpgradeForkTest is Test {
address mainnetTokenizer = 0x58EB89C69CB389DBef0c130C6296ee271b82f436;
address mainnetIPNFT = 0xcaD88677CA87a7815728C72D74B4ff4982d54Fc1;

// old IP Token implementation
address vitaFASTAddress = 0x6034e0d6999741f07cb6Fb1162cBAA46a1D33d36;

// https://app.safe.global/home?safe=eth:0xf7990CD398daFB4fe5Fd6B9228B8e6f72b296555
address vitaFASTMultisig = 0xf7990CD398daFB4fe5Fd6B9228B8e6f72b296555;
address vitaDaoTreasury = 0xF5307a74d1550739ef81c6488DC5C7a6a53e5Ac2;

// paulhaas.eth
address paulhaas = 0x45602BFBA960277bF917C1b2007D1f03d7bd29e4;

// ValleyDAO multisig
address valleyDaoMultisig = 0xD920E60b798A2F5a8332799d8a23075c9E77d5F8;

// ValleyDAO IPNFT
uint256 valleyDaoIpnftId = 3;
IPNFT ipnft = IPNFT(mainnetIPNFT);
Tokenizer tokenizer13;
IPToken newIPTokenImplementation;

address alice = makeAddr("alice");

function setUp() public {
mainnetFork = vm.createFork(vm.envString("MAINNET_RPC_URL"), 18968463);
mainnetFork = vm.createFork(vm.envString("MAINNET_RPC_URL"), 20240430);
vm.selectFork(mainnetFork);
}

function testCanUpgradeToV13() public {
IPNFT ipnftMainnetInstance = IPNFT(mainnetIPNFT);
Tokenizer12 tokenizer12 = Tokenizer12(mainnetTokenizer);

function upgradeToTokenizer13() public {
vm.startPrank(mainnetDeployer);
Tokenizer newTokenizerImplementation = new Tokenizer();
IPToken newIPTokenImplementation = new IPToken();
newIPTokenImplementation = new IPToken();
vm.stopPrank();

vm.startPrank(mainnetOwner);
bytes memory upgradeCallData = abi.encodeWithSelector(Tokenizer.reinit.selector, address(newIPTokenImplementation));
Tokenizer12 tokenizer12 = Tokenizer12(mainnetTokenizer);
//todo: make sure that the legacy IPTs are indexed now
bytes memory upgradeCallData = abi.encodeWithSelector(Tokenizer.reinit.selector, address(newIPTokenImplementation));
tokenizer12.upgradeToAndCall(address(newTokenizerImplementation), upgradeCallData);
Tokenizer upgradedTokenizer = Tokenizer(mainnetTokenizer);

assertEq(address(upgradedTokenizer.ipTokenImplementation()), address(newIPTokenImplementation));
tokenizer13 = Tokenizer(mainnetTokenizer);
}

deployCodeTo("Permissioner.sol:BlindPermissioner", "", address(upgradedTokenizer.permissioner()));
vm.stopPrank();
function testCanUpgradeToV13() public {
upgradeToTokenizer13();
assertEq(address(tokenizer13.ipTokenImplementation()), address(newIPTokenImplementation));
assertEq(address(tokenizer13.permissioner()), 0xC837E02982992B701A1B5e4E21fA01cEB0a628fA);

vm.startPrank(alice);
vm.expectRevert("Initializable: contract is already initialized");
newTokenizerImplementation.initialize(IPNFT(address(0)), BlindPermissioner(address(0)));
tokenizer13.initialize(IPNFT(address(0)), BlindPermissioner(address(0)));

vm.expectRevert("Initializable: contract is already initialized");
newIPTokenImplementation.initialize(2, "Foo", "Bar", alice, "abcde");
vm.stopPrank();

vm.startPrank(mainnetOwner);
vm.expectRevert("Initializable: contract is already initialized");
upgradedTokenizer.initialize(IPNFT(address(0)), BlindPermissioner(address(0)));
tokenizer13.initialize(IPNFT(address(0)), BlindPermissioner(address(0)));

vm.expectRevert("Initializable: contract is already initialized");
upgradedTokenizer.reinit(IPToken(address(0)));
vm.stopPrank();
tokenizer13.reinit(newIPTokenImplementation);
}

function testOldIPTsAreMigratedAndCantBeReminted() public {
upgradeToTokenizer13();

assertEq(address(tokenizer13.synthesized(2)), 0x6034e0d6999741f07cb6Fb1162cBAA46a1D33d36);
assertEq(address(tokenizer13.synthesized(28)), 0x7b66E84Be78772a3afAF5ba8c1993a1B5D05F9C2);
assertEq(address(tokenizer13.synthesized(37)), 0xBcE56276591128047313e64744b3EBE03998783f);
assertEq(address(tokenizer13.synthesized(31415269)), address(0));

deployCodeTo("Permissioner.sol:BlindPermissioner", "", address(tokenizer13.permissioner()));

address vitaFASTMultisig = 0xf7990CD398daFB4fe5Fd6B9228B8e6f72b296555;

assertEq(ipnftMainnetInstance.ownerOf(valleyDaoIpnftId), valleyDaoMultisig);
vm.startPrank(vitaFASTMultisig);
vm.expectRevert(AlreadyTokenized.selector);
tokenizer13.tokenizeIpnft(2, 1_000_000 ether, "VITA-FAST", "bafkreig274nfj7srmtnb5wd5wlwm3ig2s63wovlz7i3noodjlfz2tm3n5q", bytes(""));

vm.startPrank(alice);
vm.expectRevert(MustOwnIpnft.selector);
tokenizer13.tokenizeIpnft(2, 1_000_000 ether, "VITA-FAST", "bafkreig274nfj7srmtnb5wd5wlwm3ig2s63wovlz7i3noodjlfz2tm3n5q", bytes(""));
}

function testTokenizeNewIPTs() public {
upgradeToTokenizer13();
address valleyDaoMultisig = 0xD920E60b798A2F5a8332799d8a23075c9E77d5F8;
uint256 valleyDaoIpnftId = 3; //hasnt been tokenized yet
deployCodeTo("Permissioner.sol:BlindPermissioner", "", address(tokenizer13.permissioner()));

assertEq(ipnft.ownerOf(valleyDaoIpnftId), valleyDaoMultisig);

vm.startPrank(valleyDaoMultisig);
IPToken ipt = upgradedTokenizer.tokenizeIpnft(valleyDaoIpnftId, 1_000_000 ether, "IPT", agreementCid, "");
IPToken ipt = tokenizer13.tokenizeIpnft(valleyDaoIpnftId, 1_000_000 ether, "VALLEY", agreementCid, "");
assertEq(ipt.balanceOf(valleyDaoMultisig), 1_000_000 ether);
ipt.transfer(alice, 100_000 ether);

assertEq(ipt.balanceOf(valleyDaoMultisig), 900_000 ether);
assertEq(ipt.balanceOf(alice), 100_000 ether);

//controlling the IPT from its own interface
ipt.issue(valleyDaoMultisig, 1_000_000 ether);
assertEq(ipt.totalSupply(), 2_000_000 ether);
assertEq(ipt.balanceOf(valleyDaoMultisig), 1_900_000 ether);
Expand All @@ -107,6 +126,12 @@ contract Tokenizer13UpgradeForkTest is Test {
ipt.issue(valleyDaoMultisig, 100);

vm.stopPrank();
}

function testOldTokensAreStillControllable() public {
upgradeToTokenizer13();
address vitaFASTAddress = 0x6034e0d6999741f07cb6Fb1162cBAA46a1D33d36;
address vitaFASTMultisig = 0xf7990CD398daFB4fe5Fd6B9228B8e6f72b296555;

IPToken vitaFast = IPToken(vitaFASTAddress);

Expand All @@ -120,12 +145,94 @@ contract Tokenizer13UpgradeForkTest is Test {
vm.stopPrank();

vm.startPrank(vitaFASTMultisig);
assertEq(vitaFast.balanceOf(vitaFASTMultisig), 16940676213630533216614);
assertEq(vitaFast.totalSupply(), 1_029_555 ether);
assertEq(vitaFast.balanceOf(vitaFASTMultisig), 13390539642731621592709);
//the old IPTs allow their original owner to issue more tokens
vitaFast.issue(vitaFASTMultisig, 100_000 ether);
assertEq(vitaFast.totalSupply(), 1129555 ether);
assertEq(vitaFast.balanceOf(vitaFASTMultisig), 116940676213630533216614);
assertEq(vitaFast.totalSupply(), 1_129_555 ether);
assertEq(vitaFast.balanceOf(vitaFASTMultisig), 113390539642731621592709);

vitaFast.cap();
vm.expectRevert(TokenCapped.selector);
vitaFast.issue(vitaFASTMultisig, 100_000 ether);

/// --- same for VitaRNA, better safe than sorry.
address vitaRNAAddress = 0x7b66E84Be78772a3afAF5ba8c1993a1B5D05F9C2;
address vitaRNAMultisig = 0x452f3b60129FdB3cdc78178848c63eC23f38C80d;
IPToken vitaRna = IPToken(vitaRNAAddress);

assertEq(vitaRna.balanceOf(paulhaas), 514.411456805927582924 ether);
assertEq(vitaRna.balanceOf(alice), 0);

vm.startPrank(paulhaas);
vitaRna.transfer(alice, 100 ether);
assertEq(vitaRna.balanceOf(paulhaas), 414.411456805927582924 ether);
assertEq(vitaRna.balanceOf(alice), 100 ether);
vm.stopPrank();

vm.startPrank(vitaRNAMultisig);
assertEq(vitaRna.totalSupply(), 5_000_000 ether);
assertEq(vitaRna.balanceOf(vitaRNAMultisig), 200_000 ether);
vitaRna.issue(vitaRNAMultisig, 100_000 ether);
assertEq(vitaRna.totalSupply(), 5_100_000 ether);
assertEq(vitaRna.balanceOf(vitaRNAMultisig), 300_000 ether);

vitaRna.cap();
vm.expectRevert(TokenCapped.selector);
vitaRna.issue(vitaRNAMultisig, 100_000 ether);
}

// IPN-21: and the main reason why we're doing all the above
function testOldTokensCanBeIssuedByNewIPNFTHolder() public {
upgradeToTokenizer13();

deployCodeTo("Permissioner.sol:BlindPermissioner", "", address(tokenizer13.permissioner()));

address bob = makeAddr("bob");
address vitaFASTMultisig = 0xf7990CD398daFB4fe5Fd6B9228B8e6f72b296555;
//we're using vita fast's original abi here. It actually is call-compatible to IPToken, but this is the ultimate legacy test
IPToken12 vitaFAST12 = IPToken12(0x6034e0d6999741f07cb6Fb1162cBAA46a1D33d36);
IPToken vitaFAST13 = IPToken(0x6034e0d6999741f07cb6Fb1162cBAA46a1D33d36);

vm.startPrank(vitaFASTMultisig);
ipnft.transferFrom(vitaFASTMultisig, alice, 2);
assertEq(ipnft.ownerOf(2), alice);

vm.startPrank(alice);
// This is new: originally Alice *would* indeed have been able to do this:
vm.expectRevert(AlreadyTokenized.selector);
tokenizer13.tokenizeIpnft(2, 1_000_000 ether, "VITA-FAST", "imfeelingfunny", bytes(""));

assertEq(vitaFAST12.balanceOf(alice), 0);

//this *should* be possible but can't work due to the old implementation
vm.expectRevert(OnlyIssuerOrOwner.selector);
vitaFAST12.issue(alice, 1_000_000 ether);
//the selector of course doesnt exist on the new interface, but the implementation reverts with it:
vm.expectRevert(OnlyIssuerOrOwner.selector);
vitaFAST13.issue(alice, 1_000_000 ether);

//to issue new tokens, alice uses the Tokenizer instead:
tokenizer13.issue(vitaFAST13, 1_000_000 ether, alice);
assertEq(vitaFAST12.balanceOf(alice), 1_000_000 ether);

//due to the original implementation, the original owner can still issue tokens and we cannot do anything about it:
vm.startPrank(vitaFASTMultisig);
vitaFAST12.issue(bob, 1_000_000 ether);
assertEq(vitaFAST12.balanceOf(bob), 1_000_000 ether);
assertEq(vitaFAST13.balanceOf(bob), 1_000_000 ether);

// but they cannot do that using the tokenizer:
vm.expectRevert(MustOwnIpnft.selector);
tokenizer13.issue(vitaFAST13, 1_000_000 ether, alice);
vm.expectRevert(MustOwnIpnft.selector);
tokenizer13.cap(vitaFAST13);

//but they unfortunately also can cap the token:
vitaFAST12.cap();

vm.startPrank(alice);
vm.expectRevert(TokenCapped.selector);
tokenizer13.issue(vitaFAST13, 1_000_000 ether, alice);
}
}

0 comments on commit 653474a

Please sign in to comment.